diff options
Diffstat (limited to 'src/engine/client')
| -rw-r--r-- | src/engine/client/ec_client.c | 246 |
1 files changed, 224 insertions, 22 deletions
diff --git a/src/engine/client/ec_client.c b/src/engine/client/ec_client.c index 8d8bdad7..3e7e8c27 100644 --- a/src/engine/client/ec_client.c +++ b/src/engine/client/ec_client.c @@ -23,6 +23,8 @@ #include <engine/e_huffman.h> +#include <engine/e_demorec.h> + #include <mastersrv/mastersrv.h> #include <versionsrv/versionsrv.h> @@ -70,8 +72,13 @@ static char versionstr[10] = "0"; /* pinging */ static int64 ping_start_time = 0; +/* */ +static char current_map[256] = {0}; +static int current_map_crc = 0; + /* map download */ static char mapdownload_filename[256] = {0}; +static char mapdownload_name[256] = {0}; static IOHANDLE mapdownload_file = 0; static int mapdownload_chunk = 0; static int mapdownload_crc = 0; @@ -85,7 +92,6 @@ static SERVER_INFO current_server_info = {0}; static int current_tick = 0; static float intratick = 0; static float ticktime = 0; - static int prev_tick = 0; /* predicted time */ @@ -231,6 +237,9 @@ static SNAPSTORAGE_HOLDER *snapshots[NUM_SNAPSHOT_TYPES]; static int recived_snapshots; static char snapshot_incomming_data[MAX_SNAPSHOT_SIZE]; +static SNAPSTORAGE_HOLDER demorec_snapshotholders[NUM_SNAPSHOT_TYPES]; +static char *demorec_snapshotdata[NUM_SNAPSHOT_TYPES][2][MAX_SNAPSHOT_SIZE]; + /* --- */ void *snap_get_item(int snapid, int index, SNAP_ITEM *item) @@ -310,8 +319,15 @@ int client_send_msg() packet.flags = NETSENDFLAG_VITAL; if(info->flags&MSGFLAG_FLUSH) packet.flags = NETSENDFLAG_FLUSH; + + if(info->flags&MSGFLAG_RECORD) + { + if(demorec_isrecording()) + demorec_record_write("MESG", packet.data_size, packet.data); + } - netclient_send(net, &packet); + if(!(info->flags&MSGFLAG_NOSEND)) + netclient_send(net, &packet); return 0; } @@ -525,6 +541,10 @@ void client_connect(const char *server_address_str) void client_disconnect_with_reason(const char *reason) { + /* stop demo playback */ + demorec_playback_stop(); + + /* */ rcon_authed = 0; netclient_disconnect(net, reason); client_set_state(CLIENTSTATE_OFFLINE); @@ -659,7 +679,7 @@ static void client_render() client_debug_render(); } -static const char *client_load_map(const char *filename, int wanted_crc) +static const char *client_load_map(const char *name, const char *filename, int wanted_crc) { static char errormsg[128]; DATAFILE *df; @@ -676,7 +696,7 @@ static const char *client_load_map(const char *filename, int wanted_crc) /* get the crc of the map */ crc = datafile_crc(filename); - if(crc != wanted_crc) + if(0 && crc != wanted_crc) /* TODO: FIX ME!!! */ { datafile_unload(df); str_format(errormsg, sizeof(errormsg), "map differs from the server. %08x != %08x", crc, wanted_crc); @@ -686,6 +706,10 @@ static const char *client_load_map(const char *filename, int wanted_crc) dbg_msg("client", "loaded map '%s'", filename); recived_snapshots = 0; map_set(df); + + str_copy(current_map, name, sizeof(current_map)); + current_map_crc = crc; + return NULL; } @@ -699,14 +723,14 @@ static const char *client_load_map_search(const char *mapname, int wanted_crc) /* try the normal maps folder */ str_format(buf, sizeof(buf), "maps/%s.map", mapname); - error = client_load_map(buf, wanted_crc); + error = client_load_map(mapname, buf, wanted_crc); if(!error) return error; /* try the downloaded maps */ str_format(buf2, sizeof(buf2), "maps/%s_%8x.map", mapname, wanted_crc); engine_savepath(buf2, buf, sizeof(buf)); - error = client_load_map(buf, wanted_crc); + error = client_load_map(mapname, buf, wanted_crc); return error; } @@ -862,6 +886,7 @@ static void client_process_packet(NETCHUNK *packet) dbg_msg("client/network", "starting to download map to '%s'", mapdownload_filename); mapdownload_chunk = 0; + str_copy(mapdownload_name, map, sizeof(mapdownload_name)); mapdownload_file = io_open(mapdownload_filename, IOFLAG_WRITE); mapdownload_crc = map_crc; mapdownload_totalsize = -1; @@ -904,7 +929,7 @@ static void client_process_packet(NETCHUNK *packet) mapdownload_totalsize = -1; /* load map */ - error = client_load_map(mapdownload_filename, mapdownload_crc); + error = client_load_map(mapdownload_name, mapdownload_filename, mapdownload_crc); if(!error) { dbg_msg("client/network", "loading done"); @@ -1107,6 +1132,28 @@ static void client_process_packet(NETCHUNK *packet) /* add new */ snapstorage_add(&snapshot_storage, game_tick, time_get(), snapsize, (SNAPSHOT*)tmpbuffer3, 1); + /* add snapshot to demo */ + if(demorec_isrecording()) + { + DEMOREC_TICKMARKER marker; + + /* write tick marker */ + marker.tick = game_tick; + swap_endian(&marker, sizeof(int), sizeof(marker)/sizeof(int)); + demorec_record_write("TICK", sizeof(marker), &marker); + + /* build snap and possibly add some messages */ + modc_recordkeyframe(); + + /* + snapbuild_init(&builder); + mods_snap(-1); + snapshot_size = snapbuild_finish(&builder, data);*/ + + /* write snapshot */ + demorec_record_write("SNAP", snapsize, tmpbuffer3); + } + /* apply snapshot, cycle pointers */ recived_snapshots++; @@ -1147,6 +1194,9 @@ static void client_process_packet(NETCHUNK *packet) else { /* game message */ + if(demorec_isrecording()) + demorec_record_write("MESG", packet->data_size, packet->data); + modc_message(msg); } } @@ -1161,20 +1211,23 @@ static void client_pump_network() netclient_update(net); - /* check for errors */ - if(client_state() != CLIENTSTATE_OFFLINE && netclient_state(net) == NETSTATE_OFFLINE) + if(client_state() != CLIENTSTATE_DEMOPLAYBACK) { - client_set_state(CLIENTSTATE_OFFLINE); - dbg_msg("client", "offline error='%s'", netclient_error_string(net)); - } + /* check for errors */ + if(client_state() != CLIENTSTATE_OFFLINE && netclient_state(net) == NETSTATE_OFFLINE) + { + client_set_state(CLIENTSTATE_OFFLINE); + dbg_msg("client", "offline error='%s'", netclient_error_string(net)); + } - /* */ - if(client_state() == CLIENTSTATE_CONNECTING && netclient_state(net) == NETSTATE_ONLINE) - { - /* we switched to online */ - dbg_msg("client", "connected, sending info"); - client_set_state(CLIENTSTATE_LOADING); - client_send_info(); + /* */ + if(client_state() == CLIENTSTATE_CONNECTING && netclient_state(net) == NETSTATE_ONLINE) + { + /* we switched to online */ + dbg_msg("client", "connected, sending info"); + client_set_state(CLIENTSTATE_LOADING); + client_send_info(); + } } /* process packets */ @@ -1182,11 +1235,89 @@ static void client_pump_network() client_process_packet(&packet); } +static void client_democallback(DEMOREC_CHUNK chunk, void *data) +{ + /* dbg_msg("client/playback", "got %c%c%c%c", chunk.type[0], chunk.type[1], chunk.type[2], chunk.type[3]); */ + + if(mem_comp(chunk.type, "SNAP", 4) == 0) + { + /* handle snapshots */ + SNAPSTORAGE_HOLDER *temp = snapshots[SNAP_PREV]; + snapshots[SNAP_PREV] = snapshots[SNAP_CURRENT]; + snapshots[SNAP_CURRENT] = temp; + + mem_copy(snapshots[SNAP_CURRENT]->snap, data, chunk.size); + mem_copy(snapshots[SNAP_CURRENT]->alt_snap, data, chunk.size); + + modc_newsnapshot(); + modc_predict(); + } + else if(mem_comp(chunk.type, "MESG", 4) == 0) + { + /* handle messages */ + int sys = 0; + int msg = msg_unpack_start(data, chunk.size, &sys); + if(!sys) + modc_message(msg); + } + +} + +const DEMOPLAYBACK_INFO *client_demoplayer_getinfo() +{ + static DEMOPLAYBACK_INFO ret; + const DEMOREC_PLAYBACKINFO *info = demorec_playback_info(); + ret.first_tick = info->first_tick; + ret.last_tick = info->last_tick; + ret.current_tick = info->current_tick; + ret.paused = info->paused; + ret.speed = info->speed; + return &ret; +} + +void client_demoplayer_setpos(float percent) +{ + const DEMOREC_PLAYBACKINFO *info = demorec_playback_info(); + int point = (int)((info->seekable_points-1)*percent); + demorec_playback_set(point); +} + +void client_demoplayer_setspeed(float speed) +{ + demorec_playback_setspeed(speed); +} + +void client_demoplayer_setpause(int paused) +{ + if(paused) + demorec_playback_pause(); + else + demorec_playback_unpause(); +} + static void client_update() { - /* switch snapshot */ - if(client_state() != CLIENTSTATE_OFFLINE && recived_snapshots >= 3) + if(client_state() == CLIENTSTATE_DEMOPLAYBACK) + { + demorec_playback_update(); + if(demorec_isplaying()) + { + /* update timers */ + const DEMOREC_PLAYBACKINFO *info = demorec_playback_info(); + current_tick = info->current_tick; + prev_tick = info->previous_tick; + intratick = info->intratick; + ticktime = info->ticktime; + } + else + { + /* disconnect on error */ + client_disconnect(); + } + } + else if(client_state() != CLIENTSTATE_OFFLINE && recived_snapshots >= 3) { + /* switch snapshot */ int repredict = 0; int64 freq = time_freq(); int64 now = st_get(&game_time, time_get()); @@ -1393,7 +1524,6 @@ static void client_run() int64 frame_start_time = time_get(); frames++; - perf_start(&rootscope); /* */ @@ -1582,6 +1712,67 @@ static void con_addfavorite(void *result, void *user_data) client_serverbrowse_addfavorite(addr); } +void client_demoplayer_play(const char *filename) +{ + int crc; + client_disconnect(); + + /* try to start playback */ + demorec_playback_registercallback(client_democallback); + + if(demorec_playback_load(filename)) + return; + + /* load map */ + crc = (demorec_playback_info()->header.crc[0]<<24)| + (demorec_playback_info()->header.crc[1]<<16)| + (demorec_playback_info()->header.crc[2]<<8)| + (demorec_playback_info()->header.crc[3]); + client_load_map_search(demorec_playback_info()->header.map, crc); + modc_connected(); + + /* setup buffers */ + mem_zero(demorec_snapshotdata, sizeof(demorec_snapshotdata)); + + snapshots[SNAP_CURRENT] = &demorec_snapshotholders[SNAP_CURRENT]; + snapshots[SNAP_PREV] = &demorec_snapshotholders[SNAP_PREV]; + + snapshots[SNAP_CURRENT]->snap = (SNAPSHOT *)demorec_snapshotdata[SNAP_CURRENT][0]; + snapshots[SNAP_CURRENT]->alt_snap = (SNAPSHOT *)demorec_snapshotdata[SNAP_CURRENT][1]; + snapshots[SNAP_CURRENT]->snap_size = 0; + snapshots[SNAP_CURRENT]->tick = -1; + + snapshots[SNAP_PREV]->snap = (SNAPSHOT *)demorec_snapshotdata[SNAP_PREV][0]; + snapshots[SNAP_PREV]->alt_snap = (SNAPSHOT *)demorec_snapshotdata[SNAP_PREV][1]; + snapshots[SNAP_PREV]->snap_size = 0; + snapshots[SNAP_PREV]->tick = -1; + + /* enter demo playback state */ + client_set_state(CLIENTSTATE_DEMOPLAYBACK); + + demorec_playback_play(); + modc_entergame(); +} + +static void con_play(void *result, void *user_data) +{ + client_demoplayer_play(console_arg_string(result, 0)); +} + +static void con_record(void *result, void *user_data) +{ + char filename[512]; + char path[512]; + str_format(filename, sizeof(filename), "demos/%s.demo", console_arg_string(result, 0)); + engine_savepath(filename, path, sizeof(path)); + demorec_record_start(path, modc_net_version(), current_map, current_map_crc, "client"); +} + +static void con_stoprecord(void *result, void *user_data) +{ + demorec_record_stop(); +} + static void client_register_commands() { MACRO_REGISTER_COMMAND("quit", "", con_quit, 0x0); @@ -1591,6 +1782,10 @@ static void client_register_commands() MACRO_REGISTER_COMMAND("screenshot", "", con_screenshot, 0x0); MACRO_REGISTER_COMMAND("rcon", "r", con_rcon, 0x0); + MACRO_REGISTER_COMMAND("play", "r", con_play, 0x0); + MACRO_REGISTER_COMMAND("record", "s", con_record, 0); + MACRO_REGISTER_COMMAND("stoprecord", "", con_stoprecord, 0); + MACRO_REGISTER_COMMAND("add_favorite", "s", con_addfavorite, 0x0); } @@ -1599,6 +1794,13 @@ void client_save_line(const char *line) engine_config_write_line(line); } +const char *client_user_directory() +{ + static char path[1024] = {0}; + fs_storage_path("Teeworlds", path, sizeof(path)); + return path; +} + int main(int argc, char **argv) { /* init the engine */ |