about summary refs log tree commit diff
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
parent30a7246f2fd5e2141de2c37f01b491abe374f3f9 (diff)
downloadzcatch-a67738e9801a4485cfaf68012279cd5042dc2ab9.tar.gz
zcatch-a67738e9801a4485cfaf68012279cd5042dc2ab9.zip
general fixes. fixed scoreboard
-rw-r--r--datasrc/teewars.ds4
-rw-r--r--src/engine/client/client.c403
-rw-r--r--src/engine/client/snd.c4
-rw-r--r--src/engine/client/srvbrowse.c383
-rw-r--r--src/engine/config_variables.h2
-rw-r--r--src/engine/interface.h2
-rw-r--r--src/engine/server/server.c34
-rw-r--r--src/engine/snapshot.c2
-rw-r--r--src/game/client/game_client.cpp25
-rw-r--r--src/game/client/mapres_tilemap.h6
-rw-r--r--src/game/game_protocol.h2
-rw-r--r--src/game/server/game_server.cpp5
-rw-r--r--src/game/server/srv_common.h2
-rw-r--r--src/game/server/srv_ctf.cpp1
-rw-r--r--src/game/server/srv_tdm.cpp11
15 files changed, 473 insertions, 413 deletions
diff --git a/datasrc/teewars.ds b/datasrc/teewars.ds
index a2e1afaa..2212d464 100644
--- a/datasrc/teewars.ds
+++ b/datasrc/teewars.ds
@@ -554,6 +554,10 @@ sprites {
 		powerup_weapon 3 0 6 2
 		powerup_ninja 3 10 7 2
 		powerup_timefield 3 0 6 2
+
+		flag_blue 12 8 4 8
+		flag_red 16 8 4 8
+
 	}
 	
 	tees images.char_default 16 64 {
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();
+}
diff --git a/src/engine/config_variables.h b/src/engine/config_variables.h
index 5b855bc3..8fbab733 100644
--- a/src/engine/config_variables.h
+++ b/src/engine/config_variables.h
@@ -40,5 +40,5 @@ MACRO_CONFIG_INT(sv_port, 8303, 0, 0)
 MACRO_CONFIG_INT(sv_sendheartbeats, 1, 0, 1)
 MACRO_CONFIG_STR(sv_map, 128, "dm1")
 
-MACRO_CONFIG_INT(sv_max_clients, 8, 1, 8)
+MACRO_CONFIG_INT(sv_max_clients, 8, 1, 16)
 
diff --git a/src/engine/interface.h b/src/engine/interface.h
index c1a0b282..8c272000 100644
--- a/src/engine/interface.h
+++ b/src/engine/interface.h
@@ -810,6 +810,8 @@ int client_serverbrowse_num();
 
 int client_serverbrowse_num_requests();
 
+void client_serverbrowse_update();
+
 /* undocumented graphics stuff */
 void gfx_pretty_text(float x, float y, float size, const char *text, int max_width);
 float gfx_pretty_text_width(float size, const char *text, int length);
diff --git a/src/engine/server/server.c b/src/engine/server/server.c
index 3bcb79dd..59074699 100644
--- a/src/engine/server/server.c
+++ b/src/engine/server/server.c
@@ -284,7 +284,7 @@ static void server_do_snap()
 			
 			int input_predtick = -1;
 			int64 timeleft = 0;
-			for(k = 0; k < 200; k++) // TODO: do this better
+			for(k = 0; k < 200; k++) /* TODO: do this better */
 			{
 				if(clients[i].inputs[k].game_tick == current_tick)
 				{
@@ -460,7 +460,6 @@ static void server_process_client_packet(NETPACKET *packet)
 			for(i = 0; i < size/4; i++)
 				input->data[i] = msg_unpack_int();
 				
-			//time_get()
 			clients[cid].current_input++;
 			clients[cid].current_input %= 200;
 		}
@@ -489,13 +488,10 @@ static void server_process_client_packet(NETPACKET *packet)
 static void server_send_serverinfo(NETADDR4 *addr)
 {
 	NETPACKET packet;
-	
 	PACKER p;
-	packer_reset(&p);
-	packer_add_raw(&p, SERVERBROWSE_INFO, sizeof(SERVERBROWSE_INFO));
-	packer_add_string(&p, config.sv_name, 128);
-	packer_add_string(&p, config.sv_map, 32);
-	packer_add_int(&p, netserver_max_clients(net)); /* max_players */
+	char buf[128];
+
+	/* count the players */	
 	int c = 0;
 	int i;
 	for(i = 0; i < MAX_CLIENTS; i++)
@@ -503,7 +499,27 @@ static void server_send_serverinfo(NETADDR4 *addr)
 		if(!clients[i].state != SRVCLIENT_STATE_EMPTY)
 			c++;
 	}
-	packer_add_int(&p, c); /* num_players */
+	
+	packer_reset(&p);
+	packer_add_string(&p, mods_net_version(), 32);
+	packer_add_string(&p, config.sv_name, 64);
+	packer_add_string(&p, config.sv_map, 32);
+	packer_add_string(&p, "0", 2); /* gametype */
+	packer_add_string(&p, "0", 2); /* flags */
+	packer_add_string(&p, "0", 4); /* progression */
+	
+	sprintf(buf, "%d", c); packer_add_string(&p, buf, 3);  /* num players */
+	sprintf(buf, "%d", netserver_max_clients(net)); packer_add_string(&p, buf, 3); /* max players */
+
+	for(i = 0; i < MAX_CLIENTS; i++)
+	{
+		if(!clients[i].state != SRVCLIENT_STATE_EMPTY)
+		{
+			packer_add_string(&p, clients[i].name, 48);  /* player name */
+			packer_add_string(&p, "0", 6); /* score */
+		}
+	}
+	
 	
 	packet.client_id = -1;
 	packet.address = *addr;
diff --git a/src/engine/snapshot.c b/src/engine/snapshot.c
index b42b0157..bd6f0c8e 100644
--- a/src/engine/snapshot.c
+++ b/src/engine/snapshot.c
@@ -136,7 +136,7 @@ static void undiff_item(int *past, int *diff, int *out, int size)
 }
 
 
-// TODO: OPT: this should be made much faster
+/* TODO: OPT: this should be made much faster */
 int snapshot_create_delta(SNAPSHOT *from, SNAPSHOT *to, void *dstdata)
 {
 	SNAPSHOT_DELTA *delta = (SNAPSHOT_DELTA *)dstdata;
diff --git a/src/game/client/game_client.cpp b/src/game/client/game_client.cpp
index 3288fa65..8a2c5523 100644
--- a/src/game/client/game_client.cpp
+++ b/src/game/client/game_client.cpp
@@ -1562,10 +1562,31 @@ void render_scoreboard(obj_game *gameobj, float x, float y, float w, int team, c
 	}
 
 	float tw = gfx_pretty_text_width( 64, title, -1);
-	gfx_pretty_text(x+w/2-tw/2, y, 64, title, -1);
-	
 
+	if(team == -1)
+	{
+		gfx_pretty_text(x+w/2-tw/2, y, 64, title, -1);
+	}
+	else
+	{
+		gfx_pretty_text(x+10, y, 64, title, -1);
+		
+		char buf[128];
+		sprintf(buf, "%d", gameobj->teamscore[team&1]);
+		tw = gfx_pretty_text_width(64, buf, -1);
+		gfx_pretty_text(x+w-tw-40, y, 64, buf, -1);
+	}
+	
 	y += 64.0f;
+	
+	/*
+	if(team)
+	{
+		char buf[128];
+		sprintf(buf, "%4d", gameobj->teamscore[team&1]);
+		gfx_pretty_text(x+w/2-tw/2, y, 32, buf, -1);
+	}*/
+
 
 	// find players
 	const obj_player *players[MAX_CLIENTS] = {0};
diff --git a/src/game/client/mapres_tilemap.h b/src/game/client/mapres_tilemap.h
index 6e9d81be..df2da7a3 100644
--- a/src/game/client/mapres_tilemap.h
+++ b/src/game/client/mapres_tilemap.h
@@ -7,6 +7,12 @@ int tilemap_init();
 // renders the tilemaps
 void tilemap_render(float scale, int fg);
 
+enum
+{
+	TILEFLAG_VFLIP=1,
+	TILEFLAG_HFLIP=2,
+};
+
 struct mapres_tilemap
 {
 	int image;
diff --git a/src/game/game_protocol.h b/src/game/game_protocol.h
index f7249501..925de7b8 100644
--- a/src/game/game_protocol.h
+++ b/src/game/game_protocol.h
@@ -124,6 +124,8 @@ struct obj_game
 	int score_limit;
 	int time_limit;
 	int gametype;
+	
+	int teamscore[2];
 };
 
 struct obj_projectile
diff --git a/src/game/server/game_server.cpp b/src/game/server/game_server.cpp
index 0e42614e..78b95de3 100644
--- a/src/game/server/game_server.cpp
+++ b/src/game/server/game_server.cpp
@@ -306,6 +306,8 @@ void gameobject::startround()
 	sudden_death = 0;
 	game_over_tick = -1;
 	world->paused = false;
+	teamscore[0] = 0;
+	teamscore[1] = 0;
 }
 
 void gameobject::post_reset()
@@ -344,6 +346,9 @@ void gameobject::snap(int snapping_client)
 	game->time_limit = config.timelimit;
 	game->round_start_tick = round_start_tick;
 	game->gametype = gametype;
+	
+	game->teamscore[0] = teamscore[0];
+	game->teamscore[1] = teamscore[1];
 }
 
 int gameobject::getteam(int notthisid)
diff --git a/src/game/server/srv_common.h b/src/game/server/srv_common.h
index 7b6e7e1e..22aa4535 100644
--- a/src/game/server/srv_common.h
+++ b/src/game/server/srv_common.h
@@ -117,6 +117,8 @@ protected:
 	int game_over_tick;
 	int sudden_death;
 	
+	int teamscore[2];
+	
 public:
 	int gametype;
 	gameobject();
diff --git a/src/game/server/srv_ctf.cpp b/src/game/server/srv_ctf.cpp
index 7a13b877..1831db31 100644
--- a/src/game/server/srv_ctf.cpp
+++ b/src/game/server/srv_ctf.cpp
@@ -59,6 +59,7 @@ void gameobject_ctf::tick()
 				if(distance(f->pos, flags[fi^1]->pos) < 24)
 				{
 					// CAPTURE! \o/
+					teamscore[fi^1]++;
 					for(int i = 0; i < 2; i++)
 						flags[i]->reset();
 				}
diff --git a/src/game/server/srv_tdm.cpp b/src/game/server/srv_tdm.cpp
index ca1a5a67..3ed35dca 100644
--- a/src/game/server/srv_tdm.cpp
+++ b/src/game/server/srv_tdm.cpp
@@ -7,22 +7,23 @@ void gameobject_tdm::tick()
 	if(game_over_tick == -1)
 	{
 		// game is running
+		teamscore[0] = 0;
+		teamscore[1] = 0;
 		
 		// gather some stats
-		int totalscore[2] = {0,0};
 		int topscore_count = 0;
 		for(int i = 0; i < MAX_CLIENTS; i++)
 		{
 			if(players[i].client_id != -1)
-				totalscore[players[i].team] += players[i].score;
+				teamscore[players[i].team] += players[i].score;
 		}
-		if (totalscore[0] >= config.scorelimit)
+		if (teamscore[0] >= config.scorelimit)
 			topscore_count++;
-		if (totalscore[1] >= config.scorelimit)
+		if (teamscore[1] >= config.scorelimit)
 			topscore_count++;
 		
 		// check score win condition
-		if((config.scorelimit > 0 && (totalscore[0] >= config.scorelimit || totalscore[1] >= config.scorelimit)) ||
+		if((config.scorelimit > 0 && (teamscore[0] >= config.scorelimit || teamscore[1] >= config.scorelimit)) ||
 			(config.timelimit > 0 && (server_tick()-round_start_tick) >= config.timelimit*server_tickspeed()*60))
 		{
 			if(topscore_count == 1)