about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMagnus Auvinen <magnus.auvinen@gmail.com>2009-05-31 09:44:20 +0000
committerMagnus Auvinen <magnus.auvinen@gmail.com>2009-05-31 09:44:20 +0000
commit4bb1df318905f491740f4298c69cda317fb53fcb (patch)
tree486c4edf2d6af2089ffab60a7422d5e7abefa891
parentb28ede2da2c42643c5aa710a8076f0249d48c9e4 (diff)
downloadzcatch-4bb1df318905f491740f4298c69cda317fb53fcb.tar.gz
zcatch-4bb1df318905f491740f4298c69cda317fb53fcb.zip
moved 0.5 branch to trunk
-rw-r--r--default.bam4
-rw-r--r--other/sdl/sdl.bam1
-rw-r--r--src/engine/client/ec_client.c2
-rw-r--r--src/engine/client/ec_gfx.c21
-rw-r--r--src/engine/client/ec_inp.c16
-rw-r--r--src/engine/client/ec_srvbrowse.c17
-rw-r--r--src/engine/e_config_variables.h10
-rw-r--r--src/engine/e_network.c6
-rw-r--r--src/engine/server/es_server.c354
-rw-r--r--src/game/client/components/chat.cpp13
-rw-r--r--src/game/client/components/chat.hpp2
-rw-r--r--src/game/client/components/console.cpp7
-rw-r--r--src/game/client/components/hud.cpp2
-rw-r--r--src/game/client/components/menus_browser.cpp7
-rw-r--r--src/game/client/components/players.cpp2
-rw-r--r--src/game/client/components/scoreboard.cpp34
-rw-r--r--src/game/client/render.hpp4
-rw-r--r--src/game/editor/ed_editor.cpp25
-rw-r--r--src/game/server/entities/character.cpp8
-rw-r--r--src/game/server/gamemodes/ctf.cpp7
-rw-r--r--src/game/server/hooks.cpp2
-rw-r--r--src/game/version.hpp2
22 files changed, 331 insertions, 215 deletions
diff --git a/default.bam b/default.bam
index dca130e0..71bec72f 100644
--- a/default.bam
+++ b/default.bam
@@ -269,20 +269,24 @@ if platform == "macosx"  and arch == "ia32" then
 	debug_settings_ppc.config_ext = "_ppc_d"
 	debug_settings_ppc.cc.flags:Add("-arch ppc")
 	debug_settings_ppc.link.flags:Add("-arch ppc")
+	debug_settings_ppc.cc.defines:Add("CONF_DEBUG")
 
 	release_settings_ppc = release_settings:Copy()
 	release_settings_ppc.config_name = "release_ppc"
 	release_settings_ppc.config_ext = "_ppc"
 	release_settings_ppc.cc.flags:Add("-arch ppc")
 	release_settings_ppc.link.flags:Add("-arch ppc")
+	release_settings_ppc.cc.defines:Add("CONF_RELEASE")
 
 	debug_settings_x86 = debug_settings:Copy()
 	debug_settings_x86.config_name = "debug_x86"
 	debug_settings_x86.config_ext = "_x86_d"
+	debug_settings_x86.cc.defines:Add("CONF_DEBUG")
 
 	release_settings_x86 = release_settings:Copy()
 	release_settings_x86.config_name = "release_x86"
 	release_settings_x86.config_ext = "_x86"
+	release_settings_x86.cc.defines:Add("CONF_RELEASE")
 
 	ppc_d = build(debug_settings_ppc)
 	x86_d = build(debug_settings_x86)
diff --git a/other/sdl/sdl.bam b/other/sdl/sdl.bam
index 8330952c..be94209d 100644
--- a/other/sdl/sdl.bam
+++ b/other/sdl/sdl.bam
@@ -22,6 +22,7 @@ SDL = {
 			if platform == "macosx" then
 				option.value = 1
 				option.use_osxframework = 1
+				option.use_sdlconfig = nil
 			end
 		end
 		
diff --git a/src/engine/client/ec_client.c b/src/engine/client/ec_client.c
index 0a785df7..ad52d077 100644
--- a/src/engine/client/ec_client.c
+++ b/src/engine/client/ec_client.c
@@ -1362,6 +1362,7 @@ static void client_pump_network()
 		if(client_state() != CLIENTSTATE_OFFLINE && netclient_state(net) == NETSTATE_OFFLINE)
 		{
 			client_set_state(CLIENTSTATE_OFFLINE);
+			client_disconnect();
 			dbg_msg("client", "offline error='%s'", netclient_error_string(net));
 		}
 
@@ -1972,6 +1973,7 @@ static void con_serverdummy(void *result, void *user_data)
 static void client_register_commands()
 {
 	MACRO_REGISTER_COMMAND("quit", "", CFGFLAG_CLIENT, con_quit, 0x0, "Quit Teeworlds");
+	MACRO_REGISTER_COMMAND("exit", "", CFGFLAG_CLIENT, con_quit, 0x0, "Quit Teeworlds");
 	MACRO_REGISTER_COMMAND("connect", "s", CFGFLAG_CLIENT, con_connect, 0x0, "Connect to the specified host/ip");
 	MACRO_REGISTER_COMMAND("disconnect", "", CFGFLAG_CLIENT, con_disconnect, 0x0, "Disconnect from the server");
 	MACRO_REGISTER_COMMAND("ping", "", CFGFLAG_CLIENT, con_ping, 0x0, "Ping the current server");
diff --git a/src/engine/client/ec_gfx.c b/src/engine/client/ec_gfx.c
index 64840b2b..97dced87 100644
--- a/src/engine/client/ec_gfx.c
+++ b/src/engine/client/ec_gfx.c
@@ -252,11 +252,24 @@ int gfx_init()
 	if(config.dbg_stress)
 		no_gfx = 1;
 
-	if(SDL_Init(SDL_INIT_AUDIO|SDL_INIT_VIDEO) < 0)
 	{
-        dbg_msg("gfx", "unable to init SDL: %s", SDL_GetError());
-        return -1;
-    }
+		int systems = 0;
+		
+		if(!no_gfx)
+			systems |= SDL_INIT_VIDEO;
+			
+		if(config.snd_enable)
+			systems |= SDL_INIT_AUDIO;
+
+		if(config.cl_eventthread)
+			systems |= SDL_INIT_EVENTTHREAD;
+		
+		if(SDL_Init(systems) < 0)
+		{
+			dbg_msg("gfx", "unable to init SDL: %s", SDL_GetError());
+			return -1;
+		}
+	}
 	
     atexit(SDL_Quit);
 
diff --git a/src/engine/client/ec_inp.c b/src/engine/client/ec_inp.c
index 6aae34fc..4aea840a 100644
--- a/src/engine/client/ec_inp.c
+++ b/src/engine/client/ec_inp.c
@@ -16,26 +16,16 @@ static unsigned char input_state[2][1024] = {{0}, {0}};
 
 static int input_current = 0;
 static int input_grabbed = 0;
-static int input_use_grab = 0;
 
 static unsigned int last_release = 0;
 static unsigned int release_delta = -1;
 
 void inp_mouse_relative(int *x, int *y)
 {
-	static int last_x = 0, last_y = 0;
-	static int last_sens = 100.0f;
 	int nx = 0, ny = 0;
 	float sens = config.inp_mousesens/100.0f;
 	
-	if(last_sens != config.inp_mousesens)
-	{
-		last_x = (last_x/(float)last_sens)*(float)config.inp_mousesens;
-		last_y = (last_y/(float)last_sens)*(float)config.inp_mousesens;
-		last_sens = config.inp_mousesens;
-	}
-	
-	if(input_use_grab)
+	if(config.inp_grab)
 		SDL_GetRelativeMouseState(&nx, &ny);
 	else
 	{
@@ -101,7 +91,7 @@ void inp_mouse_mode_absolute()
 {
 	SDL_ShowCursor(1);
 	input_grabbed = 0;
-	if(input_use_grab)
+	if(config.inp_grab)
 		SDL_WM_GrabInput(SDL_GRAB_OFF);
 }
 
@@ -109,7 +99,7 @@ void inp_mouse_mode_relative()
 {
 	SDL_ShowCursor(0);
 	input_grabbed = 1;
-	if(input_use_grab)
+	if(config.inp_grab)
 		SDL_WM_GrabInput(SDL_GRAB_ON);
 }
 
diff --git a/src/engine/client/ec_srvbrowse.c b/src/engine/client/ec_srvbrowse.c
index 81712cb4..4a85e778 100644
--- a/src/engine/client/ec_srvbrowse.c
+++ b/src/engine/client/ec_srvbrowse.c
@@ -166,6 +166,22 @@ static void client_serverbrowse_filter()
 			filtered = 1;
 		else if(config.b_filter_pure && (strcmp(serverlist[i]->info.gametype, "DM") != 0 && strcmp(serverlist[i]->info.gametype, "TDM") != 0 && strcmp(serverlist[i]->info.gametype, "CTF") != 0))
 			filtered = 1;
+		else if(config.b_filter_pure_map &&
+			!(strcmp(serverlist[i]->info.map, "dm1") == 0 ||
+			strcmp(serverlist[i]->info.map, "dm2") == 0 ||
+			strcmp(serverlist[i]->info.map, "dm6") == 0 ||
+			strcmp(serverlist[i]->info.map, "dm7") == 0 ||
+			strcmp(serverlist[i]->info.map, "dm8") == 0 ||
+			strcmp(serverlist[i]->info.map, "dm9") == 0 ||
+			strcmp(serverlist[i]->info.map, "ctf1") == 0 ||
+			strcmp(serverlist[i]->info.map, "ctf2") == 0 ||
+			strcmp(serverlist[i]->info.map, "ctf3") == 0 ||
+			strcmp(serverlist[i]->info.map, "ctf4") == 0 ||
+			strcmp(serverlist[i]->info.map, "ctf5") == 0)
+		)
+		{
+			filtered = 1;
+		}
 		else if(config.b_filter_ping < serverlist[i]->info.latency)
 			filtered = 1;
 		else if(config.b_filter_compatversion && strncmp(serverlist[i]->info.version, modc_net_version(), 3) != 0)
@@ -229,6 +245,7 @@ static int client_serverbrowse_sorthash()
 	i |= config.b_sort_order<<7;
 	i |= config.b_filter_compatversion<<8;
 	i |= config.b_filter_pure<<9;
+	i |= config.b_filter_pure_map<<10;
 	i |= config.b_filter_ping<<16;
 	return i;
 }
diff --git a/src/engine/e_config_variables.h b/src/engine/e_config_variables.h
index 01989542..aa3da3f6 100644
--- a/src/engine/e_config_variables.h
+++ b/src/engine/e_config_variables.h
@@ -12,6 +12,10 @@ MACRO_CONFIG_STR(logfile, 128, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filename to log
 MACRO_CONFIG_INT(cl_cpu_throttle, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "")
 MACRO_CONFIG_INT(cl_editor, 0, 0, 1, CFGFLAG_CLIENT, "")
 
+MACRO_CONFIG_INT(cl_eventthread, 0, 0, 1, CFGFLAG_CLIENT, "Enables the usage of a thread to pump the events")
+
+MACRO_CONFIG_INT(inp_grab, 0, 0, 1, CFGFLAG_CLIENT, "Use forceful input grabbing method")
+
 MACRO_CONFIG_STR(b_filter_string, 64, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Server browser filtering string")
 
 MACRO_CONFIG_INT(b_filter_full, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter out full server in browser")
@@ -19,7 +23,8 @@ MACRO_CONFIG_INT(b_filter_empty, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter o
 MACRO_CONFIG_INT(b_filter_pw, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter out password protected servers in browser")
 MACRO_CONFIG_INT(b_filter_ping, 999, 0, 999, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Ping to filter by in the server browser")
 MACRO_CONFIG_STR(b_filter_gametype, 128, "", CFGFLAG_SAVE|CFGFLAG_CLIENT, "Game types to filter")
-MACRO_CONFIG_INT(b_filter_pure, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter out non-pure servers in browser")
+MACRO_CONFIG_INT(b_filter_pure, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter out non-standard servers in browser")
+MACRO_CONFIG_INT(b_filter_pure_map, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter out non-standard maps in browser")
 MACRO_CONFIG_INT(b_filter_compatversion, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Filter out non-compatible servers in browser")
 
 MACRO_CONFIG_INT(b_sort, 0, 0, 256, CFGFLAG_SAVE|CFGFLAG_CLIENT, "")
@@ -60,6 +65,7 @@ MACRO_CONFIG_INT(sv_max_clients, 8, 1, MAX_CLIENTS, CFGFLAG_SERVER, "Maximum num
 MACRO_CONFIG_INT(sv_high_bandwidth, 0, 0, 1, CFGFLAG_SERVER, "Use high bandwidth mode. Doubles the bandwidth required for the server. LAN use only")
 MACRO_CONFIG_INT(sv_register, 1, 0, 1, CFGFLAG_SERVER, "Register server with master server for public listing")
 MACRO_CONFIG_STR(sv_rcon_password, 32, "", CFGFLAG_SERVER, "Remote console password")
+MACRO_CONFIG_INT(sv_map_reload, 0, 0, 1, CFGFLAG_SERVER, "Reload the current map")
 
 MACRO_CONFIG_INT(debug, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SERVER, "Debug mode")
 MACRO_CONFIG_INT(dbg_stress, 0, 0, 0, CFGFLAG_CLIENT|CFGFLAG_SERVER, "Stress systems")
@@ -69,5 +75,3 @@ MACRO_CONFIG_INT(dbg_graphs, 0, 0, 1, CFGFLAG_CLIENT, "Performance graphs")
 MACRO_CONFIG_INT(dbg_hitch, 0, 0, 0, CFGFLAG_SERVER, "Hitch warnings")
 MACRO_CONFIG_STR(dbg_stress_server, 32, "localhost", CFGFLAG_CLIENT, "Server to stress")
 MACRO_CONFIG_INT(dbg_resizable, 0, 0, 0, CFGFLAG_CLIENT, "Enables window resizing")
-
-MACRO_CONFIG_INT(sv_map_reload, 0, 0, 1, CFGFLAG_SERVER, "Reload the current map")
diff --git a/src/engine/e_network.c b/src/engine/e_network.c
index c7aabc99..3c32de1d 100644
--- a/src/engine/e_network.c
+++ b/src/engine/e_network.c
@@ -224,6 +224,12 @@ int unpack_packet(unsigned char *buffer, int size, NETPACKETCONSTRUCT *packet)
 
 	if(packet->flags&NET_PACKETFLAG_CONNLESS)
 	{
+		if(size < 6)
+		{
+			dbg_msg("", "connection less packet too small, %d", size);
+			return -1;
+		}
+			
 		packet->flags = NET_PACKETFLAG_CONNLESS;
 		packet->ack = 0;
 		packet->num_chunks = 0;
diff --git a/src/engine/server/es_server.c b/src/engine/server/es_server.c
index 3d9f56f5..0072f123 100644
--- a/src/engine/server/es_server.c
+++ b/src/engine/server/es_server.c
@@ -70,6 +70,7 @@ static int snap_id_inited = 0;
 enum
 {
 	SRVCLIENT_STATE_EMPTY = 0,
+	SRVCLIENT_STATE_AUTH,
 	SRVCLIENT_STATE_CONNECTING,
 	SRVCLIENT_STATE_READY,
 	SRVCLIENT_STATE_INGAME,
@@ -211,9 +212,42 @@ const char *server_clientname(int client_id)
 	return clients[client_id].name;
 }
 
+static const char *str_ltrim(const char *str)
+{
+	while(*str && *str <= 32)
+		str++;
+	return str;
+}
+
+static void str_rtrim(char *str)
+{
+	int i = str_length(str);
+	while(i >= 0)
+	{
+		if(str[i] > 32)
+			break;
+		str[i] = 0;
+		i--;
+	}
+}
+
 static int server_try_setclientname(int client_id, const char *name)
 {
 	int i;
+	char trimmed_name[64];
+
+	/* trim the name */
+	str_copy(trimmed_name, str_ltrim(name), sizeof(trimmed_name));
+	str_rtrim(trimmed_name);
+	dbg_msg("", "'%s' -> '%s'", name, trimmed_name);
+	name = trimmed_name;
+	
+	
+	/* check for empty names */
+	if(!name[0])
+		return -1;
+	
+	/* make sure that two clients doesn't have the same name */
 	for(i = 0; i < MAX_CLIENTS; i++)
 		if(i != client_id && clients[i].state >= SRVCLIENT_STATE_READY)
 		{
@@ -221,6 +255,7 @@ static int server_try_setclientname(int client_id, const char *name)
 				return -1;
 		}
 
+	/* set the client name */
 	str_copy(clients[client_id].name, name, MAX_NAME_LENGTH);
 	return 0;
 }
@@ -544,7 +579,7 @@ static void reset_client(int cid)
 
 static int new_client_callback(int cid, void *user)
 {
-	clients[cid].state = SRVCLIENT_STATE_CONNECTING;
+	clients[cid].state = SRVCLIENT_STATE_AUTH;
 	clients[cid].name[0] = 0;
 	clients[cid].clan[0] = 0;
 	clients[cid].authed = 0;
@@ -608,10 +643,9 @@ static void server_process_client_packet(NETCHUNK *packet)
 	int sys;
 	int msg = msg_unpack_start(packet->data, packet->data_size, &sys);
 	
-	if(sys)
+	if(clients[cid].state == SRVCLIENT_STATE_AUTH)
 	{
-		/* system message */
-		if(msg == NETMSG_INFO)
+		if(sys && msg == NETMSG_INFO)
 		{
 			char version[64];
 			const char *password;
@@ -636,185 +670,197 @@ static void server_process_client_packet(NETCHUNK *packet)
 				return;
 			}
 			
+			clients[cid].state = SRVCLIENT_STATE_CONNECTING;
 			server_send_map(cid);
 		}
-		else if(msg == NETMSG_REQUEST_MAP_DATA)
+	}
+	else
+	{
+		if(sys)
 		{
-			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)
+			/* system message */
+			if(msg == NETMSG_REQUEST_MAP_DATA)
+			{
+				int chunk = msg_unpack_int();
+				int chunk_size = 1024-128;
+				int offset = chunk * chunk_size;
+				int last = 0;
+				
+				/* drop faulty map data requests */
+				if(chunk < 0 || offset > current_map_size)
+					return;
+				
+				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|MSGFLAG_FLUSH);
+				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)
 			{
-				chunk_size = current_map_size-offset;
-				if(chunk_size < 0)
-					chunk_size = 0;
-				last = 1;
+				if(clients[cid].state == SRVCLIENT_STATE_CONNECTING)
+				{
+					netserver_client_addr(net, cid, &addr);
+					
+					dbg_msg("server", "player is ready. cid=%x ip=%d.%d.%d.%d",
+						cid,
+						addr.ip[0], addr.ip[1], addr.ip[2], addr.ip[3]
+						);
+					clients[cid].state = SRVCLIENT_STATE_READY;
+					mods_connected(cid);
+				}
 			}
-			
-			msg_pack_start_system(NETMSG_MAP_DATA, MSGFLAG_VITAL|MSGFLAG_FLUSH);
-			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)
+			else if(msg == NETMSG_ENTERGAME)
 			{
-				netserver_client_addr(net, cid, &addr);
-				
-				dbg_msg("server", "player is ready. cid=%x ip=%d.%d.%d.%d",
-					cid,
-					addr.ip[0], addr.ip[1], addr.ip[2], addr.ip[3]
-					);
-				clients[cid].state = SRVCLIENT_STATE_READY;
-				mods_connected(cid);
+				if(clients[cid].state == SRVCLIENT_STATE_READY)
+				{
+					netserver_client_addr(net, cid, &addr);
+					
+					dbg_msg("server", "player has entered the game. cid=%x ip=%d.%d.%d.%d",
+						cid,
+						addr.ip[0], addr.ip[1], addr.ip[2], addr.ip[3]
+						);
+					clients[cid].state = SRVCLIENT_STATE_INGAME;
+					mods_client_enter(cid);
+				}
 			}
-		}
-		else if(msg == NETMSG_ENTERGAME)
-		{
-			if(clients[cid].state == SRVCLIENT_STATE_READY)
+			else if(msg == NETMSG_INPUT)
 			{
-				netserver_client_addr(net, cid, &addr);
+				int tick, size, i;
+				CLIENT_INPUT *input;
+				int64 tagtime;
 				
-				dbg_msg("server", "player has entered the game. cid=%x ip=%d.%d.%d.%d",
-					cid,
-					addr.ip[0], addr.ip[1], addr.ip[2], addr.ip[3]
-					);
-				clients[cid].state = SRVCLIENT_STATE_INGAME;
-				mods_client_enter(cid);
-			}
-		}
-		else if(msg == NETMSG_INPUT)
-		{
-			int tick, size, i;
-			CLIENT_INPUT *input;
-			int64 tagtime;
-			
-			clients[cid].last_acked_snapshot = msg_unpack_int();
-			tick = msg_unpack_int();
-			size = msg_unpack_int();
-			
-			/* check for errors */
-			if(msg_unpack_error() || size/4 > MAX_INPUT_SIZE)
-				return;
-
-			if(clients[cid].last_acked_snapshot > 0)
-				clients[cid].snap_rate = SRVCLIENT_SNAPRATE_FULL;
+				clients[cid].last_acked_snapshot = msg_unpack_int();
+				tick = msg_unpack_int();
+				size = msg_unpack_int();
 				
-			if(snapstorage_get(&clients[cid].snapshots, clients[cid].last_acked_snapshot, &tagtime, 0, 0) >= 0)
-				clients[cid].latency = (int)(((time_get()-tagtime)*1000)/time_freq());
+				/* check for errors */
+				if(msg_unpack_error() || size/4 > MAX_INPUT_SIZE)
+					return;
 
-			/* add message to report the input timing */
-			/* skip packets that are old */
-			if(tick > clients[cid].last_input_tick)
-			{
-				int time_left = ((server_tick_start_time(tick)-time_get())*1000) / time_freq();
-				msg_pack_start_system(NETMSG_INPUTTIMING, 0);
-				msg_pack_int(tick);
-				msg_pack_int(time_left);
-				msg_pack_end();
-				server_send_msg(cid);
-			}
+				if(clients[cid].last_acked_snapshot > 0)
+					clients[cid].snap_rate = SRVCLIENT_SNAPRATE_FULL;
+					
+				if(snapstorage_get(&clients[cid].snapshots, clients[cid].last_acked_snapshot, &tagtime, 0, 0) >= 0)
+					clients[cid].latency = (int)(((time_get()-tagtime)*1000)/time_freq());
 
-			clients[cid].last_input_tick = tick;
+				/* add message to report the input timing */
+				/* skip packets that are old */
+				if(tick > clients[cid].last_input_tick)
+				{
+					int time_left = ((server_tick_start_time(tick)-time_get())*1000) / time_freq();
+					msg_pack_start_system(NETMSG_INPUTTIMING, 0);
+					msg_pack_int(tick);
+					msg_pack_int(time_left);
+					msg_pack_end();
+					server_send_msg(cid);
+				}
 
-			input = &clients[cid].inputs[clients[cid].current_input];
-			
-			if(tick <= server_tick())
-				tick = server_tick()+1;
+				clients[cid].last_input_tick = tick;
 
-			input->game_tick = tick;
-			
-			for(i = 0; i < size/4; i++)
-				input->data[i] = msg_unpack_int();
-			
-			mem_copy(clients[cid].latestinput.data, input->data, MAX_INPUT_SIZE*sizeof(int));
-			
-			clients[cid].current_input++;
-			clients[cid].current_input %= 200;
-		
-			/* call the mod with the fresh input data */
-			if(clients[cid].state == SRVCLIENT_STATE_INGAME)
-				mods_client_direct_input(cid, clients[cid].latestinput.data);
-		}
-		else if(msg == NETMSG_RCON_CMD)
-		{
-			const char *cmd = msg_unpack_string();
+				input = &clients[cid].inputs[clients[cid].current_input];
+				
+				if(tick <= server_tick())
+					tick = server_tick()+1;
+
+				input->game_tick = tick;
+				
+				for(i = 0; i < size/4; i++)
+					input->data[i] = msg_unpack_int();
+				
+				mem_copy(clients[cid].latestinput.data, input->data, MAX_INPUT_SIZE*sizeof(int));
+				
+				clients[cid].current_input++;
+				clients[cid].current_input %= 200;
 			
-			if(msg_unpack_error() == 0 && clients[cid].authed)
-			{
-				dbg_msg("server", "cid=%d rcon='%s'", cid, cmd);
-				console_execute_line(cmd);
+				/* call the mod with the fresh input data */
+				if(clients[cid].state == SRVCLIENT_STATE_INGAME)
+					mods_client_direct_input(cid, clients[cid].latestinput.data);
 			}
-		}
-		else if(msg == NETMSG_RCON_AUTH)
-		{
-			const char *pw;
-			msg_unpack_string(); /* login name, not used */
-			pw = msg_unpack_string();
-			
-			if(msg_unpack_error() == 0)
+			else if(msg == NETMSG_RCON_CMD)
 			{
-				if(config.sv_rcon_password[0] == 0)
+				const char *cmd = msg_unpack_string();
+				
+				if(msg_unpack_error() == 0 && clients[cid].authed)
 				{
-					server_send_rcon_line(cid, "No rcon password set on server. Set sv_rcon_password to enable the remote console.");
+					dbg_msg("server", "cid=%d rcon='%s'", cid, cmd);
+					console_execute_line(cmd);
 				}
-				else if(strcmp(pw, config.sv_rcon_password) == 0)
+			}
+			else if(msg == NETMSG_RCON_AUTH)
+			{
+				const char *pw;
+				msg_unpack_string(); /* login name, not used */
+				pw = msg_unpack_string();
+				
+				if(msg_unpack_error() == 0)
 				{
-					msg_pack_start_system(NETMSG_RCON_AUTH_STATUS, MSGFLAG_VITAL);
-					msg_pack_int(1);
-					msg_pack_end();
-					server_send_msg(cid);
-					
-					clients[cid].authed = 1;
-					server_send_rcon_line(cid, "Authentication successful. Remote console access granted.");
-					dbg_msg("server", "cid=%d authed", cid);
+					if(config.sv_rcon_password[0] == 0)
+					{
+						server_send_rcon_line(cid, "No rcon password set on server. Set sv_rcon_password to enable the remote console.");
+					}
+					else if(strcmp(pw, config.sv_rcon_password) == 0)
+					{
+						msg_pack_start_system(NETMSG_RCON_AUTH_STATUS, MSGFLAG_VITAL);
+						msg_pack_int(1);
+						msg_pack_end();
+						server_send_msg(cid);
+						
+						clients[cid].authed = 1;
+						server_send_rcon_line(cid, "Authentication successful. Remote console access granted.");
+						dbg_msg("server", "cid=%d authed", cid);
+					}
+					else
+					{
+						server_send_rcon_line(cid, "Wrong password.");
+					}
 				}
-				else
+			}
+			else if(msg == NETMSG_PING)
+			{
+				msg_pack_start_system(NETMSG_PING_REPLY, 0);
+				msg_pack_end();
+				server_send_msg(cid);
+			}
+			else
+			{
+				char hex[] = "0123456789ABCDEF";
+				char buf[512];
+				int b;
+
+				for(b = 0; b < packet->data_size && b < 32; b++)
 				{
-					server_send_rcon_line(cid, "Wrong password.");
+					buf[b*3] = hex[((const unsigned char *)packet->data)[b]>>4];
+					buf[b*3+1] = hex[((const unsigned char *)packet->data)[b]&0xf];
+					buf[b*3+2] = ' ';
+					buf[b*3+3] = 0;
 				}
+
+				dbg_msg("server", "strange message cid=%d msg=%d data_size=%d", cid, msg, packet->data_size);
+				dbg_msg("server", "%s", buf);
+				
 			}
 		}
-		else if(msg == NETMSG_PING)
-		{
-			msg_pack_start_system(NETMSG_PING_REPLY, 0);
-			msg_pack_end();
-			server_send_msg(cid);
-		}
 		else
 		{
-			char hex[] = "0123456789ABCDEF";
-			char buf[512];
-			int b;
-
-			for(b = 0; b < packet->data_size && b < 32; b++)
-			{
-				buf[b*3] = hex[((const unsigned char *)packet->data)[b]>>4];
-				buf[b*3+1] = hex[((const unsigned char *)packet->data)[b]&0xf];
-				buf[b*3+2] = ' ';
-				buf[b*3+3] = 0;
-			}
-
-			dbg_msg("server", "strange message cid=%d msg=%d data_size=%d", cid, msg, packet->data_size);
-			dbg_msg("server", "%s", buf);
-			
+			/* game message */
+			if(clients[cid].state >= SRVCLIENT_STATE_READY)
+				mods_message(msg, cid);
 		}
 	}
-	else
-	{
-		/* game message */
-		if(clients[cid].state >= SRVCLIENT_STATE_READY)
-			mods_message(msg, cid);
-	}
 }
 
 
diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp
index 01b9f457..8ef4e17d 100644
--- a/src/game/client/components/chat.cpp
+++ b/src/game/client/components/chat.cpp
@@ -10,12 +10,15 @@
 
 #include "chat.hpp"
 
-void CHAT::on_reset()
+void CHAT::on_statechange(int new_state, int old_state)
 {
-	mode = MODE_NONE;
-	for(int i = 0; i < MAX_LINES; i++)
-		lines[i].time = -1000000;
-	current_line = 0;
+	if(old_state <= CLIENTSTATE_CONNECTING)
+	{
+		mode = MODE_NONE;
+		for(int i = 0; i < MAX_LINES; i++)
+			lines[i].time = 0;
+		current_line = 0;
+	}
 }
 
 void CHAT::con_say(void *result, void *user_data)
diff --git a/src/game/client/components/chat.hpp b/src/game/client/components/chat.hpp
index 593ef87e..ca34237d 100644
--- a/src/game/client/components/chat.hpp
+++ b/src/game/client/components/chat.hpp
@@ -47,7 +47,7 @@ public:
 	void say(int team, const char *line);
 	
 	virtual void on_console_init();
-	virtual void on_reset();
+	virtual void on_statechange(int new_state, int old_state);
 	virtual void on_render();
 	virtual void on_message(int msgtype, void *rawmsg);
 	virtual bool on_input(INPUT_EVENT e);
diff --git a/src/game/client/components/console.cpp b/src/game/client/components/console.cpp
index c1493fb8..53d5637e 100644
--- a/src/game/client/components/console.cpp
+++ b/src/game/client/components/console.cpp
@@ -276,8 +276,11 @@ void CONSOLE::on_render()
 
 		progress = 1.0f;
 	}
-	
-	if (console_state == CONSOLE_CLOSED || config.cl_editor)
+
+	if (console_state == CONSOLE_OPEN && config.cl_editor)
+		toggle(0);	
+		
+	if (console_state == CONSOLE_CLOSED)
 		return;
 		
 	if (console_state == CONSOLE_OPEN)
diff --git a/src/game/client/components/hud.cpp b/src/game/client/components/hud.cpp
index b86d3873..b1926ab4 100644
--- a/src/game/client/components/hud.cpp
+++ b/src/game/client/components/hud.cpp
@@ -171,7 +171,7 @@ void HUD::render_teambalancewarning()
 {
 	// render prompt about team-balance
 	bool flash = time_get()/(time_freq()/2)%2 == 0;
-	if (gameclient.snap.gameobj && gameclient.snap.gameobj->flags&GAMEFLAG_TEAMS != 0)
+	if (gameclient.snap.gameobj && (gameclient.snap.gameobj->flags&GAMEFLAG_TEAMS) != 0)
 	{	
 		if (config.cl_warning_teambalance && abs(gameclient.snap.team_size[0]-gameclient.snap.team_size[1]) >= 2)
 		{
diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp
index 17c7775f..c26bddba 100644
--- a/src/game/client/components/menus_browser.cpp
+++ b/src/game/client/components/menus_browser.cpp
@@ -373,10 +373,15 @@ void MENUS::render_serverbrowser_filters(RECT view)
 		config.b_filter_compatversion ^= 1;
 	
 	ui_hsplit_t(&view, 20.0f, &button, &view);
-	if (ui_do_button((char *)&config.b_filter_pure, "Only pure", config.b_filter_pure, &button, ui_draw_checkbox, 0))
+	if (ui_do_button((char *)&config.b_filter_pure, "Standard gametype", config.b_filter_pure, &button, ui_draw_checkbox, 0))
 		config.b_filter_pure ^= 1;
 
 	ui_hsplit_t(&view, 20.0f, &button, &view);
+	/*ui_vsplit_l(&button, 20.0f, 0, &button);*/
+	if (ui_do_button((char *)&config.b_filter_pure_map, "Standard map", config.b_filter_pure_map, &button, ui_draw_checkbox, 0))
+		config.b_filter_pure_map ^= 1;
+		
+	ui_hsplit_t(&view, 20.0f, &button, &view);
 	ui_do_label(&button, "Game types: ", 14.0f, -1);
 	ui_vsplit_l(&button, 95.0f, 0, &button);
 	ui_margin(&button, 1.0f, &button);
diff --git a/src/game/client/components/players.cpp b/src/game/client/components/players.cpp
index f8e73dfb..6d6bcc37 100644
--- a/src/game/client/components/players.cpp
+++ b/src/game/client/components/players.cpp
@@ -95,7 +95,7 @@ void PLAYERS::render_player(
 	bool is_teamplay = false;
 	bool new_tick = gameclient.new_tick;
 	if(gameclient.snap.gameobj)
-		is_teamplay = gameclient.snap.gameobj->flags&GAMEFLAG_TEAMS != 0;
+		is_teamplay = (gameclient.snap.gameobj->flags&GAMEFLAG_TEAMS) != 0;
 
 	// check for ninja	
 	if (player.weapon == WEAPON_NINJA)
diff --git a/src/game/client/components/scoreboard.cpp b/src/game/client/components/scoreboard.cpp
index 59a23508..dc1c4283 100644
--- a/src/game/client/components/scoreboard.cpp
+++ b/src/game/client/components/scoreboard.cpp
@@ -113,7 +113,7 @@ void SCOREBOARD::render_scoreboard(float x, float y, float w, int team, const ch
 	gfx_texture_set(-1);
 	gfx_quads_begin();
 	gfx_setcolor(0,0,0,0.5f);
-	draw_round_rect(x-10.f, y-10.f, w, h, 40.0f);
+	draw_round_rect(x-10.f, y-10.f, w, h, 17.0f);
 	gfx_quads_end();
 
 	// render title
@@ -157,8 +157,12 @@ void SCOREBOARD::render_scoreboard(float x, float y, float w, int team, const ch
 
 		if(item.type == NETOBJTYPE_PLAYER_INFO)
 		{
-			players[num_players] = (const NETOBJ_PLAYER_INFO *)data;
-			num_players++;
+			const NETOBJ_PLAYER_INFO *info = (const NETOBJ_PLAYER_INFO *)data;
+			if(info->team == team)
+			{
+				players[num_players] = info;
+				num_players++;
+			}
 		}
 	}
 
@@ -182,24 +186,34 @@ void SCOREBOARD::render_scoreboard(float x, float y, float w, int team, const ch
 	gfx_text(0, x+w-70, y, 24.0f, "Ping", -1);
 	y += 29.0f;
 
+	float font_size = 35.0f;
+	float line_height = 50.0f;
+	float tee_sizemod = 1.0f;
+	float tee_offset = 0.0f;
+	
+	if(num_players > 13)
+	{
+		font_size = 30.0f;
+		line_height = 40.0f;
+		tee_sizemod = 0.8f;
+		tee_offset = -5.0f;
+	}
+	
 	// render player scores
 	for(int i = 0; i < num_players; i++)
 	{
 		const NETOBJ_PLAYER_INFO *info = players[i];
 
 		// make sure that we render the correct team
-		if(team == -1 || info->team != team)
-			continue;
 
 		char buf[128];
-		float font_size = 35.0f;
 		if(info->local)
 		{
 			// background so it's easy to find the local player
 			gfx_texture_set(-1);
 			gfx_quads_begin();
 			gfx_setcolor(1,1,1,0.25f);
-			draw_round_rect(x, y, w-20, 48, 20.0f);
+			draw_round_rect(x, y, w-20, line_height*0.95f, 17.0f);
 			gfx_quads_end();
 		}
 
@@ -228,10 +242,12 @@ void SCOREBOARD::render_scoreboard(float x, float y, float w, int team, const ch
 			gfx_quads_end();
 		}
 		
-		render_tee(ANIMSTATE::get_idle(), &gameclient.clients[info->cid].render_info, EMOTE_NORMAL, vec2(1,0), vec2(x+90, y+28));
+		TEE_RENDER_INFO teeinfo = gameclient.clients[info->cid].render_info;
+		teeinfo.size *= tee_sizemod;
+		render_tee(ANIMSTATE::get_idle(), &teeinfo, EMOTE_NORMAL, vec2(1,0), vec2(x+90, y+28+tee_offset));
 
 		
-		y += 50.0f;
+		y += line_height;
 	}
 }
 
diff --git a/src/game/client/render.hpp b/src/game/client/render.hpp
index 917641c8..9ce555d2 100644
--- a/src/game/client/render.hpp
+++ b/src/game/client/render.hpp
@@ -37,9 +37,9 @@ enum
 	TILERENDERFLAG_EXTEND=4,
 };
 
-typedef struct SPRITE;
+//typedef struct SPRITE;
 
-void select_sprite(SPRITE *spr, int flags=0, int sx=0, int sy=0);
+void select_sprite(struct SPRITE *spr, int flags=0, int sx=0, int sy=0);
 void select_sprite(int id, int flags=0, int sx=0, int sy=0);
 
 void draw_sprite(float x, float y, float size);
diff --git a/src/game/editor/ed_editor.cpp b/src/game/editor/ed_editor.cpp
index 19727490..7a8a1ae7 100644
--- a/src/game/editor/ed_editor.cpp
+++ b/src/game/editor/ed_editor.cpp
@@ -1168,14 +1168,14 @@ static void do_map_editor(RECT view, RECT toolbar)
 		ui_set_hot_item(editor_id);
 				
 		// do global operations like pan and zoom
-		if(ui_active_item() == 0 && ui_mouse_button(0))
+		if(ui_active_item() == 0 && (ui_mouse_button(0) || ui_mouse_button(2)))
 		{
 			start_wx = wx;
 			start_wy = wy;
 			start_mx = mx;
 			start_my = my;
 					
-			if(inp_key_pressed(KEY_LCTRL) || inp_key_pressed(KEY_RCTRL))
+			if(inp_key_pressed(KEY_LCTRL) || inp_key_pressed(KEY_RCTRL) || ui_mouse_button(2))
 			{
 				if(inp_key_pressed(KEY_LSHIFT))
 					operation = OP_PAN_EDITOR;
@@ -2411,11 +2411,12 @@ static void render_envelopeeditor(RECT view)
 
 static int popup_menu_file(RECT view)
 {
-	static int new_map_button = 0;	
-	static int save_button = 0;	
-	static int save_as_button = 0;	
-	static int open_button = 0;	
-	static int append_button = 0;	
+	static int new_map_button = 0;
+	static int save_button = 0;
+	static int save_as_button = 0;
+	static int open_button = 0;
+	static int append_button = 0;
+	static int exit_button = 0;
 
 	RECT slot;
 	ui_hsplit_t(&view, 2.0f, &slot, &view);
@@ -2456,6 +2457,14 @@ static int popup_menu_file(RECT view)
 		editor.invoke_file_dialog(LISTDIRTYPE_SAVE, "Save Map", "Save", "maps/", "", callback_save_map);
 		return 1;
 	}
+	
+	ui_hsplit_t(&view, 10.0f, &slot, &view);
+	ui_hsplit_t(&view, 12.0f, &slot, &view);
+	if(do_editor_button(&exit_button, "Exit", 0, &slot, draw_editor_button_menuitem, 0, "Exits from the editor"))
+	{
+		config.cl_editor = 0;
+		return 1;
+	}	
 		
 	return 0;
 }
@@ -2680,7 +2689,7 @@ extern "C" void editor_update_and_render()
 {
 	static int mouse_x = 0;
 	static int mouse_y = 0;
-
+	
 	if(editor.animate)
 		editor.animate_time = (time_get()-editor.animate_start)/(float)time_freq();
 	else
diff --git a/src/game/server/entities/character.cpp b/src/game/server/entities/character.cpp
index 3bbe8670..8ba91a80 100644
--- a/src/game/server/entities/character.cpp
+++ b/src/game/server/entities/character.cpp
@@ -546,10 +546,10 @@ void CHARACTER::tick()
 	
 	float phys_size = 28.0f;
 	// handle death-tiles
-	if(col_get((int)(pos.x+phys_size/2), (int)(pos.y-phys_size/2))&COLFLAG_DEATH ||
-			col_get((int)(pos.x+phys_size/2), (int)(pos.y+phys_size/2))&COLFLAG_DEATH ||
-			col_get((int)(pos.x-phys_size/2), (int)(pos.y-phys_size/2))&COLFLAG_DEATH ||
-			col_get((int)(pos.x-phys_size/2), (int)(pos.y+phys_size/2))&COLFLAG_DEATH)
+	if(col_get((int)(pos.x+phys_size/3), (int)(pos.y-phys_size/3))&COLFLAG_DEATH ||
+			col_get((int)(pos.x+phys_size/3), (int)(pos.y+phys_size/3))&COLFLAG_DEATH ||
+			col_get((int)(pos.x-phys_size/3), (int)(pos.y-phys_size/3))&COLFLAG_DEATH ||
+			col_get((int)(pos.x-phys_size/3), (int)(pos.y+phys_size/3))&COLFLAG_DEATH)
 	{
 		die(player->client_id, WEAPON_WORLD);
 	}
diff --git a/src/game/server/gamemodes/ctf.cpp b/src/game/server/gamemodes/ctf.cpp
index f1c7c236..b2146b51 100644
--- a/src/game/server/gamemodes/ctf.cpp
+++ b/src/game/server/gamemodes/ctf.cpp
@@ -216,11 +216,8 @@ void FLAG::reset()
 void FLAG::snap(int snapping_client)
 {
 	NETOBJ_FLAG *flag = (NETOBJ_FLAG *)snap_new_item(NETOBJTYPE_FLAG, team, sizeof(NETOBJ_FLAG));
-	if(!networkclipped(snapping_client, pos))
-	{
-		flag->x = (int)pos.x;
-		flag->y = (int)pos.y;
-	}
+	flag->x = (int)pos.x;
+	flag->y = (int)pos.y;
 	flag->team = team;
 	flag->carried_by = -1;
 	
diff --git a/src/game/server/hooks.cpp b/src/game/server/hooks.cpp
index 18626b4e..1ae38ce2 100644
--- a/src/game/server/hooks.cpp
+++ b/src/game/server/hooks.cpp
@@ -257,7 +257,7 @@ void mods_message(int msgtype, int client_id)
 				return;
 			}
 			
-			str_format(chatmsg, sizeof(chatmsg), "Vote called to kick '%s'", server_clientname(kick_id));
+			str_format(chatmsg, sizeof(chatmsg), "%s called for vote to kick '%s'", server_clientname(client_id), server_clientname(kick_id));
 			str_format(desc, sizeof(desc), "Kick '%s'", server_clientname(kick_id));
 			str_format(cmd, sizeof(cmd), "kick %d", kick_id);
 			if (!config.sv_vote_kick_bantime)
diff --git a/src/game/version.hpp b/src/game/version.hpp
index 1277ccfa..2692752c 100644
--- a/src/game/version.hpp
+++ b/src/game/version.hpp
@@ -1,4 +1,4 @@
 /* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
 #include "generated/nethash.c"
-#define GAME_VERSION "0.5.1"
+#define GAME_VERSION "trunk"
 #define GAME_NETVERSION "0.5 " GAME_NETVERSION_HASH