void net_controller_har_hook(int action, void *cb_data) { controller *ctrl = cb_data; wtf *data = ctrl->data; serial ser; ENetPeer *peer = data->peer; ENetHost *host = data->host; ENetPacket *packet; if (action == ACT_STOP && data->last_action == ACT_STOP) { data->last_action = -1; return; } if (action == ACT_FLUSH) { enet_host_flush(host); return; } data->last_action = action; serial_create(&ser); serial_write_int8(&ser, EVENT_TYPE_ACTION); serial_write_int16(&ser, action); /*DEBUG("controller hook fired with %d", action);*/ /*sprintf(buf, "k%d", action);*/ packet = enet_packet_create(ser.data, ser.len, ENET_PACKET_FLAG_RELIABLE); if (peer) { enet_peer_send(peer, 1, packet); /*enet_host_flush (host);*/ } else { DEBUG("peer is null~"); } }
/* * Serializes the object to a buffer. Should return 1 on error, 0 on success * This will call the specialized objects, eg. har or projectile for their * serialization data. */ int object_serialize(object *obj, serial *ser) { serial_write_float(ser, obj->pos.x); serial_write_float(ser, obj->pos.y); serial_write_float(ser, obj->vel.x); serial_write_float(ser, obj->vel.y); serial_write_float(ser, obj->gravity); serial_write_int8(ser, obj->direction); serial_write_int8(ser, obj->group); serial_write_int8(ser, obj->layers); serial_write_int8(ser, obj->stride); serial_write_int8(ser, object_get_repeat(obj)); serial_write_int8(ser, obj->sprite_override); serial_write_int32(ser, obj->age); serial_write_int32(ser, random_get_seed(&obj->rand_state)); serial_write_int8(ser, obj->cur_animation->id); serial_write_int8(ser, obj->pal_offset); serial_write_int8(ser, obj->hit_frames); serial_write_int8(ser, obj->can_hit); // Write animation state if (obj->custom_str) { serial_write_int16(ser, strlen(obj->custom_str)+1); serial_write(ser, obj->custom_str, strlen(obj->custom_str)+1); } else { // using regular animation string from animation serial_write_int16(ser, 0); } serial_write_int16(ser, (int)obj->animation_state.current_tick); serial_write_int16(ser, (int)obj->animation_state.previous_tick); serial_write_int8(ser, (int)obj->animation_state.reverse); /*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);*/ // Serialize the underlying object if(obj->serialize != NULL) { obj->serialize(obj, ser); } else { serial_write_int8(ser, SPECID_NONE); } // Return success return 0; }
int projectile_serialize(object *obj, serial *ser) { projectile_local *local = object_get_userdata(obj); serial_write_int8(ser, SPECID_PROJECTILE); serial_write_int8(ser, local->af_data->id); return 0; }
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; }