about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/engine/client/client.c62
-rw-r--r--src/engine/datafile.c26
-rw-r--r--src/engine/datafile.h2
-rw-r--r--src/engine/network.c4
-rw-r--r--src/engine/server/server.c8
-rw-r--r--src/game/client/menu2.cpp1
6 files changed, 82 insertions, 21 deletions
diff --git a/src/engine/client/client.c b/src/engine/client/client.c
index 6f8a2761..bcc350d2 100644
--- a/src/engine/client/client.c
+++ b/src/engine/client/client.c
@@ -18,6 +18,7 @@
 #include <engine/config.h>
 #include <engine/packer.h>
 #include <engine/memheap.h>
+#include <engine/datafile.h>
 
 #include <mastersrv/mastersrv.h>
 
@@ -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 fbb1c430..7069044c 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 397bf51f..7cc7b209 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 2fe80528..fd687637 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 f26a51c5..3135f418 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 b6394977..c3c1fdfe 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;
 }