about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/engine/client/ec_client.c134
-rw-r--r--src/engine/e_engine.c4
-rw-r--r--src/engine/e_if_client.h29
-rw-r--r--src/engine/e_protocol.h2
-rw-r--r--src/engine/server/es_server.c39
-rw-r--r--src/game/client/gc_hooks.cpp1
-rw-r--r--src/game/client/gc_menu.cpp16
7 files changed, 209 insertions, 16 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;
diff --git a/src/engine/e_engine.c b/src/engine/e_engine.c
index 9af77f84..f4f1ed3b 100644
--- a/src/engine/e_engine.c
+++ b/src/engine/e_engine.c
@@ -47,6 +47,10 @@ void engine_init(const char *appname, int argc, char **argv)
 			strcpy(path, application_save_path);
 			strcat(path, "/screenshots");
 			fs_makedir(path);
+
+			strcpy(path, application_save_path);
+			strcat(path, "/maps");
+			fs_makedir(path);
 		}
 	}
 
diff --git a/src/engine/e_if_client.h b/src/engine/e_if_client.h
index 4f6393ce..9173cfe1 100644
--- a/src/engine/e_if_client.h
+++ b/src/engine/e_if_client.h
@@ -386,4 +386,33 @@ int client_connection_problems();
 */
 int client_state();
 
+/*
+	Function: client_mapdownload_amount
+		TODO
+	
+	Arguments:
+		arg1 - desc
+	
+	Returns:
+
+	See Also:
+		<other_func>
+*/
+int client_mapdownload_amount();
+
+/*
+	Function: client_mapdownload_totalsize
+		TODO
+	
+	Arguments:
+		arg1 - desc
+	
+	Returns:
+
+	See Also:
+		<other_func>
+*/
+int client_mapdownload_totalsize();
+
+
 #endif
diff --git a/src/engine/e_protocol.h b/src/engine/e_protocol.h
index 65d76350..a0213483 100644
--- a/src/engine/e_protocol.h
+++ b/src/engine/e_protocol.h
@@ -34,6 +34,7 @@ enum
 	
 	/* sent by server */
 	NETMSG_MAP,
+	NETMSG_MAP_DATA,
 	NETMSG_SNAP,
 	NETMSG_SNAPEMPTY,
 	NETMSG_SNAPSINGLE,
@@ -44,6 +45,7 @@ enum
 	NETMSG_ENTERGAME,
 	NETMSG_INPUT,
 	NETMSG_CMD,
+	NETMSG_REQUEST_MAP_DATA,
 	
 	/* sent by both */
 	NETMSG_PING,
diff --git a/src/engine/server/es_server.c b/src/engine/server/es_server.c
index 9c2aac41..c677d154 100644
--- a/src/engine/server/es_server.c
+++ b/src/engine/server/es_server.c
@@ -33,6 +33,8 @@ static NETADDR4 master_server;
 
 static char current_map[64];
 static int current_map_crc;
+static unsigned char *current_map_data = 0;
+static int current_map_size = 0;
 
 void *snap_new_item(int type, int id, int size)
 {
@@ -592,6 +594,32 @@ static void server_process_client_packet(NETPACKET *packet)
 			
 			server_send_map(cid);
 		}
+		else if(msg == NETMSG_REQUEST_MAP_DATA)
+		{
+			int chunk = msg_unpack_int();
+			int chunk_size = 1024-128;
+			int offset = chunk * chunk_size;
+			int last = 0;
+			
+			if(offset+chunk_size >= current_map_size)
+			{
+				chunk_size = current_map_size-offset;
+				if(chunk_size < 0)
+					chunk_size = 0;
+				last = 1;
+			}
+			
+			msg_pack_start_system(NETMSG_MAP_DATA, MSGFLAG_VITAL);
+			msg_pack_int(last);
+			msg_pack_int(current_map_size);
+			msg_pack_int(chunk_size);
+			msg_pack_raw(&current_map_data[offset], chunk_size);
+			msg_pack_end();
+			server_send_msg(cid);
+			
+			if(config.debug)
+				dbg_msg("server", "sending chunk %d with size %d", chunk, chunk_size);
+		}
 		else if(msg == NETMSG_READY)
 		{
 			if(clients[cid].state == SRVCLIENT_STATE_CONNECTING)
@@ -831,6 +859,17 @@ static int server_load_map(const char *mapname)
 		
 	strcpy(current_map, mapname);
 	map_set(df);
+	
+	/* load compelate map into memory for download */
+	{
+		IOHANDLE file = io_open(buf, IOFLAG_READ);
+		current_map_size = (int)io_length(file);
+		if(current_map_data)
+			mem_free(current_map_data);
+		current_map_data = (unsigned char *)mem_alloc(current_map_size, 1);
+		io_read(file, current_map_data, current_map_size);
+		io_close(file);
+	}
 	return 1;
 }
 
diff --git a/src/game/client/gc_hooks.cpp b/src/game/client/gc_hooks.cpp
index 4ab5cf6a..a6391007 100644
--- a/src/game/client/gc_hooks.cpp
+++ b/src/game/client/gc_hooks.cpp
@@ -394,7 +394,6 @@ extern "C" void modc_statechange(int state, int old)
 	}
 }
 
-
 obj_projectile extraproj_projectiles[MAX_EXTRA_PROJECTILES];
 int extraproj_num;
 
diff --git a/src/game/client/gc_menu.cpp b/src/game/client/gc_menu.cpp
index 409edbe8..633c44da 100644
--- a/src/game/client/gc_menu.cpp
+++ b/src/game/client/gc_menu.cpp
@@ -1796,21 +1796,30 @@ int menu2_render()
 		// make sure that other windows doesn't do anything funnay!
 		//ui_set_hot_item(0);
 		//ui_set_active_item(0);
+		char buf[128];
 		const char *title = "";
 		const char *extra_text = "";
 		const char *button_text = "";
+		int extra_align = 0;
 		
 		if(popup == POPUP_CONNECTING)
 		{
 			title = "Connecting to";
 			extra_text = config.ui_server_address;  // TODO: query the client about the address
 			button_text = "Abort";
+			if(client_mapdownload_totalsize() > 0)
+			{
+				title = "Downloading map";
+				sprintf(buf, "%d/%d KiB", client_mapdownload_amount()/1024, client_mapdownload_totalsize()/1024);
+				extra_text = buf;
+			}
 		}
 		else if(popup == POPUP_DISCONNECTED)
 		{
 			title = "Disconnected";
 			extra_text = client_error_string();
 			button_text = "Ok";
+			extra_align = -1;
 		}
 		else if(popup == POPUP_PASSWORD)
 		{
@@ -1831,6 +1840,7 @@ int menu2_render()
 			"It's recommended that you check the settings to adjust them to your liking "
 			"before joining a server.";
 			button_text = "Ok";
+			extra_align = -1;
 		}
 		
 		RECT box, part;
@@ -1847,7 +1857,11 @@ int menu2_render()
 		ui_hsplit_t(&box, 20.f, &part, &box);
 		ui_hsplit_t(&box, 24.f, &part, &box);
 		ui_vmargin(&part, 20.f, &part);
-		ui_do_label(&part, extra_text, 20.f, -1, (int)part.w);
+		
+		if(extra_align == -1)
+			ui_do_label(&part, extra_text, 20.f, -1, (int)part.w);
+		else
+			ui_do_label(&part, extra_text, 20.f, 0, -1);
 
 		if(popup == POPUP_QUIT)
 		{