about summary refs log tree commit diff
path: root/src/engine/client
diff options
context:
space:
mode:
authorMagnus Auvinen <magnus.auvinen@gmail.com>2007-10-03 21:32:02 +0000
committerMagnus Auvinen <magnus.auvinen@gmail.com>2007-10-03 21:32:02 +0000
commita67738e9801a4485cfaf68012279cd5042dc2ab9 (patch)
tree5a4fa1db378b9b889b73b66ff9ac974fdc141dca /src/engine/client
parent30a7246f2fd5e2141de2c37f01b491abe374f3f9 (diff)
downloadzcatch-a67738e9801a4485cfaf68012279cd5042dc2ab9.tar.gz
zcatch-a67738e9801a4485cfaf68012279cd5042dc2ab9.zip
general fixes. fixed scoreboard
Diffstat (limited to 'src/engine/client')
-rw-r--r--src/engine/client/client.c403
-rw-r--r--src/engine/client/snd.c4
-rw-r--r--src/engine/client/srvbrowse.c383
3 files changed, 395 insertions, 395 deletions
diff --git a/src/engine/client/client.c b/src/engine/client/client.c
index 847dd8ea..066e9236 100644
--- a/src/engine/client/client.c
+++ b/src/engine/client/client.c
@@ -32,21 +32,25 @@ const int prediction_margin = 5;
 	Prediction Latency
 		Upstream latency
 */
+
+/* network client, must be accessible from other parts like the server browser */
+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;
 
-static int extra_polating = 0;
 static int debug_font;
 static float frametime = 0.0001f;
-static NETCLIENT *net;
-static NETADDR4 master_server;
 static NETADDR4 server_address;
 static int window_must_refocus = 0;
 static int snaploss = 0;
 static int snapcrcerrors = 0;
 
 static int ack_game_tick = -1;
-
 static int current_recv_tick = 0;
 
 // current time
@@ -344,381 +348,6 @@ int *client_get_input(int tick)
 	return 0;
 }
 
-/* ------ server browse ---- */
-/* TODO: move all this to a separate file */
-
-typedef struct SERVERENTRY_t SERVERENTRY;
-struct SERVERENTRY_t
-{
-	NETADDR4 addr;
-	int64 request_time;
-	int got_info;
-	SERVER_INFO info;
-	
-	SERVERENTRY *next_ip; // ip hashed list
-	
-	SERVERENTRY *prev_req; // request list
-	SERVERENTRY *next_req;
-};
-
-static HEAP *serverlist_heap = 0;
-static SERVERENTRY **serverlist = 0;
-static int *sorted_serverlist = 0;
-
-static SERVERENTRY *serverlist_ip[256] = {0}; // ip hash list
-
-static SERVERENTRY *first_req_server = 0; // request list
-static SERVERENTRY *last_req_server = 0;
-static int num_requests = 0;
-
-static int num_sorted_servers = 0;
-static int num_sorted_servers_capacity = 0;
-static int num_servers = 0;
-static int num_server_capacity = 0;
-
-static int sorthash = 0;
-static char filterstring[64] = {0};
-
-static int serverlist_lan = 1;
-
-int client_serverbrowse_num() { return num_servers; }
-
-SERVER_INFO *client_serverbrowse_get(int index)
-{
-	if(index < 0 || index >= num_servers)
-		return 0;
-	return &serverlist[index]->info;
-}
-
-int client_serverbrowse_sorted_num() { return num_sorted_servers; }
-
-SERVER_INFO *client_serverbrowse_sorted_get(int index)
-{
-	if(index < 0 || index >= num_sorted_servers)
-		return 0;
-	return &serverlist[sorted_serverlist[index]]->info;
-}
-
-
-int client_serverbrowse_num_requests()
-{
-	return num_requests;
-}
-
-static void client_serverbrowse_init()
-{
-}
-
-static int client_serverbrowse_sort_compare_name(const void *ai, const void *bi)
-{
-	SERVERENTRY *a = serverlist[*(const int*)ai];
-	SERVERENTRY *b = serverlist[*(const int*)bi];
-	return strcmp(a->info.name, b->info.name);
-}
-
-static int client_serverbrowse_sort_compare_map(const void *ai, const void *bi)
-{
-	SERVERENTRY *a = serverlist[*(const int*)ai];
-	SERVERENTRY *b = serverlist[*(const int*)bi];
-	return strcmp(a->info.map, b->info.map);
-}
-
-static int client_serverbrowse_sort_compare_ping(const void *ai, const void *bi)
-{
-	SERVERENTRY *a = serverlist[*(const int*)ai];
-	SERVERENTRY *b = serverlist[*(const int*)bi];
-	return a->info.latency > b->info.latency;
-}
-
-static int client_serverbrowse_sort_compare_numplayers(const void *ai, const void *bi)
-{
-	SERVERENTRY *a = serverlist[*(const int*)ai];
-	SERVERENTRY *b = serverlist[*(const int*)bi];
-	return a->info.num_players > b->info.num_players;
-}
-
-static void client_serverbrowse_filter()
-{
-	int i = 0;
-	num_sorted_servers = 0;
-
-	/* allocate the sorted list */	
-	if(num_sorted_servers_capacity < num_servers)
-	{
-		if(sorted_serverlist)
-			mem_free(sorted_serverlist);
-		num_sorted_servers_capacity = num_servers;
-		sorted_serverlist = mem_alloc(num_sorted_servers_capacity*sizeof(int), 1);
-	}
-	
-	/* filter the servers */
-	for(i = 0; i < num_servers; i++)
-	{
-		int filtered = 0;
-
-		if(config.b_filter_empty && serverlist[i]->info.num_players == 0)
-			filtered = 1;
-		else if(config.b_filter_full && serverlist[i]->info.num_players == serverlist[i]->info.max_players)
-			filtered = 1;
-		else if(config.b_filter_pw && serverlist[i]->info.flags&1)
-			filtered = 1;
-		else if(config.b_filter_string[0] != 0)
-		{
-			if(strstr(serverlist[i]->info.name, config.b_filter_string) == 0)
-				filtered = 1;
-		}
-			
-		if(filtered == 0)
-			sorted_serverlist[num_sorted_servers++] = i;
-	}
-}
-
-static int client_serverbrowse_sorthash()
-{
-	int i = config.b_sort&3;
-	i |= config.b_filter_empty<<4;
-	i |= config.b_filter_full<<5;
-	i |= config.b_filter_pw<<6;
-	return i;
-}
-
-static void client_serverbrowse_sort()
-{
-	int i;
-	
-	/* create filtered list */
-	client_serverbrowse_filter();
-	
-	/* sort */
-	if(config.b_sort == BROWSESORT_NAME)
-		qsort(sorted_serverlist, num_sorted_servers, sizeof(int), client_serverbrowse_sort_compare_name);
-	else if(config.b_sort == BROWSESORT_PING)
-		qsort(sorted_serverlist, num_sorted_servers, sizeof(int), client_serverbrowse_sort_compare_ping);
-	else if(config.b_sort == BROWSESORT_MAP)
-		qsort(sorted_serverlist, num_sorted_servers, sizeof(int), client_serverbrowse_sort_compare_map);
-	else if(config.b_sort == BROWSESORT_NUMPLAYERS)
-		qsort(sorted_serverlist, num_sorted_servers, sizeof(int), client_serverbrowse_sort_compare_numplayers);
-	
-	/* set indexes */
-	for(i = 0; i < num_sorted_servers; i++)
-		serverlist[sorted_serverlist[i]]->info.sorted_index = i;
-	
-	strncpy(filterstring, config.b_filter_string, sizeof(filterstring)-1); 
-	sorthash = client_serverbrowse_sorthash();
-}
-
-static void client_serverbrowse_remove_request(SERVERENTRY *entry)
-{
-	if(entry->prev_req || entry->next_req || first_req_server == entry)
-	{
-		if(entry->prev_req)
-			entry->prev_req->next_req = entry->next_req;
-		else
-			first_req_server = entry->next_req;
-			
-		if(entry->next_req)
-			entry->next_req->prev_req = entry->prev_req;
-		else
-			last_req_server = entry->prev_req;
-			
-		entry->prev_req = 0;
-		entry->next_req = 0;
-		num_requests--;
-	}
-}
-
-static void client_serverbrowse_set(NETADDR4 *addr, int request, SERVER_INFO *info)
-{
-	int hash = addr->ip[0];
-	SERVERENTRY *entry = serverlist_ip[hash];
-	while(entry)
-	{
-		if(net_addr4_cmp(&entry->addr, addr) == 0)
-		{
-			/* update the server that we already have */
-			entry->info = *info;
-			if(!request)
-			{
-				entry->info.latency = (time_get()-entry->request_time)*1000/time_freq();
-				client_serverbrowse_remove_request(entry);
-			}
-			
-			entry->got_info = 1;
-			client_serverbrowse_sort();
-			return;
-		}
-		entry = entry->next_ip;
-	}
-
-	/* create new entry */	
-	entry = (SERVERENTRY *)memheap_allocate(serverlist_heap, sizeof(SERVERENTRY));
-	mem_zero(entry, sizeof(SERVERENTRY));
-	
-	/* set the info */
-	entry->addr = *addr;
-	entry->info = *info;
-
-	/* add to the hash list */	
-	entry->next_ip = serverlist_ip[hash];
-	serverlist_ip[hash] = entry;
-	
-	if(num_servers == num_server_capacity)
-	{
-		num_server_capacity += 100;
-		SERVERENTRY **newlist = mem_alloc(num_server_capacity*sizeof(SERVERENTRY*), 1);
-		memcpy(newlist, serverlist, num_servers*sizeof(SERVERENTRY*));
-		mem_free(serverlist);
-		serverlist = newlist;
-	}
-	
-	/* add to list */
-	serverlist[num_servers] = entry;
-	entry->info.server_index = num_servers;
-	num_servers++;
-	
-	/* */
-	if(request)
-	{
-		/* add it to the list of servers that we should request info from */
-		entry->prev_req = last_req_server;
-		if(last_req_server)
-			last_req_server->next_req = entry;
-		else
-			first_req_server = entry;
-		last_req_server = entry;
-		
-		num_requests++;
-	}
-	
-	client_serverbrowse_sort();
-}
-
-void client_serverbrowse_refresh(int lan)
-{
-	/* clear out everything */
-	if(serverlist_heap)
-		memheap_destroy(serverlist_heap);
-	serverlist_heap = memheap_create();
-	num_servers = 0;
-	num_sorted_servers = 0;
-	mem_zero(serverlist_ip, sizeof(serverlist_ip));
-	first_req_server = 0;
-	last_req_server = 0;
-	num_requests = 0;
-	
-	
-	/* */
-	serverlist_lan = lan;
-	
-	if(serverlist_lan)
-	{
-		if(config.debug)
-			dbg_msg("client", "broadcasting for servers");
-		NETPACKET packet;
-		packet.client_id = -1;
-		mem_zero(&packet, sizeof(packet));
-		packet.address.ip[0] = 0;
-		packet.address.ip[1] = 0;
-		packet.address.ip[2] = 0;
-		packet.address.ip[3] = 0;
-		packet.address.port = 8303;
-		packet.flags = PACKETFLAG_CONNLESS;
-		packet.data_size = sizeof(SERVERBROWSE_GETINFO);
-		packet.data = SERVERBROWSE_GETINFO;
-		netclient_send(net, &packet);	
-		
-		// reset the list
-		//servers.num = 0;
-	}
-	else
-	{
-		if(config.debug)
-			dbg_msg("client", "requesting server list");
-		NETPACKET packet;
-		mem_zero(&packet, sizeof(packet));
-		packet.client_id = -1;
-		packet.address = master_server;
-		packet.flags = PACKETFLAG_CONNLESS;
-		packet.data_size = sizeof(SERVERBROWSE_GETLIST);
-		packet.data = SERVERBROWSE_GETLIST;
-		netclient_send(net, &packet);	
-		
-		// reset the list
-		//servers.num = 0;
-	}
-}
-
-
-static void client_serverbrowse_request(SERVERENTRY *entry)
-{
-	if(config.debug)
-	{
-		dbg_msg("client", "requesting server info from %d.%d.%d.%d:%d",
-			entry->addr.ip[0], entry->addr.ip[1], entry->addr.ip[2],
-			entry->addr.ip[3], entry->addr.port);
-	}
-	
-	NETPACKET p;
-	p.client_id = -1;
-	p.address = entry->addr;
-	p.flags = PACKETFLAG_CONNLESS;
-	p.data_size = sizeof(SERVERBROWSE_GETINFO);
-	p.data = SERVERBROWSE_GETINFO;
-	netclient_send(net, &p);
-	entry->request_time = time_get();
-}
-
-static void client_serverbrowse_update()
-{
-	int64 timeout = time_freq();
-	int64 now = time_get();
-	int count;
-	
-	SERVERENTRY *entry, *next;
-	
-	/* do timeouts */
-	entry = first_req_server;
-	while(1)
-	{
-		if(!entry) // no more entries
-			break;
-			
-		next = entry->next_req;
-		
-		if(entry->request_time && entry->request_time+timeout < now)
-		{
-			/* timeout */
-			client_serverbrowse_remove_request(entry);
-			num_requests--;
-		}
-			
-		entry = next;
-	}
-
-	/* do timeouts */
-	entry = first_req_server;
-	count = 0;
-	while(1)
-	{
-		if(!entry) // no more entries
-			break;
-			
-		if(count == config.b_max_requests) // no more then 10 concurrent requests
-			break;
-			
-		if(entry->request_time == 0)
-			client_serverbrowse_request(entry);
-		
-		count++;
-		entry = entry->next_req;
-	}
-	
-	/* check if we need to resort */
-	/* TODO: remove the strcmp */
-	if(sorthash != client_serverbrowse_sorthash() || strcmp(filterstring, config.b_filter_string) != 0)
-		client_serverbrowse_sort();
-}
-
 // ------ state handling -----
 static int state;
 int client_state() { return state; }
@@ -814,12 +443,11 @@ static void client_debug_render()
 	static float frametime_avg = 0;
 	frametime_avg = frametime_avg*0.9f + frametime*0.1f;
 	char buffer[512];
-	sprintf(buffer, "ticks: %8d %8d send: %6d recv: %6d snaploss: %d %c  mem %dk   gfxmem: %dk  fps: %3d",
+	sprintf(buffer, "ticks: %8d %8d send: %6d recv: %6d snaploss: %d  mem %dk   gfxmem: %dk  fps: %3d",
 		current_tick, current_predtick,
 		(current.send_bytes-prev.send_bytes)*10,
 		(current.recv_bytes-prev.recv_bytes)*10,
 		snaploss,
-		extra_polating?'E':' ',
 		mem_allocated()/1024,
 		gfx_memory_usage()/1024,
 		(int)(1.0f/frametime_avg));
@@ -1147,8 +775,6 @@ static void client_run(const char *direct_connect_server)
 	local_start_time = time_get();
 	snapshot_part = 0;
 	
-	client_serverbrowse_init();
-	
 	// init graphics and sound
 	if(!gfx_init())
 		return;
@@ -1171,9 +797,6 @@ static void client_run(const char *direct_connect_server)
 	mem_zero(&bindaddr, sizeof(bindaddr));
 	net = netclient_open(bindaddr, 0);
 	
-	//
-	net_host_lookup(config.masterserver, MASTERSERVER_PORT, &master_server);
-
 	// connect to the server if wanted
 	if(direct_connect_server)
 		client_connect(direct_connect_server);
@@ -1218,20 +841,12 @@ static void client_run(const char *direct_connect_server)
 						}
 					}
 					else
-					{
-						extra_polating = 1;
 						break;
-					}
 				}
 				else
-				{
-					extra_polating = 0;
 					break;
-				}
 			}
 
-			//tg_add(&game_time_graph, now, extra_polating);
-			
 			if(snapshots[SNAP_CURRENT] && snapshots[SNAP_PREV])
 			{
 				int64 curtick_start = (snapshots[SNAP_CURRENT]->tick)*time_freq()/50;
diff --git a/src/engine/client/snd.c b/src/engine/client/snd.c
index e11ace52..77844367 100644
--- a/src/engine/client/snd.c
+++ b/src/engine/client/snd.c
@@ -277,6 +277,9 @@ int snd_init()
 {
 	PaStreamParameters params;
 	PaError err = Pa_Initialize();
+
+	sound_lock = lock_create();
+
 	params.device = Pa_GetDefaultOutputDevice();
 	if(params.device < 0)
 		return 1;
@@ -285,7 +288,6 @@ int snd_init()
 	params.suggestedLatency = Pa_GetDeviceInfo(params.device)->defaultLowOutputLatency;
 	params.hostApiSpecificStreamInfo = 0x0;
 
-	sound_lock = lock_create();
 
 	err = Pa_OpenStream(
 			&stream,        /* passes back stream pointer */
diff --git a/src/engine/client/srvbrowse.c b/src/engine/client/srvbrowse.c
new file mode 100644
index 00000000..cf0a4467
--- /dev/null
+++ b/src/engine/client/srvbrowse.c
@@ -0,0 +1,383 @@
+#include <engine/system.h>
+#include <engine/network.h>
+#include <engine/interface.h>
+#include <engine/config.h>
+#include <engine/memheap.h>
+
+#include <mastersrv/mastersrv.h>
+
+#include <string.h>
+#include <stdlib.h>
+
+extern NETCLIENT *net;
+
+
+/* ------ server browse ---- */
+/* TODO: move all this to a separate file */
+
+typedef struct SERVERENTRY_t SERVERENTRY;
+struct SERVERENTRY_t
+{
+	NETADDR4 addr;
+	int64 request_time;
+	int got_info;
+	SERVER_INFO info;
+	
+	SERVERENTRY *next_ip; // ip hashed list
+	
+	SERVERENTRY *prev_req; // request list
+	SERVERENTRY *next_req;
+};
+
+static HEAP *serverlist_heap = 0;
+static SERVERENTRY **serverlist = 0;
+static int *sorted_serverlist = 0;
+
+static SERVERENTRY *serverlist_ip[256] = {0}; // ip hash list
+
+static SERVERENTRY *first_req_server = 0; // request list
+static SERVERENTRY *last_req_server = 0;
+static int num_requests = 0;
+
+static int num_sorted_servers = 0;
+static int num_sorted_servers_capacity = 0;
+static int num_servers = 0;
+static int num_server_capacity = 0;
+
+static int sorthash = 0;
+static char filterstring[64] = {0};
+
+static int serverlist_lan = 1;
+
+int client_serverbrowse_num() { return num_servers; }
+
+SERVER_INFO *client_serverbrowse_get(int index)
+{
+	if(index < 0 || index >= num_servers)
+		return 0;
+	return &serverlist[index]->info;
+}
+
+int client_serverbrowse_sorted_num() { return num_sorted_servers; }
+
+SERVER_INFO *client_serverbrowse_sorted_get(int index)
+{
+	if(index < 0 || index >= num_sorted_servers)
+		return 0;
+	return &serverlist[sorted_serverlist[index]]->info;
+}
+
+
+int client_serverbrowse_num_requests()
+{
+	return num_requests;
+}
+
+static int client_serverbrowse_sort_compare_name(const void *ai, const void *bi)
+{
+	SERVERENTRY *a = serverlist[*(const int*)ai];
+	SERVERENTRY *b = serverlist[*(const int*)bi];
+	return strcmp(a->info.name, b->info.name);
+}
+
+static int client_serverbrowse_sort_compare_map(const void *ai, const void *bi)
+{
+	SERVERENTRY *a = serverlist[*(const int*)ai];
+	SERVERENTRY *b = serverlist[*(const int*)bi];
+	return strcmp(a->info.map, b->info.map);
+}
+
+static int client_serverbrowse_sort_compare_ping(const void *ai, const void *bi)
+{
+	SERVERENTRY *a = serverlist[*(const int*)ai];
+	SERVERENTRY *b = serverlist[*(const int*)bi];
+	return a->info.latency > b->info.latency;
+}
+
+static int client_serverbrowse_sort_compare_numplayers(const void *ai, const void *bi)
+{
+	SERVERENTRY *a = serverlist[*(const int*)ai];
+	SERVERENTRY *b = serverlist[*(const int*)bi];
+	return a->info.num_players > b->info.num_players;
+}
+
+static void client_serverbrowse_filter()
+{
+	int i = 0;
+	num_sorted_servers = 0;
+
+	/* allocate the sorted list */	
+	if(num_sorted_servers_capacity < num_servers)
+	{
+		if(sorted_serverlist)
+			mem_free(sorted_serverlist);
+		num_sorted_servers_capacity = num_servers;
+		sorted_serverlist = mem_alloc(num_sorted_servers_capacity*sizeof(int), 1);
+	}
+	
+	/* filter the servers */
+	for(i = 0; i < num_servers; i++)
+	{
+		int filtered = 0;
+
+		if(config.b_filter_empty && serverlist[i]->info.num_players == 0)
+			filtered = 1;
+		else if(config.b_filter_full && serverlist[i]->info.num_players == serverlist[i]->info.max_players)
+			filtered = 1;
+		else if(config.b_filter_pw && serverlist[i]->info.flags&1)
+			filtered = 1;
+		else if(config.b_filter_string[0] != 0)
+		{
+			if(strstr(serverlist[i]->info.name, config.b_filter_string) == 0)
+				filtered = 1;
+		}
+			
+		if(filtered == 0)
+			sorted_serverlist[num_sorted_servers++] = i;
+	}
+}
+
+static int client_serverbrowse_sorthash()
+{
+	int i = config.b_sort&3;
+	i |= config.b_filter_empty<<4;
+	i |= config.b_filter_full<<5;
+	i |= config.b_filter_pw<<6;
+	return i;
+}
+
+static void client_serverbrowse_sort()
+{
+	int i;
+	
+	/* create filtered list */
+	client_serverbrowse_filter();
+	
+	/* sort */
+	if(config.b_sort == BROWSESORT_NAME)
+		qsort(sorted_serverlist, num_sorted_servers, sizeof(int), client_serverbrowse_sort_compare_name);
+	else if(config.b_sort == BROWSESORT_PING)
+		qsort(sorted_serverlist, num_sorted_servers, sizeof(int), client_serverbrowse_sort_compare_ping);
+	else if(config.b_sort == BROWSESORT_MAP)
+		qsort(sorted_serverlist, num_sorted_servers, sizeof(int), client_serverbrowse_sort_compare_map);
+	else if(config.b_sort == BROWSESORT_NUMPLAYERS)
+		qsort(sorted_serverlist, num_sorted_servers, sizeof(int), client_serverbrowse_sort_compare_numplayers);
+	
+	/* set indexes */
+	for(i = 0; i < num_sorted_servers; i++)
+		serverlist[sorted_serverlist[i]]->info.sorted_index = i;
+	
+	strncpy(filterstring, config.b_filter_string, sizeof(filterstring)-1); 
+	sorthash = client_serverbrowse_sorthash();
+}
+
+static void client_serverbrowse_remove_request(SERVERENTRY *entry)
+{
+	if(entry->prev_req || entry->next_req || first_req_server == entry)
+	{
+		if(entry->prev_req)
+			entry->prev_req->next_req = entry->next_req;
+		else
+			first_req_server = entry->next_req;
+			
+		if(entry->next_req)
+			entry->next_req->prev_req = entry->prev_req;
+		else
+			last_req_server = entry->prev_req;
+			
+		entry->prev_req = 0;
+		entry->next_req = 0;
+		num_requests--;
+	}
+}
+
+void client_serverbrowse_set(NETADDR4 *addr, int request, SERVER_INFO *info)
+{
+	int hash = addr->ip[0];
+	SERVERENTRY *entry = serverlist_ip[hash];
+	while(entry)
+	{
+		if(net_addr4_cmp(&entry->addr, addr) == 0)
+		{
+			/* update the server that we already have */
+			entry->info = *info;
+			if(!request)
+			{
+				entry->info.latency = (time_get()-entry->request_time)*1000/time_freq();
+				client_serverbrowse_remove_request(entry);
+			}
+			
+			entry->got_info = 1;
+			client_serverbrowse_sort();
+			return;
+		}
+		entry = entry->next_ip;
+	}
+
+	/* create new entry */	
+	entry = (SERVERENTRY *)memheap_allocate(serverlist_heap, sizeof(SERVERENTRY));
+	mem_zero(entry, sizeof(SERVERENTRY));
+	
+	/* set the info */
+	entry->addr = *addr;
+	entry->info = *info;
+
+	/* add to the hash list */	
+	entry->next_ip = serverlist_ip[hash];
+	serverlist_ip[hash] = entry;
+	
+	if(num_servers == num_server_capacity)
+	{
+		num_server_capacity += 100;
+		SERVERENTRY **newlist = mem_alloc(num_server_capacity*sizeof(SERVERENTRY*), 1);
+		memcpy(newlist, serverlist, num_servers*sizeof(SERVERENTRY*));
+		mem_free(serverlist);
+		serverlist = newlist;
+	}
+	
+	/* add to list */
+	serverlist[num_servers] = entry;
+	entry->info.server_index = num_servers;
+	num_servers++;
+	
+	/* */
+	if(request)
+	{
+		/* add it to the list of servers that we should request info from */
+		entry->prev_req = last_req_server;
+		if(last_req_server)
+			last_req_server->next_req = entry;
+		else
+			first_req_server = entry;
+		last_req_server = entry;
+		
+		num_requests++;
+	}
+	
+	client_serverbrowse_sort();
+}
+
+void client_serverbrowse_refresh(int lan)
+{
+	/* clear out everything */
+	if(serverlist_heap)
+		memheap_destroy(serverlist_heap);
+	serverlist_heap = memheap_create();
+	num_servers = 0;
+	num_sorted_servers = 0;
+	mem_zero(serverlist_ip, sizeof(serverlist_ip));
+	first_req_server = 0;
+	last_req_server = 0;
+	num_requests = 0;
+	
+	
+	/* */
+	serverlist_lan = lan;
+	
+	if(serverlist_lan)
+	{
+		NETPACKET packet;
+		packet.client_id = -1;
+		mem_zero(&packet, sizeof(packet));
+		packet.address.ip[0] = 0;
+		packet.address.ip[1] = 0;
+		packet.address.ip[2] = 0;
+		packet.address.ip[3] = 0;
+		packet.address.port = 8303;
+		packet.flags = PACKETFLAG_CONNLESS;
+		packet.data_size = sizeof(SERVERBROWSE_GETINFO);
+		packet.data = SERVERBROWSE_GETINFO;
+		netclient_send(net, &packet);	
+
+		if(config.debug)
+			dbg_msg("client", "broadcasting for servers");
+	}
+	else
+	{
+		NETADDR4 master_server;
+		NETPACKET p;
+
+		net_host_lookup(config.masterserver, MASTERSERVER_PORT, &master_server);
+
+		mem_zero(&p, sizeof(p));
+		p.client_id = -1;
+		p.address = master_server;
+		p.flags = PACKETFLAG_CONNLESS;
+		p.data_size = sizeof(SERVERBROWSE_GETLIST);
+		p.data = SERVERBROWSE_GETLIST;
+		netclient_send(net, &p);	
+
+		if(config.debug)
+			dbg_msg("client", "requesting server list");
+	}
+}
+
+static void client_serverbrowse_request(SERVERENTRY *entry)
+{
+	if(config.debug)
+	{
+		dbg_msg("client", "requesting server info from %d.%d.%d.%d:%d",
+			entry->addr.ip[0], entry->addr.ip[1], entry->addr.ip[2],
+			entry->addr.ip[3], entry->addr.port);
+	}
+	
+	NETPACKET p;
+	p.client_id = -1;
+	p.address = entry->addr;
+	p.flags = PACKETFLAG_CONNLESS;
+	p.data_size = sizeof(SERVERBROWSE_GETINFO);
+	p.data = SERVERBROWSE_GETINFO;
+	netclient_send(net, &p);
+	entry->request_time = time_get();
+}
+
+void client_serverbrowse_update()
+{
+	int64 timeout = time_freq();
+	int64 now = time_get();
+	int count;
+	
+	SERVERENTRY *entry, *next;
+	
+	/* do timeouts */
+	entry = first_req_server;
+	while(1)
+	{
+		if(!entry) // no more entries
+			break;
+			
+		next = entry->next_req;
+		
+		if(entry->request_time && entry->request_time+timeout < now)
+		{
+			/* timeout */
+			client_serverbrowse_remove_request(entry);
+			num_requests--;
+		}
+			
+		entry = next;
+	}
+
+	/* do timeouts */
+	entry = first_req_server;
+	count = 0;
+	while(1)
+	{
+		if(!entry) // no more entries
+			break;
+			
+		if(count == config.b_max_requests) // no more then 10 concurrent requests
+			break;
+			
+		if(entry->request_time == 0)
+			client_serverbrowse_request(entry);
+		
+		count++;
+		entry = entry->next_req;
+	}
+	
+	/* check if we need to resort */
+	/* TODO: remove the strcmp */
+	if(sorthash != client_serverbrowse_sorthash() || strcmp(filterstring, config.b_filter_string) != 0)
+		client_serverbrowse_sort();
+}