Example #1
0
static void server_socket_tx_map_updates (void)
{
    {
        static uint32_t ts;

        if (time_have_x_hundredths_passed_since(
                DELAY_HUNDREDTHS_SERVER_TO_CLIENT_MAP_UPDATE_FAST, ts)) {

            ts = time_get_time_ms();

            socket_server_tx_map_update(0, server_active_things,
                                        "rx client join active things");
        }
    }

    {
        static uint32_t ts;

        if (time_have_x_hundredths_passed_since(
                DELAY_HUNDREDTHS_SERVER_TO_CLIENT_MAP_UPDATE_SLOW, ts)) {
            socket_server_tx_map_update(0, server_boring_things,
                                        "rx client join boring things");
            ts = time_get_time_ms();
        }
    }
}
Example #2
0
static void server_socket_tx_ping (void)
{
    gsocketp s;

    TREE_WALK(sockets, s) {

        if (socket_get_client(s)) {
            continue;
        }

        /*
         * Don't ping thyself if both server and client.
         */
        if (socket_get_server(s)) {
            continue;
        }

        socket_tx_ping(s, &s->tx_ping_seq, time_get_time_ms());
    }

    static uint32_t ts;

    if (time_have_x_tenths_passed_since(10, ts)) {
        ts = time_get_time_ms();
        server_alive_check();
    }
}
static uint8_t wid_game_map_key_event (widp w, const SDL_KEYSYM *key)
{
    int action = PLAYER_ACTION_USE;
    int change_selection_only = false;

    if (wid_menu_visible) {
        return (false);
    }

    tpp tp;

    if (!player) {
        wid_player_info_hide(true /* fast */);
        wid_player_inventory_hide(true /* fast */);
        return (true);
    }

    int redraw_action_bar = 0;
    int action_bar_index = thing_stats_get_action_bar_index(player);

    if (key->mod & KMOD_SHIFT) {
        int weapon_switch_delta = 0;

        switch (key->sym) {
        case SDLK_LEFT:
            weapon_switch_delta = -1;
            break;
        case SDLK_RIGHT:
            weapon_switch_delta = 1;
            break;
        default:
            break;
        }

        /*
         * Weapon switch?
         */
        if (!weapon_switch_delta) {
            return (true);
        }

        /*
         * Only switch between weapons
         */
        int tries = THING_ACTION_BAR_MAX;

        while (tries-- > 0) {
            action_bar_index += weapon_switch_delta;
            if (action_bar_index < 0) {
                action_bar_index = THING_ACTION_BAR_MAX - 1;
            }

            if (action_bar_index >= THING_ACTION_BAR_MAX) {
                action_bar_index = 0;
            }

            uint32_t id = player->stats.action_bar[action_bar_index].id;
            if (!id) {
                continue;
            }

            tp = id_to_tp(id);
            if (!tp) {
                continue;
            }

            /*
             * Found a weapon, switch to it.
             */
            change_selection_only = true;
            break;
        }

        if (tries <= 0) {
            return (true);
        }

        redraw_action_bar = 1;
    } else {
        switch (key->sym) {
        case SDLK_1:
            action_bar_index = 0; 
            redraw_action_bar = 1;
            break;
        case SDLK_2:
            action_bar_index = 1; 
            redraw_action_bar = 1;
            break;
        case SDLK_3:
            action_bar_index = 2; 
            redraw_action_bar = 1;
            break;
        case SDLK_4:
            action_bar_index = 3; 
            redraw_action_bar = 1;
            break;
        case SDLK_5:
            action_bar_index = 4; 
            redraw_action_bar = 1;
            break;
        case SDLK_6:
            action_bar_index = 5; 
            redraw_action_bar = 1;
            break;
        case SDLK_7:
            action_bar_index = 6; 
            redraw_action_bar = 1;
            break;
        case SDLK_8:
            action_bar_index = 7; 
            redraw_action_bar = 1;
            break;
        case SDLK_9:
            action_bar_index = 8; 
            redraw_action_bar = 1;
            break;
        case SDLK_0:
            action_bar_index = 9; 
            redraw_action_bar = 1;
            break;
        case 'z':
            debug = !debug;
            CON("debug %d", debug);
            return (true);
        case 'd':
            action = PLAYER_ACTION_DROP;
            break;
        case 'p':
            action = PLAYER_ACTION_PAY;
            break;

        case '\t': {
            /*
             * Show the inventory.
             */
            thing_statsp s;

            s = &player->stats;

            if (!wid_player_info_is_visible()) {
                /*
                 * Show stats window.
                 */
                wid_player_stats_visible(s);
                wid_player_info_visible(s, false /* fast */);
                wid_player_inventory_visible(s, false /* fast */);

                socket_tx_player_action(client_joined_server, player, 
                                        PLAYER_ACTION_PAUSE_GAME,
                                        0 /* action_bar_index */,
                                        false /* change_selection_only */);
            } else {
                /*
                 * Hide stats window.
                 */
                wid_player_stats_hide(s);
                wid_player_info_hide(false /* fast */);
                wid_player_inventory_hide(false /* fast */);

                socket_tx_player_action(client_joined_server, player, 
                                        PLAYER_ACTION_RESUME_GAME,
                                        0 /* action_bar_index */,
                                        false /* change_selection_only */);
            }
            return (true);
        }
        case 's':
            wid_choose_stats_visible();

            socket_tx_player_action(client_joined_server, player, 
                                    PLAYER_ACTION_PAUSE_GAME,
                                    0 /* action_bar_index */,
                                    false /* change_selection_only */);
            return (true);

        case 'q':
            if (client_level->is_test_level) {
                wid_game_map_go_back_to_editor();
                return (true);
            }

            wid_game_quit_visible();
            return (true);

        case SDLK_RETURN:
        case ' ':
            return (false);

        default:
            return (false);
        }
    }

    uint32_t id = player->stats.action_bar[action_bar_index].id;
    if (!id) {
        MESG(WARNING, "Nothing in that slot");
        return (true);
    }

    tp = id_to_tp(id);
    if (!tp) {
        MESG(WARNING, "No carried item is using that key");
        return (true);
    }

    if (!client_joined_server) {
        MESG(WARNING, "Not connected to server");
        return (true);
    }

    if (redraw_action_bar) {
        /*
         * Assume the server will accept the change and update locally else it 
         * looks laggy.
         */
        player_action_bar_changed_at = time_get_time_ms();

        thing_stats_set_action_bar_index(player, action_bar_index);

        wid_player_action_hide(true /* fast */, false /* player quit */);
        wid_player_action_visible(&player->stats, true /* fast */);

        wid_player_stats_redraw(true /* fast */);
    }

    socket_tx_player_action(client_joined_server, player, 
                            action,
                            action_bar_index,
                            change_selection_only);

    return (true);
}
uint8_t wid_game_map_client_player_move (void)
{
    uint8_t right = 0;
    uint8_t left  = 0;
    uint8_t up    = 0;
    uint8_t down  = 0;
    uint8_t fire  = 0;
    uint8_t magic  = 0;

    if (!sdl_shift_held) {
#if SDL_MAJOR_VERSION == 1 && SDL_MINOR_VERSION == 2 /* { */
        {
            uint8_t *state = SDL_GetKeyState(0);

            right = state[SDLK_RIGHT] ? 1 : 0;
            left  = state[SDLK_LEFT] ? 1 : 0;
            up    = state[SDLK_UP] ? 1 : 0;
            down  = state[SDLK_DOWN] ? 1 : 0;
            fire  = state[SDLK_SPACE] ? 1 : 0;
            magic = state[SDLK_m] ? 1 : 0;
        }
#else /* } { */
        {
            const uint8_t *state = SDL_GetKeyboardState(0);

            right = state[SDL_SCANCODE_RIGHT] ? 1 : 0;
            left  = state[SDL_SCANCODE_LEFT] ? 1 : 0;
            up    = state[SDL_SCANCODE_UP] ? 1 : 0;
            down  = state[SDL_SCANCODE_DOWN] ? 1 : 0;
            fire  = state[SDL_SCANCODE_SPACE] ? 1 : 0;
            magic = state[SDL_SCANCODE_M] ? 1 : 0;
        }
#endif /* } */
    }

    if (sdl_joy_buttons[SDL_JOY_BUTTON_UP]) {
        up = true;
    }

    if (sdl_joy_buttons[SDL_JOY_BUTTON_DOWN]) {
        down = true;
    }

    if (sdl_joy_buttons[SDL_JOY_BUTTON_LEFT]) {
        left = true;
    }

    if (sdl_joy_buttons[SDL_JOY_BUTTON_RIGHT]) {
        right = true;
    }

    if (sdl_joy_buttons[SDL_JOY_BUTTON_LEFT_FIRE]) {
        fire = true;
    } else if (sdl_joy_buttons[SDL_JOY_BUTTON_RIGHT_FIRE]) {
        fire = true;
    } else if (sdl_joy_buttons[SDL_JOY_BUTTON_A]) {
        fire = true;
    } else if (sdl_joy_buttons[SDL_JOY_BUTTON_X]) {
        magic = true;
    }

    if (sdl_joy_axes) {
        if (sdl_joy_axes[3] > sdl_joy_deadzone) {
            right = true;
        }

        if (sdl_joy_axes[3] < -sdl_joy_deadzone) {
            left = true;
        }

        if (sdl_joy_axes[4] > sdl_joy_deadzone) {
            down = true;
        }

        if (sdl_joy_axes[4] < -sdl_joy_deadzone) {
            up = true;
        }

        if (wid_player_inventory_is_visible()) {
            wid_mouse_hide(1);
        } else {
            wid_mouse_hide(0);

            if (sdl_joy_axes[0] > sdl_joy_deadzone) {
                right = true;
            }

            if (sdl_joy_axes[0] < -sdl_joy_deadzone) {
                left = true;
            }

            if (sdl_joy_axes[1] > sdl_joy_deadzone) {
                down = true;
            }

            if (sdl_joy_axes[1] < -sdl_joy_deadzone) {
                up = true;
            }
        }
    }

    if (!player) {
        LOG("Client: No player, cannot move");
        return (false);
    }

    if (wid_menu_visible) {
        /*
         * Noisy
         *
        LOG("Menu present, ignore moves");
         */
        return (false);
    }

    if (!client_joined_server) {
        LOG("Client: Have not joined server, cannot move");
        return (false);
    }

    if (!up && !down && !left && !right && !fire && !magic) {
        return (false);
    }

    if (thing_is_dead_or_dying(player)) {
        return (true);
    }

    /*
     * If no longer visible it may mean we have finished the level and are 
     * waiting for others to finish.
     */
    if (!thing_is_visible(player)) {
        LOG("Client: Player is not visible, cannot move");
        return (false);
    }

    /*
     * Check if we are allowed to fire our gun again so soon.
     */
    if (fire) {
        tpp weapon = thing_weapon(player);

        if (!weapon) {
            THING_LOG(player, "tried to fire but no weapon");
            fire = 0;
        }

        if (fire) {
            static uint32_t last_fired = 0;

            uint32_t delay = tp_get_weapon_fire_delay_hundredths(weapon);
            
            if (tp_is_melee_weapon(weapon)) {
                if (thing_has_ability_double_speed_swing(player)) {
                    delay /= 2;
                } else if (thing_has_ability_triple_speed_swing(player)) {
                    delay /= 3;
                } else if (thing_has_ability_double_damage_swing(player)) {
                    delay = 0;
                }
            }

            if (!time_have_x_hundredths_passed_since(delay, last_fired)) {
                fire = 0;

                if (!up && !down && !left && !right && !magic) {
                    return (false);
                }
            }

            if (fire) {
                last_fired = time_get_time_ms();
            }
        }
    }

    /*
     * If not able to fire any more magic, stop.
     */
    if (!player->stats.magic) {
        magic = 0;
    }

    /*
     * Check we don't send magic events too often to the server.
     */
    if (magic) {
        static uint32_t last_fired = 0;

        if (!time_have_x_hundredths_passed_since(2, last_fired)) {
            magic = 0;

            if (!up && !down && !left && !right && !fire) {
                return (false);
            }
        }

        if (magic) {
            last_fired = time_get_time_ms();
        }
    }

    /*
     * Check for not moving too fast. Yep, this needs to be done on the
     * server. If the clients want to cheat, so be it!
     */
    static uint32_t last_moved = 0;

    double speed = thing_stats_get_total_speed(player);
    int delay = (60 - speed) / 2;
    if (delay < 0) {
        delay = 0;
    }

    if (!time_have_x_thousandths_passed_since(delay, last_moved)) {
        double x = player->x;
        double y = player->y;

        thing_client_move(player, x, y, false, false, false, false, 
                          fire, magic);
        return (false);
    }

    last_moved = time_get_time_ms();

    double x = player->x;
    double y = player->y;

    double delta = 0.10;

    x += (double)right * delta;
    x -= (double)left * delta;
    y -= (double)up * delta;
    y += (double)down * delta;

    thing_client_move(player, x, y, up, down, left, right, 
                      fire, magic);

    /*
     * If no key then we allow the console.
     */
    return (up || down || left || right || fire || magic);
}
Example #5
0
void thing_reached_teleport (levelp level,
                             thingp t, 
                             thingp teleport)
{
    int tx[MAP_WIDTH*MAP_HEIGHT];
    int ty[MAP_WIDTH*MAP_HEIGHT];
    int poss = 0;

    int x, y;

    int delay = 20;

    if (!thing_is_player(t)) {
        /*
         * Only move other things sometimes.
         */
        if ((myrand() % 100) < 95) {
            return;
        }
    }

    if (!time_have_x_tenths_passed_since(delay, 
                                         t->timestamp_last_teleport)) {
        return;
    }

    for (x = 0; x < MAP_WIDTH; x++) {
        for (y = 0; y < MAP_HEIGHT; y++) {

            level_map_tile *tile = 
                &level->map_grid.tile[x][y][MAP_DEPTH_EXPLOSION];

            tpp it = tile->tp;
            if (!it) {
                continue;
            }

            if (!tp_is_teleport(it)) {
                continue;
            }

            if (DISTANCE(t->x, t->y, x, y) < 2.0) {
                continue;
            }

            color tcol;
            color col;

            tcol = teleport->data.col;

            col = tile->data.col;

            if (color_none(col) || color_none(tcol)) {
                tx[poss] = x;
                ty[poss] = y;
                poss++;
                continue;
            }

            if (color_cmp(col, tcol)) {
                tx[poss] = x;
                ty[poss] = y;
                poss++;
                continue;
            }
        }
    }

    if (!poss) {
        return;
    }

    t->timestamp_last_teleport = time_get_time_ms();

    poss = myrand() % poss;

    double nx = tx[poss];
    double ny = ty[poss];

    /*
     * Don't let lava spawn continually on top of itself.
     */
    if (thing_is_lava(t) && map_is_lava_at(level, nx, ny)) {
        return;
    }

    /*
     * Don't let water spawn continually on top of itself.
     */
    if (thing_is_water(t) && map_is_water_at(level, nx, ny)) {
        return;
    }

    /*
     * Don't let acid spawn continually on top of itself.
     */
    if (thing_is_acid(t) && map_is_acid_at(level, nx, ny)) {
        return;
    }

    /*
     * Don't let water spawn continually on top of itself.
     */
    if (thing_is_water(t) && map_is_water_at(level, nx, ny)) {
        return;
    }

    /*
     * Don't let monsters spawn continually on top of themselves.
     */
    if (thing_is_monst(t) && map_is_monst_at(level, nx, ny)) {
        return;
    }

    THING_LOG(t, "Teleport");

    wid_move_end(t->wid);

    thing_wid_update(level,
                     t, nx, ny, 
                     false /* smooth */,
                     true /* is_new */);

    /*
     * Make sure the client sees the jump
     */
    thing_handle_collisions(level, t);

    MSG_SHOUT_AT(SOUND, t, t->x, t->y, "teleport");
}
Example #6
0
void thing_reached_teleport (thingp t, thingp teleport)
{
    int tx[MAP_WIDTH*MAP_HEIGHT];
    int ty[MAP_WIDTH*MAP_HEIGHT];
    int poss = 0;

    int x, y;

    int delay = 20;

    if (!thing_is_player(t)) {
        /*
         * Only move other things sometimes.
         */
        if ((myrand() % 100) < 95) {
            return;
        }
    }

    if (!time_have_x_tenths_passed_since(delay, 
                                         t->timestamp_last_teleport)) {
        return;
    }

    for (x = 0; x < MAP_WIDTH; x++) {
        for (y = 0; y < MAP_HEIGHT; y++) {

            level_map_tile *tile = 
                &server_level->map_grid.tile[x][y][MAP_DEPTH_EXPLOSION];

            tpp it = tile->tp;
            if (!it) {
                continue;
            }

            if (!tp_is_teleport(it)) {
                continue;
            }

            if (DISTANCE(t->x, t->y, x, y) < 2.0) {
                continue;
            }

            const char *tcol;
            const char *col;

            if (teleport->data) {
                tcol = teleport->data->col_name;
            } else {
                tcol = 0;
            }

            col = tile->data.col_name;

            if (!col || !tcol) {
                tx[poss] = x;
                ty[poss] = y;
                poss++;
                continue;
            }

            if (!strcmp(col, tcol)) {
                tx[poss] = x;
                ty[poss] = y;
                poss++;
                continue;
            }
        }
    }

    if (!poss) {
        return;
    }

    t->timestamp_last_teleport = time_get_time_ms();

    poss = myrand() % poss;

    double nx = tx[poss];
    double ny = ty[poss];

    /*
     * Don't let lava spawn continually on top of itself.
     */
    if (thing_is_lava(t) && map_is_lava_at(server_level, nx, ny)) {
        return;
    }

    /*
     * Don't let acid spawn continually on top of itself.
     */
    if (thing_is_acid(t) && map_is_acid_at(server_level, nx, ny)) {
        return;
    }

    /*
     * Don't let water spawn continually on top of itself.
     */
    if (thing_is_water(t) && map_is_water_at(server_level, nx, ny)) {
        return;
    }

    /*
     * Don't let monsters spawn continually on top of themselves.
     */
    if (thing_is_monst(t) && map_is_monst_at(server_level, nx, ny)) {
        return;
    }

    THING_LOG(t, "teleport");

    wid_move_end(t->wid);

    thing_server_wid_update(t, nx, ny, true /* is_new */);
    thing_update(t);

    /*
     * Make sure the client sees the jump
     */
    t->needs_tx_refresh_xy_and_template_id = 1;

    thing_handle_collisions(wid_game_map_server_grid_container, t);

    MSG_SERVER_SHOUT_AT_ALL_PLAYERS(SOUND, t->x, t->y, "teleport");
}
Example #7
0
/*
 * Blit the font to the screen
 */
void ttf_putc (font *f, int32_t c, double x, double y, double scaling)
{
    double texMinX = f->glyphs[c].texMinX;
    double texMaxX = f->glyphs[c].texMaxX;
    double texMinY = f->glyphs[c].texMinY;
    double texMaxY = f->glyphs[c].texMaxY;

    if (c == TTF_CURSOR_CHAR) {

        c = TTF_FIXED_WIDTH_CHAR;

        GLfloat left = (GLfloat)(x);
        GLfloat right = (GLfloat)(x + f->glyphs[c].width * scaling);
        GLfloat top = (GLfloat)(y);
        GLfloat bottom = (GLfloat)(y + f->glyphs[c].height * (scaling));

#ifdef CURSOR_FLASH
        static uint32_t last;
        static uint8_t first = true;

        glBindTexture(GL_TEXTURE_2D, 0);

        if (first) {
            first = false;
            last = time_get_time_ms();
        }

        glcolor_save();

        if (time_have_x_tenths_passed_since(10, last)) {
            glcolor(CONSOLE_CURSOR_COLOR);
            last = time_get_time_ms();
        } else if (time_have_x_tenths_passed_since(5, last)) {
            glcolor(CONSOLE_CURSOR_COLOR);
        } else {
            glcolor(CONSOLE_CURSOR_OTHER_COLOR);

            gl_blitsquare(left, top, right, bottom);

            left += 1;
            right -= 1;
            top += 1;
            bottom -= 1;

            gl_blitquad(left, top, right, bottom);

            glcolor_restore();
            return;
        }

        gl_blitquad(left, top, right, bottom);

        glcolor(BLACK);

        left += 1;
        right -= 1;
        top += 1;
        bottom -= 1;

        gl_blitquad(left, top, right, bottom);

        glcolor_restore();
        return;
#else
        glBindTexture(GL_TEXTURE_2D, 0);

        {
            color c = CONSOLE_CURSOR_COLOR;

            c.a = 200;

            glcolor(c);

            gl_blitsquare(left, top, right, bottom);

            glcolor_restore();
            return;
        }
#endif
    }

    GLfloat left = (GLfloat)(x);
    GLfloat right = (GLfloat)(x + f->glyphs[c].width * scaling);
    GLfloat top = (GLfloat)(y);
    GLfloat bottom = (GLfloat)(y + f->glyphs[c].height * (scaling));

    blit(f->tex[c].tex,
         texMinX, texMinY, texMaxX, texMaxY, left, top, right, bottom);
}