diff --git a/src/engine/client/client.c b/src/engine/client/client.c index 6f8a27616..bcc350d22 100644 --- a/src/engine/client/client.c +++ b/src/engine/client/client.c @@ -18,6 +18,7 @@ #include #include #include +#include #include @@ -295,15 +296,6 @@ static void client_send_ready() client_send_msg(); } -static void client_send_error(const char *error) -{ - /* - packet p(NETMSG_CLIENT_ERROR); - p.write_str(error); - send_packet(&p); - */ -} - void client_rcon(const char *cmd) { msg_pack_start_system(NETMSG_CMD, MSGFLAG_VITAL); @@ -434,10 +426,16 @@ void client_connect(const char *server_address_str) } +void client_disconnect_with_reason(const char *reason) +{ + netclient_disconnect(net, reason); + client_set_state(CLIENTSTATE_OFFLINE); + map_unload(); +} + void client_disconnect() { - client_send_error("disconnected"); - netclient_disconnect(net, "disconnected"); + netclient_disconnect(net, 0); client_set_state(CLIENTSTATE_OFFLINE); map_unload(); } @@ -524,11 +522,35 @@ static void client_render() client_debug_render(); } -static void client_error(const char *msg) +static const char *client_load_map(const char *mapname, int wanted_crc) { - dbg_msg("client", "error: %s", msg); - client_send_error(msg); - client_set_state(CLIENTSTATE_OFFLINE); + static char errormsg[128]; + DATAFILE *df; + char buf[512]; + int crc; + + dbg_msg("client", "loading map, map=%s wanted crc=%08x", mapname, wanted_crc); + client_set_state(CLIENTSTATE_LOADING); + + sprintf(buf, "data/maps/%s.map", mapname); + df = datafile_load(buf); + if(!df) + { + sprintf(errormsg, "map '%s' not found", mapname); + return errormsg; + } + + /* get the crc of the map */ + crc = datafile_crc(buf); + if(crc != wanted_crc) + { + datafile_unload(df); + sprintf(errormsg, "map differs from the server. %08x != %08x", crc, wanted_crc); + return errormsg; + } + + map_set(df); + return NULL; } static void client_process_packet(NETPACKET *packet) @@ -609,10 +631,10 @@ static void client_process_packet(NETPACKET *packet) if(msg == NETMSG_MAP) { const char *map = msg_unpack_string(); - dbg_msg("client/network", "connection accepted, map=%s", map); - client_set_state(CLIENTSTATE_LOADING); - - if(map_load(map)) + int map_crc = msg_unpack_int(); + const char *error = client_load_map(map, map_crc); + + if(!error) { dbg_msg("client/network", "loading done"); client_send_ready(); @@ -620,7 +642,7 @@ static void client_process_packet(NETPACKET *packet) } else { - client_error("failure to load map"); + client_disconnect_with_reason(error); } } else if(msg == NETMSG_SNAP || msg == NETMSG_SNAPEMPTY) diff --git a/src/engine/datafile.c b/src/engine/datafile.c index fbb1c430f..7069044c7 100644 --- a/src/engine/datafile.c +++ b/src/engine/datafile.c @@ -602,3 +602,29 @@ int datafile_finish(DATAFILE_OUT *df) dbg_msg("datafile", "done"); return 0; } + +#define BUFFER_SIZE 64*1024 + +int datafile_crc(const char *filename) +{ + unsigned char buffer[BUFFER_SIZE]; + IOHANDLE file; + int crc = 0; + unsigned bytes = 0; + + file = io_open(filename, IOFLAG_READ); + if(!file) + return 0; + + while(1) + { + bytes = io_read(file, buffer, BUFFER_SIZE); + if(bytes <= 0) + break; + crc = crc32(crc, buffer, bytes); + } + + io_close(file); + + return crc; +} diff --git a/src/engine/datafile.h b/src/engine/datafile.h index 397bf51f9..7cc7b2099 100644 --- a/src/engine/datafile.h +++ b/src/engine/datafile.h @@ -17,6 +17,8 @@ int datafile_num_items(DATAFILE *df); int datafile_num_data(DATAFILE *df); void datafile_unload(DATAFILE *df); +int datafile_crc(const char *filename); + /* write access */ typedef struct DATAFILE_OUT_t DATAFILE_OUT; DATAFILE_OUT *datafile_create(const char *filename); diff --git a/src/engine/network.c b/src/engine/network.c index 2fe805283..fd6876372 100644 --- a/src/engine/network.c +++ b/src/engine/network.c @@ -334,6 +334,10 @@ static void conn_disconnect(NETCONNECTION *conn, const char *reason) else conn_send(conn, NETWORK_PACKETFLAG_CLOSE, 0, 0); } + + conn->error_string[0] = 0; + if(reason) + strcpy(conn->error_string, reason); conn_reset(conn); } diff --git a/src/engine/server/server.c b/src/engine/server/server.c index f26a51c5f..3135f4181 100644 --- a/src/engine/server/server.c +++ b/src/engine/server/server.c @@ -32,6 +32,7 @@ static int64 lastheartbeat; static NETADDR4 master_server; static char current_map[64]; +static int current_map_crc; void *snap_new_item(int type, int id, int size) { @@ -401,6 +402,7 @@ static void server_send_map(int cid) { msg_pack_start_system(NETMSG_MAP, MSGFLAG_VITAL); msg_pack_string(config.sv_map, 0); + msg_pack_int(current_map_crc); msg_pack_end(); server_send_msg(cid); } @@ -640,6 +642,10 @@ static int server_load_map(const char *mapname) df = datafile_load(buf); if(!df) return 0; + + /* get the crc of the map */ + current_map_crc = datafile_crc(buf); + dbg_msg("server", "%s crc is %08x", buf, current_map_crc); strcpy(current_map, mapname); map_set(df); @@ -651,7 +657,7 @@ static int server_run() { NETADDR4 bindaddr; - net_init(); /* For Windows compatibility. */ + net_init(); snap_init_id(); diff --git a/src/game/client/menu2.cpp b/src/game/client/menu2.cpp index b63949773..c3c1fdfe3 100644 --- a/src/game/client/menu2.cpp +++ b/src/game/client/menu2.cpp @@ -1450,6 +1450,7 @@ static int popup = POPUP_NONE; void menu_do_disconnected() { + popup = POPUP_NONE; if(strlen(client_error_string())) popup = POPUP_DISCONNECTED; }