コード例 #1
0
ファイル: object.c プロジェクト: acasaccia/openomf
/*
 * Unserializes the data from buffer to a specialized object.
 * Should return 1 on error, 0 on success.
 * Serial reder position should be set to correct position before calling this.
 */
int object_unserialize(object *obj, serial *ser, game_state *gs) {
    obj->pos.x = serial_read_float(ser);
    obj->pos.y = serial_read_float(ser);
    obj->vel.x = serial_read_float(ser);
    obj->vel.y = serial_read_float(ser);
    float gravity = serial_read_float(ser);
    obj->direction = serial_read_int8(ser);
    obj->group = serial_read_int8(ser);
    obj->layers = serial_read_int8(ser);
    uint8_t stride = serial_read_int8(ser);
    uint8_t repeat = serial_read_int8(ser);
    obj->sprite_override = serial_read_int8(ser);
    obj->age = serial_read_int32(ser);
    random_seed(&obj->rand_state, serial_read_int32(ser));
    uint8_t animation_id = serial_read_int8(ser);
    uint8_t pal_offset = serial_read_int8(ser);
    int8_t hit_frames = serial_read_int8(ser);
    int8_t can_hit = serial_read_int8(ser);

    // Other stuff not included in serialization
    obj->y_percent = 1.0;
    obj->cur_animation_own = OWNER_EXTERNAL;
    obj->cur_animation = NULL;
    obj->cur_sprite = NULL;
    obj->sound_translation_table = NULL;
    obj->cur_surface = NULL;
    obj->cur_remap = 0;
    obj->halt = 0;
    obj->halt_ticks = 0;
    obj->cast_shadow = 0;
    player_create(obj);

    // Read animation state
    uint16_t anim_str_len = serial_read_int16(ser);
    char anim_str[anim_str_len+1];
    if(anim_str_len > 0) {
        serial_read(ser, anim_str, anim_str_len);
    }
    obj->animation_state.current_tick = (uint16_t)serial_read_int16(ser);
    obj->animation_state.previous_tick = (uint16_t)serial_read_int16(ser);
    uint8_t reverse = serial_read_int8(ser);

    // Read the specialization ID from ther serial "stream".
    // This should be an int.
    int specialization_id = serial_read_int8(ser);

    // This should automatically bootstrap the object so that it has at least
    // unserialize function callback and local memory allocated
    object_auto_specialize(obj, specialization_id);

    // Now, if the object has unserialize function, call it with
    // serialization data. serial object should be pointing to the
    // start of that data.
    if(obj->unserialize != NULL) {
        obj->unserialize(obj, ser, animation_id, gs);
    } else {
        DEBUG("object has no special unserializer");
    }

    // Init animation with correct string and tick
    if(anim_str_len > 0) {
        // server is using a custom string
        DEBUG("serialized object has custom animation string %s", anim_str);
        player_reload_with_str(obj, anim_str);
    }
    if(reverse) {
        object_set_playback_direction(obj, PLAY_BACKWARDS);
    }

    // deserializing hars can reset these, so we have to set this late
    obj->stride = stride;
    object_set_gravity(obj, gravity);
    object_set_repeat(obj, repeat);
    object_set_pal_offset(obj, pal_offset);
    obj->hit_frames = hit_frames;
    obj->can_hit = can_hit;

    /*DEBUG("Animation state: [%d] %s, ticks = %d stride = %d direction = %d pos = %f,%f vel = %f,%f gravity = %f", strlen(player_get_str(obj))+1, player_get_str(obj), obj->animation_state.ticks, obj->stride, obj->animation_state.reverse, obj->pos.x, obj->pos.y, obj->vel.x, obj->vel.y, obj->gravity);*/

    // Return success
    return 0;
}
コード例 #2
0
ファイル: net_controller.c プロジェクト: gdeda/openomf
int net_controller_tick(controller *ctrl, int ticks, ctrl_event **ev) {
    ENetEvent event;
    wtf *data = ctrl->data;
    ENetHost *host = data->host;
    ENetPeer *peer = data->peer;
    serial *ser;
    /*int handled = 0;*/
    while (enet_host_service(host, &event, 0) > 0) {
        switch (event.type) {
            case ENET_EVENT_TYPE_RECEIVE:
                ser = malloc(sizeof(serial));
                serial_create(ser);
                ser->data = malloc(event.packet->dataLength);
                ser->len = event.packet->dataLength;
                memcpy(ser->data, event.packet->data, event.packet->dataLength);
                switch(serial_read_int8(ser)) {
                    case EVENT_TYPE_ACTION:
                        {
                            // dispatch keypress to scene
                            int action = serial_read_int16(ser);
                            controller_cmd(ctrl, action, ev);
                            /*handled = 1;*/
                            serial_free(ser);
                            free(ser);
                        }
                        break;
                    case EVENT_TYPE_HB:
                        {
                            // got a tick
                            int id = serial_read_int8(ser);
                            if (id == data->id) {
                                int start = serial_read_int32(ser);
                                int peerticks = serial_read_int32(ser);
                                int newrtt = abs(start - ticks);
                                data->rttbuf[data->rttpos++] = newrtt;
                                if (data->rttpos >= 100) {
                                    data->rttpos = 0;
                                    data->rttfilled = 1;
                                }
                                if (data->rttfilled == 1) {
                                    ctrl->rtt = avg_rtt(data->rttbuf, 100);
                                    data->tick_offset = (peerticks + (ctrl->rtt/2)) - ticks;
                                    /*DEBUG("I am %d ticks away from server: %d %d", data->tick_offset, ticks, peerticks);*/
                                }
                                data->outstanding_hb = 0;
                                data->last_hb = ticks;
                                serial_free(ser);
                            } else {
                                // a heartbeat from the peer, bounce it back
                                ENetPacket *packet;
                                // write our own ticks into it
                                serial_write_int32(ser, ticks);
                                packet = enet_packet_create(ser->data, ser->len, ENET_PACKET_FLAG_UNSEQUENCED);
                                if (peer) {
                                    enet_peer_send(peer, 0, packet);
                                    enet_host_flush (host);
                                }
                            }
                            free(ser);
                        }
                        break;
                    case EVENT_TYPE_SYNC:
                        controller_sync(ctrl, ser, ev);
                        /*handled = 1;*/
                        break;
                    default:
                        serial_free(ser);
                        free(ser);
                }
                enet_packet_destroy(event.packet);
                break;
            case ENET_EVENT_TYPE_DISCONNECT:
                DEBUG("peer disconnected!");
                data->disconnected = 1;
                controller_close(ctrl, ev);
                return 1; // bail the f**k out
                break;
            default:
                break;
        }
    }

    int tick_interval = 5;
    if (data->rttfilled) {
        tick_interval = 20;
    }

    if ((data->last_hb == -1 || ticks - data->last_hb > tick_interval) || !data->outstanding_hb) {
        data->outstanding_hb = 1;
        serial ser;
        ENetPacket *packet;
        serial_create(&ser);
        serial_write_int8(&ser, EVENT_TYPE_HB);
        serial_write_int8(&ser, data->id);
        serial_write_int32(&ser, ticks);
        packet = enet_packet_create(ser.data, ser.len, ENET_PACKET_FLAG_UNSEQUENCED);
        if (peer) {
            enet_peer_send(peer, 0, packet);
            enet_host_flush (host);
        } else {
            DEBUG("peer is null~");
            data->disconnected = 1;
            controller_close(ctrl, ev);
        }
    }

    /*if(!handled) {*/
        /*controller_cmd(ctrl, ACT_STOP, ev);*/
    /*}*/
    return 0;
}