about summary refs log tree commit diff
path: root/src/engine/client/ec_client.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/engine/client/ec_client.c')
-rw-r--r--src/engine/client/ec_client.c134
1 files changed, 120 insertions, 14 deletions
diff --git a/src/engine/client/ec_client.c b/src/engine/client/ec_client.c
index dfc16ec3..9c63f7cb 100644
--- a/src/engine/client/ec_client.c
+++ b/src/engine/client/ec_client.c
@@ -43,7 +43,6 @@ NETCLIENT *net;
 /* TODO: ugly, fix me */
 extern void client_serverbrowse_set(NETADDR4 *addr, int request, SERVER_INFO *info);
 
-
 static int snapshot_part;
 static int64 local_start_time;
 
@@ -63,6 +62,14 @@ static int current_recv_tick = 0;
 /* pinging */
 static int64 ping_start_time = 0;
 
+/* map download */
+static char mapdownload_filename[256] = {0};
+static IOHANDLE mapdownload_file = 0;
+static int mapdownload_chunk = 0;
+static int mapdownload_crc = 0;
+static int mapdownload_amount = -1;
+static int mapdownload_totalsize = -1;
+
 /* current time */
 static int current_tick = 0;
 static float intratick = 0;
@@ -546,26 +553,23 @@ static void client_render()
 	client_debug_render();
 }
 
-static const char *client_load_map(const char *mapname, int wanted_crc)
+static const char *client_load_map(const char *filename, int wanted_crc)
 {
 	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);
+	df = datafile_load(filename);
 	if(!df)
 	{
-		sprintf(errormsg, "map '%s' not found", mapname);
+		sprintf(errormsg, "map '%s' not found", filename);
 		return errormsg;
 	}
 	
 	/* get the crc of the map */
-	crc = datafile_crc(buf);
+	crc = datafile_crc(filename);
 	if(crc != wanted_crc)
 	{
 		datafile_unload(df);
@@ -573,11 +577,33 @@ static const char *client_load_map(const char *mapname, int wanted_crc)
 		return errormsg;
 	}
 	
+	dbg_msg("client", "loaded map '%s'", filename);
 	recived_snapshots = 0;
 	map_set(df);
 	return NULL;
 }
 
+static const char *client_load_map_search(const char *mapname, int wanted_crc)
+{
+	const char *error = 0;
+	char buf[512];
+	char buf2[512];
+	dbg_msg("client", "loading map, map=%s wanted crc=%08x", mapname, wanted_crc);
+	client_set_state(CLIENTSTATE_LOADING);
+	
+	/* try the normal maps folder */
+	sprintf(buf, "data/maps/%s.map", mapname);
+	error = client_load_map(buf, wanted_crc);
+	if(!error)
+		return error;
+
+	/* try the downloaded maps */
+	sprintf(buf2, "%s_%8x.map", mapname, wanted_crc);
+	engine_savepath(buf2, buf, sizeof(buf));
+	error = client_load_map(buf, wanted_crc);
+	return error;
+}
+
 static void client_process_packet(NETPACKET *packet)
 {
 	if(packet->client_id == -1)
@@ -677,17 +703,94 @@ static void client_process_packet(NETPACKET *packet)
 			{
 				const char *map = msg_unpack_string();
 				int map_crc = msg_unpack_int();
-				const char *error = client_load_map(map, map_crc);
+				const char *error = 0;
+				int i;
+				
+				for(i = 0; map[i]; i++) /* protect the player from nasty map names */
+				{
+					if(map[i] == '/' || map[i] == '\\')
+						error = "strange character in map name";
+				}
+				
+				if(error)
+					client_disconnect_with_reason(error);
+				else
+				{
+					error = client_load_map_search(map, map_crc);
+
+					if(!error)
+					{
+						dbg_msg("client/network", "loading done");
+						client_send_ready();
+						modc_connected();
+					}
+					else
+					{
+						char buf[512];
+						sprintf(buf, "%s_%8x.map", map, map_crc);
+						engine_savepath(buf, mapdownload_filename, sizeof(mapdownload_filename));
 
-				if(!error)
+						dbg_msg("client/network", "starting to download map to '%s'", mapdownload_filename);
+						
+						mapdownload_chunk = 0;
+						mapdownload_file = io_open(mapdownload_filename, IOFLAG_WRITE);
+						mapdownload_crc = map_crc;
+						mapdownload_totalsize = -1;
+						mapdownload_amount = 0;
+						
+						msg_pack_start_system(NETMSG_REQUEST_MAP_DATA, 0);
+						msg_pack_int(mapdownload_chunk);
+						msg_pack_end();
+						client_send_msg();
+										
+						if(config.debug)
+							dbg_msg("client/network", "requested chunk %d", mapdownload_chunk);
+					}
+				}
+			}
+			else if(msg == NETMSG_MAP_DATA)
+			{
+				int last = msg_unpack_int();
+				int total_size = msg_unpack_int();
+				int size = msg_unpack_int();
+				const unsigned char *data = msg_unpack_raw(size);
+				io_write(mapdownload_file, data, size);
+				
+				mapdownload_totalsize = total_size;
+				mapdownload_amount += size;
+				
+				if(last)
 				{
-					dbg_msg("client/network", "loading done");
-					client_send_ready();
-					modc_connected();
+					const char *error;
+					dbg_msg("client/network", "download complete, loading map");
+					
+					io_close(mapdownload_file);
+					mapdownload_file = 0;
+					mapdownload_amount = 0;
+					mapdownload_totalsize = -1;
+					
+					/* load map */
+					error = client_load_map(mapdownload_filename, mapdownload_crc);
+					if(!error)
+					{
+						dbg_msg("client/network", "loading done");
+						client_send_ready();
+						modc_connected();
+					}
+					else
+						client_disconnect_with_reason(error);
 				}
 				else
 				{
-					client_disconnect_with_reason(error);
+					/* request new chunk */
+					mapdownload_chunk++;
+					msg_pack_start_system(NETMSG_REQUEST_MAP_DATA, 0);
+					msg_pack_int(mapdownload_chunk);
+					msg_pack_end();
+					client_send_msg();
+
+					if(config.debug)
+						dbg_msg("client/network", "requested chunk %d", mapdownload_chunk);
 				}
 			}
 			else if(msg == NETMSG_PING)
@@ -884,6 +987,9 @@ static void client_process_packet(NETPACKET *packet)
 	}
 }
 
+int client_mapdownload_amount() { return mapdownload_amount; }
+int client_mapdownload_totalsize() { return mapdownload_totalsize; }
+
 static void client_pump_network()
 {
 	NETPACKET packet;