about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMagnus Auvinen <magnus.auvinen@gmail.com>2008-03-17 21:31:46 +0000
committerMagnus Auvinen <magnus.auvinen@gmail.com>2008-03-17 21:31:46 +0000
commitc4e165f395e90c1c370bac8fa5226c1bee92d6e3 (patch)
tree920310e95168f2e6b62b1b0669d8903672331d4c
parent88f23416270c5e204356f2316e1d363764908d19 (diff)
downloadzcatch-c4e165f395e90c1c370bac8fa5226c1bee92d6e3.tar.gz
zcatch-c4e165f395e90c1c370bac8fa5226c1bee92d6e3.zip
reworked the whole message system
-rw-r--r--scripts/netobj.py164
-rw-r--r--src/game/client/gc_client.cpp51
-rw-r--r--src/game/client/gc_effects.cpp3
-rw-r--r--src/game/client/gc_hooks.cpp182
-rw-r--r--src/game/g_protocol.def113
-rw-r--r--src/game/server/gs_server.cpp156
6 files changed, 439 insertions, 230 deletions
diff --git a/scripts/netobj.py b/scripts/netobj.py
index 0245a5c8..bd090b67 100644
--- a/scripts/netobj.py
+++ b/scripts/netobj.py
@@ -14,6 +14,10 @@ class variable:
 		return "#line %d" % self.line
 	def emit_secure(self):
 		return []
+	def emit_unpack(self):
+		return ["msg.%s = msg_unpack_int();" % self.name]
+	def emit_pack(self):
+		return ["\t\tmsg_pack_int(%s);" % self.name]
 
 class var_any(variable):
 	def __init__(self, args, name):
@@ -37,6 +41,16 @@ class var_string(variable):
 	def __init__(self, args, name):
 		variable.__init__(self, args, name)
 
+class var_string(variable):
+	def __init__(self, args, name):
+		variable.__init__(self, args, name)
+	def emit_declaration(self):
+		return ["\tconst char *%s;" % self.name]
+	def emit_unpack(self):
+		return ["msg.%s = msg_unpack_string();" % self.name]
+	def emit_pack(self):
+		return ["\t\tmsg_pack_string(%s, -1);" % self.name]
+
 class object:
 	def __init__(self, line):
 		fields = line.split()
@@ -95,7 +109,74 @@ class object:
 		for m in self.members:
 			lines += m.emit_secure()
 		return lines
+
+class message:
+	def __init__(self, line):
+		fields = line.split()
+		self.name = fields[1]
+		self.enum_name = "NETMSGTYPE_%s" % self.name.upper()
+		self.struct_name = "NETMSG_%s" % self.name.upper()
+		self.members = []
 		
+	def parse(self, lines):
+		global line_count
+		for index in xrange(0, len(lines)):
+			line_count += 1
+			line = lines[index]
+			if not len(line):
+				continue
+				
+			if line == "end":
+				return lines[index+1:]
+			else:
+				# check for argument
+				fields = line.split(")", 1)
+				if len(fields) == 2:
+					names = [line.strip() for line in fields[1].split(",")]
+					l = fields[0].split("(", 1)
+					type = l[0]
+					args = [line.strip() for line in l[1].split(",")]
+				else:
+					l = fields[0].split(None, 1)
+					type = l[0]
+					args = []
+					names = [line.strip() for line in l[1].split(",")]
+					
+				for name in names:
+					create_string = 'var_%s(%s, "%s")' % (type, args, name)
+					new_member = eval(create_string)
+					self.members += [new_member]
+				
+		raise BaseException("Parse error")
+	
+	def emit_declaration(self):
+		lines = []
+		lines += ["struct %s\n {" % self.struct_name]
+		for m in self.members:
+			lines += m.emit_declaration()
+		lines += ["\tvoid pack(int flags)"]
+		lines += ["\t{"]
+		lines += ["\t\tmsg_pack_start(%s, flags);" % self.enum_name]
+		for m in self.members:
+			lines += m.emit_pack()
+		lines += ["\t\tmsg_pack_end();"]
+		lines += ["\t}"]
+		lines += ["};"]
+		return lines
+
+	def emit_unpack(self):
+		lines = []
+		for m in self.members:
+			lines += m.emit_unpack()
+		return lines
+
+	def emit_pack(self):
+		lines = []
+		for m in self.members:
+			lines += m.emit_pack()
+		return lines
+		
+
 class event(object):
 	def __init__(self, line):
 		object.__init__(self, line)
@@ -123,10 +204,10 @@ class raw_reader:
 class proto:
 	def __init__(self):
 		self.objects = []
+		self.messages = []
 		self.source_raw = []
 		self.header_raw = []
 
-
 def load(filename):
 	# read the file
 	global line_count
@@ -148,10 +229,14 @@ def load(filename):
 		
 		del lines[0]
 		
-		if fields[0] == "object" or fields[0] == "msg":
+		if fields[0] == "object":
 			new_obj = object(line)
 			lines = new_obj.parse(lines)
 			p.objects += [new_obj]
+		elif fields[0] == "message":
+			new_msg = message(line)
+			lines = new_msg.parse(lines)
+			p.messages += [new_msg]
 		elif fields[0] == "event":
 			new_obj = event(line)
 			lines = new_obj.parse(lines)
@@ -173,7 +258,7 @@ def emit_header_file(f, p):
 	for l in p.header_raw:
 		print >>f, l
 		
-	if 1: # emit the enum table
+	if 1: # emit the enum table for objects
 		print >>f, "enum {"
 		print >>f, "\tNETOBJTYPE_INVALID=0,"
 		for obj in p.objects:
@@ -182,19 +267,34 @@ def emit_header_file(f, p):
 		print >>f, "};"
 		print >>f, ""
 
+	if 1: # emit the enum table for messages
+		print >>f, "enum {"
+		print >>f, "\tNETMSGTYPE_INVALID=0,"
+		for msg in p.messages:
+			print >>f, "\t%s," % msg.enum_name
+		print >>f, "\tNUM_NETMSGTYPES"
+		print >>f, "};"
+		print >>f, ""
+
 	print >>f, "int netobj_secure(int type, void *data, int size);"
 	print >>f, "const char *netobj_get_name(int type);"
 	print >>f, "int netobj_num_corrections();"
 	print >>f, ""
+	print >>f, "void *netmsg_secure_unpack(int type);"
+	print >>f, "const char *netmsg_get_name(int type);"
+	print >>f, ""
 
 	for obj in p.objects:
 		for l in obj.emit_declaration():
 			print >>f, l
 		print >>f, ""
+
+	for msg in p.messages:
+		for l in msg.emit_declaration():
+			print >>f, l
+		print >>f, ""
 			
 def emit_source_file(f, p, protofilename):
-	
-	
 	print >>f, "#line 1 \"%s\"" % os.path.abspath(protofilename).replace("\\", "\\\\")
 	
 	for l in p.source_raw:
@@ -220,7 +320,7 @@ def emit_source_file(f, p, protofilename):
 		print >>f, '\t""'
 		print >>f, "};"
 		print >>f, ""
-
+		
 	if 1: # secure functions
 		print >>f, "static int secure_object_invalid(void *data, int size) { return 0; }"
 		for obj in p.objects:
@@ -263,7 +363,57 @@ def emit_source_file(f, p, protofilename):
 		print >>f, "\treturn object_names[type];"
 		print >>f, "};"
 		print >>f, ""
-	
+		
+	if 1: # names
+		print >>f, "static const char *message_names[] = {"
+		print >>f, "\t" + '"invalid",'
+		for msg in p.messages:
+			print >>f, '\t"%s",' % msg.name
+		print >>f, '\t""'
+		print >>f, "};"
+		print >>f, ""		
+
+	if 1: # secure functions
+		print >>f, "static void *secure_unpack_invalid() { return 0; }"
+		for msg in p.messages:
+			print >>f, "static void *secure_unpack_%s()" % msg.name
+			print >>f, "{"
+			print >>f, "\tstatic %s msg;" % msg.struct_name
+			for l in msg.emit_unpack():
+				print >>f, "\t" + l
+			print >>f, "\treturn &msg;";
+			print >>f, "}"
+			print >>f, ""		
+
+	if 1: # secure function table
+		print >>f, "typedef void *(*SECUREUNPACKFUNC)();"
+		print >>f, "static SECUREUNPACKFUNC secure_unpack_funcs[] = {"
+		print >>f, "\t" + 'secure_unpack_invalid,'
+		for msg in p.messages:
+			print >>f, "\tsecure_unpack_%s," % msg.name
+		print >>f, "\t" + '0x0'
+		print >>f, "};"
+		print >>f, ""
+		
+	if 1:
+		print >>f, "void *netmsg_secure_unpack(int type)"
+		print >>f, "{"
+		print >>f, "\tvoid *msg;"
+		print >>f, "\tif(type < 0 || type >= NUM_NETMSGTYPES) return 0;"
+		print >>f, "\tmsg = secure_unpack_funcs[type]();"
+		print >>f, "\tif(msg_unpack_error()) return 0;"
+		print >>f, "\treturn msg;"
+		print >>f, "};"
+		print >>f, ""
+
+	if 1:
+		print >>f, "const char *netmsg_get_name(int type)"
+		print >>f, "{"
+		print >>f, "\tif(type < 0 || type >= NUM_NETMSGTYPES) return \"(invalid)\";"
+		print >>f, "\treturn message_names[type];"
+		print >>f, "};"
+		print >>f, ""		
+		
 if sys.argv[1] == "header":
 	p = load(sys.argv[2])
 	emit_header_file(file(sys.argv[3], "w"), p)
diff --git a/src/game/client/gc_client.cpp b/src/game/client/gc_client.cpp
index 03211e2c..168f6913 100644
--- a/src/game/client/gc_client.cpp
+++ b/src/game/client/gc_client.cpp
@@ -99,9 +99,9 @@ void snd_play_random(int chn, int setid, float vol, vec2 pos)
 
 void send_switch_team(int team)
 {
-	msg_pack_start(MSG_SETTEAM, MSGFLAG_VITAL);
-	msg_pack_int(team);
-	msg_pack_end();
+	NETMSG_CL_SETTEAM msg;
+	msg.team = team;
+	msg.pack(MSGFLAG_VITAL);
 	client_send_msg();	
 }
 
@@ -320,31 +320,40 @@ void clear_object_pointers()
 void send_info(bool start)
 {
 	if(start)
-		msg_pack_start(MSG_STARTINFO, MSGFLAG_VITAL);
+	{
+		NETMSG_CL_STARTINFO msg;
+		msg.name = config.player_name;
+		msg.skin = config.player_skin;
+		msg.use_custom_color = config.player_use_custom_color;
+		msg.color_body = config.player_color_body;
+		msg.color_feet = config.player_color_feet;
+		msg.pack(MSGFLAG_VITAL);
+	}
 	else
-		msg_pack_start(MSG_CHANGEINFO, MSGFLAG_VITAL);
-	msg_pack_string(config.player_name, 64);
-	msg_pack_string(config.player_skin, 64);
-	msg_pack_int(config.player_use_custom_color);
-	msg_pack_int(config.player_color_body);
-	msg_pack_int(config.player_color_feet);
-	msg_pack_end();
+	{
+		NETMSG_CL_CHANGEINFO msg;
+		msg.name = config.player_name;
+		msg.skin = config.player_skin;
+		msg.use_custom_color = config.player_use_custom_color;
+		msg.color_body = config.player_color_body;
+		msg.color_feet = config.player_color_feet;
+		msg.pack(MSGFLAG_VITAL);
+	}
 	client_send_msg();
 }
 
 void send_emoticon(int emoticon)
 {
-	msg_pack_start(MSG_EMOTICON, MSGFLAG_VITAL);
-	msg_pack_int(emoticon);
-	msg_pack_end();
+	NETMSG_CL_EMOTICON msg;
+	msg.emoticon = emoticon;
+	msg.pack(MSGFLAG_VITAL);
 	client_send_msg();
 }
 
 void send_kill(int client_id)
 {
-	msg_pack_start(MSG_KILL, MSGFLAG_VITAL);
-	msg_pack_int(client_id);
-	msg_pack_end();
+	NETMSG_CL_KILL msg;
+	msg.pack(MSGFLAG_VITAL);
 	client_send_msg();
 }
 
@@ -714,10 +723,10 @@ static int do_input(int *v, int key)
 void chat_say(int team, const char *line)
 {
 	// send chat message
-	msg_pack_start(MSG_SAY, MSGFLAG_VITAL);
-	msg_pack_int(team);
-	msg_pack_string(line, 512);
-	msg_pack_end();
+	NETMSG_CL_SAY msg;
+	msg.team = team;
+	msg.message = line;
+	msg.pack(MSGFLAG_VITAL);
 	client_send_msg();
 }
 
diff --git a/src/game/client/gc_effects.cpp b/src/game/client/gc_effects.cpp
index 4b811e2f..79bac29e 100644
--- a/src/game/client/gc_effects.cpp
+++ b/src/game/client/gc_effects.cpp
@@ -132,10 +132,7 @@ void effect_playerdeath(vec2 pos, int cid)
 	{
 		const skin *s = skin_get(client_datas[cid].skin_id);
 		if(s)
-		{
-			dbg_msg("", "good blood color!");
 			blood_color = s->blood_color;
-		}
 	}
 	
 	for(int i = 0; i < 64; i++)
diff --git a/src/game/client/gc_hooks.cpp b/src/game/client/gc_hooks.cpp
index d98cbfea..9c242ffc 100644
--- a/src/game/client/gc_hooks.cpp
+++ b/src/game/client/gc_hooks.cpp
@@ -283,10 +283,10 @@ extern "C" void modc_newsnapshot()
 	{
 		if((client_tick()%250) == 0)
 		{
-			msg_pack_start(MSG_SAY, MSGFLAG_VITAL);
-			msg_pack_int(-1);
-			msg_pack_string("galenskap!!!!", 512);
-			msg_pack_end();
+			NETMSG_CL_SAY msg;
+			msg.team = -1;
+			msg.message = "galenskap!!!!";
+			msg.pack(MSGFLAG_VITAL);
 			client_send_msg();
 		}
 	}
@@ -458,26 +458,10 @@ void extraproj_reset()
 
 char server_motd[900] = {0};
 
-extern "C" void modc_message(int msg)
+extern "C" void modc_message(int msgtype)
 {
-	if(msg == MSG_CHAT)
-	{
-		int cid = msg_unpack_int();
-		int team = msg_unpack_int();
-		const char *message = msg_unpack_string();
-
-		/* check for errors and invalid inputs */
-		if(msg_unpack_error() || cid < -1 || cid >= MAX_CLIENTS)
-			return;
-			
-		chat_add_line(cid, team, message);
-
-		if(cid >= 0)
-			snd_play(CHN_GUI, data->sounds[SOUND_CHAT_CLIENT].sounds[0].id, 0);
-		else
-			snd_play(CHN_GUI, data->sounds[SOUND_CHAT_SERVER].sounds[0].id, 0);
-	}
-	else if(msg == MSG_EXTRA_PROJECTILE)
+	// special messages
+	if(msgtype == NETMSGTYPE_SV_EXTRA_PROJECTILE)
 	{
 		int num = msg_unpack_int();
 		
@@ -496,17 +480,49 @@ extern "C" void modc_message(int msg)
 				extraproj_num++;
 			}
 		}
+		
+		return;
 	}
-	else if(msg == MSG_MOTD)
+	else if(msgtype == NETMSGTYPE_SV_TUNE_PARAMS)
 	{
-		const char *message = msg_unpack_string();
+		// unpack the new tuning
+		tuning_params new_tuning;
+		int *params = (int *)&new_tuning;
+		for(unsigned i = 0; i < sizeof(tuning_params)/sizeof(int); i++)
+			params[i] = msg_unpack_int();
 
-		/* check for errors and invalid inputs */
+		// check for unpacking errors
 		if(msg_unpack_error())
 			return;
+			
+		// apply new tuning
+		tuning = new_tuning;
+	}
+	
+	// normal 
+	void *rawmsg = netmsg_secure_unpack(msgtype);
+	if(!rawmsg)
+	{
+		dbg_msg("client", "dropped weird message '%s' (%d)", netmsg_get_name(msgtype), msgtype);
+		return;
+	}
+		
+	if(msgtype == NETMSGTYPE_SV_CHAT)
+	{
+		NETMSG_SV_CHAT *msg = (NETMSG_SV_CHAT *)rawmsg;
+		chat_add_line(msg->cid, msg->team, msg->message);
+
+		if(msg->cid >= 0)
+			snd_play(CHN_GUI, data->sounds[SOUND_CHAT_CLIENT].sounds[0].id, 0);
+		else
+			snd_play(CHN_GUI, data->sounds[SOUND_CHAT_SERVER].sounds[0].id, 0);
+	}
+	else if(msgtype == NETMSGTYPE_SV_MOTD)
+	{
+		NETMSG_SV_MOTD *msg = (NETMSG_SV_MOTD *)rawmsg;
 
 		// process escaping			
-		str_copy(server_motd, message, sizeof(server_motd));
+		str_copy(server_motd, msg->message, sizeof(server_motd));
 		for(int i = 0; server_motd[i]; i++)
 		{
 			if(server_motd[i] == '\\')
@@ -522,108 +538,74 @@ extern "C" void modc_message(int msg)
 			
 		dbg_msg("game", "MOTD: %s", server_motd);
 	}
-	else if(msg == MSG_SETINFO)
+	else if(msgtype == NETMSGTYPE_SV_SETINFO)
 	{
-		int cid = msg_unpack_int();
-		const char *name = msg_unpack_string();
-		const char *skinname = msg_unpack_string();
+		NETMSG_SV_SETINFO *msg = (NETMSG_SV_SETINFO *)rawmsg;
 		
-		/* check for errors and invalid inputs */
-		if(msg_unpack_error() || cid < 0 || cid >= MAX_CLIENTS)
-			return;
-		
-		str_copy(client_datas[cid].name, name, 64);
-		str_copy(client_datas[cid].skin_name, skinname, 64);
+		str_copy(client_datas[msg->cid].name, msg->name, 64);
+		str_copy(client_datas[msg->cid].skin_name, msg->skin, 64);
 		
 		// make sure that we don't set a special skin on the client
-		if(client_datas[cid].skin_name[0] == 'x' || client_datas[cid].skin_name[1] == '_')
-			str_copy(client_datas[cid].skin_name, "default", 64);
+		if(client_datas[msg->cid].skin_name[0] == 'x' || client_datas[msg->cid].skin_name[1] == '_')
+			str_copy(client_datas[msg->cid].skin_name, "default", 64);
 		
-		int use_custom_color = msg_unpack_int();
-		client_datas[cid].skin_info.color_body = skin_get_color(msg_unpack_int());
-		client_datas[cid].skin_info.color_feet = skin_get_color(msg_unpack_int());
-		client_datas[cid].skin_info.size = 64;
+		client_datas[msg->cid].skin_info.color_body = skin_get_color(msg->color_body);
+		client_datas[msg->cid].skin_info.color_feet = skin_get_color(msg->color_feet);
+		client_datas[msg->cid].skin_info.size = 64;
 		
 		// find new skin
-		client_datas[cid].skin_id = skin_find(client_datas[cid].skin_name);
-		if(client_datas[cid].skin_id < 0)
-			client_datas[cid].skin_id = 0;
+		client_datas[msg->cid].skin_id = skin_find(client_datas[msg->cid].skin_name);
+		if(client_datas[msg->cid].skin_id < 0)
+			client_datas[msg->cid].skin_id = 0;
 		
-		if(use_custom_color)
-			client_datas[cid].skin_info.texture = skin_get(client_datas[cid].skin_id)->color_texture;
+		if(msg->use_custom_color)
+			client_datas[msg->cid].skin_info.texture = skin_get(client_datas[msg->cid].skin_id)->color_texture;
 		else
 		{
-			client_datas[cid].skin_info.texture = skin_get(client_datas[cid].skin_id)->org_texture;
-			client_datas[cid].skin_info.color_body = vec4(1,1,1,1);
-			client_datas[cid].skin_info.color_feet = vec4(1,1,1,1);
+			client_datas[msg->cid].skin_info.texture = skin_get(client_datas[msg->cid].skin_id)->org_texture;
+			client_datas[msg->cid].skin_info.color_body = vec4(1,1,1,1);
+			client_datas[msg->cid].skin_info.color_feet = vec4(1,1,1,1);
 		}
 		
-		client_datas[cid].update_render_info();
+		client_datas[msg->cid].update_render_info();
 	}
-	else if(msg == MSG_TUNE_PARAMS)
-	{
-		// unpack the new tuning		
-		tuning_params new_tuning;
-		int *params = (int *)&new_tuning;
-		for(unsigned i = 0; i < sizeof(tuning_params)/sizeof(int); i++)
-			params[i] = msg_unpack_int();
-
-		// check for unpacking errors
-		if(msg_unpack_error())
-			return;
-			
-		// apply new tuning
-		tuning = new_tuning;
-	}
-    else if(msg == MSG_WEAPON_PICKUP)
+    else if(msgtype == NETMSGTYPE_SV_WEAPON_PICKUP)
     {
-        int weapon = msg_unpack_int();
-		if(msg_unpack_error())
-			return;
-        picked_up_weapon = weapon+1;
+    	NETMSG_SV_WEAPON_PICKUP *msg = (NETMSG_SV_WEAPON_PICKUP *)rawmsg;
+        picked_up_weapon = msg->weapon+1;
     }
-	else if(msg == MSG_READY_TO_ENTER)
+	else if(msgtype == NETMSGTYPE_SV_READY_TO_ENTER)
 	{
 		client_entergame();
 	}
-	else if(msg == MSG_KILLMSG)
+	else if(msgtype == NETMSGTYPE_SV_KILLMSG)
 	{
+		NETMSG_SV_KILLMSG *msg = (NETMSG_SV_KILLMSG *)rawmsg;
+		
 		// unpack messages
-		killmsg msg;
-		msg.killer = msg_unpack_int();
-		msg.victim = msg_unpack_int();
-		msg.weapon = msg_unpack_int();
-		msg.mode_special = msg_unpack_int();
-		msg.tick = client_tick();
-
-		// check for unpacking errors
-		if(msg_unpack_error() || msg.killer >= MAX_CLIENTS || msg.victim >= MAX_CLIENTS || msg.weapon >= NUM_WEAPONS)
-			return;
+		killmsg kill;
+		kill.killer = msg->killer;
+		kill.victim = msg->victim;
+		kill.weapon = msg->weapon;
+		kill.mode_special = msg->mode_special;
+		kill.tick = client_tick();
 
 		// add the message
 		killmsg_current = (killmsg_current+1)%killmsg_max;
-		killmsgs[killmsg_current] = msg;
+		killmsgs[killmsg_current] = kill;
 	}
-	else if (msg == MSG_EMOTICON)
+	else if (msgtype == NETMSGTYPE_SV_EMOTICON)
 	{
-		// unpack
-		int cid = msg_unpack_int();
-		int emoticon = msg_unpack_int();
-
-		// check for errors
-		if(msg_unpack_error() || cid < 0 || cid >= MAX_CLIENTS)
-			return;
+		NETMSG_SV_EMOTICON *msg = (NETMSG_SV_EMOTICON *)rawmsg;
 
 		// apply
-		client_datas[cid].emoticon = emoticon;
-		client_datas[cid].emoticon_start = client_tick();
+		client_datas[msg->cid].emoticon = msg->emoticon;
+		client_datas[msg->cid].emoticon_start = client_tick();
 	}
-	else if(msg == MSG_SOUND_GLOBAL)
+	else if(msgtype == NETMSGTYPE_SV_SOUND_GLOBAL)
 	{
-		int soundid = msg_unpack_int();
-		if(msg_unpack_error() || soundid < 0)
-			return;
-		snd_play_random(CHN_GLOBAL, soundid, 1.0f, vec2(0,0));
+		NETMSG_SV_SOUND_GLOBAL *msg = (NETMSG_SV_SOUND_GLOBAL *)rawmsg;
+		snd_play_random(CHN_GLOBAL, msg->soundid, 1.0f, vec2(0,0));
 	}
 }
 
diff --git a/src/game/g_protocol.def b/src/game/g_protocol.def
index 3d411e45..6e0a4806 100644
--- a/src/game/g_protocol.def
+++ b/src/game/g_protocol.def
@@ -1,10 +1,10 @@
 
 raw_source
+	#include <engine/e_common_interface.h>
 	#include "g_protocol.h"
 	extern "C" {
 		#include "g_protocol_ids.h"
 	}
-	#include <engine/e_common_interface.h>
 	#define max_int 2147483647
 end
 
@@ -35,31 +35,7 @@ raw_header
 		
 		// other stuff
 		INPUT_STATE_MASK=0x1f,
-	};
-	
-	enum
-	{
-		MSG_NULL=0,
-		
-		MSG_MOTD, // server -> client, message of the day
-		
-		MSG_SAY, // client -> server
-		MSG_CHAT, // server -> client
-		MSG_SETINFO, // server -> client - contains name, skin and color info
-		MSG_KILLMSG, // server -> client
-		MSG_SETTEAM,
-		MSG_JOIN,
-		MSG_QUIT,
-		MSG_EMOTICON,
-		MSG_STARTINFO, // client -> server
-		MSG_CHANGEINFO, // client -> server
-		MSG_READY_TO_ENTER, // server -> client
-		MSG_WEAPON_PICKUP,
-		MSG_SOUND_GLOBAL,
-		MSG_TUNE_PARAMS,
-		MSG_KILL,
-		MSG_EXTRA_PROJECTILE, // server -> client
-		
+		NUM_EMOTICONS=16,
 	};
 	
 end
@@ -211,3 +187,88 @@ event damageind
 	any x, y
 	any angle
 end
+
+message sv_motd
+	string message
+end
+
+message cl_say
+	range(0, 1) team
+	string message
+end
+
+message sv_chat
+	range(0, 1) team
+	clientid cid
+	string message
+end
+
+message sv_setinfo
+	clientid cid
+	string name
+	string skin
+	range(0,1) use_custom_color
+	any color_body
+	any color_feet
+end
+
+message sv_killmsg
+	clientid killer
+	clientid victim
+	range(-1,NUM_WEAPONS-1) weapon
+	any mode_special
+end
+
+message cl_setteam
+	range(-1,1) team
+end
+
+message sv_ready_to_ender
+end
+
+message sv_sound_global
+	range(0, NUM_SOUNDS-1) soundid
+end
+
+message cl_startinfo
+	clientid who
+	string name
+	string skin
+	range(0,1) use_custom_color
+	any color_body
+	any color_feet
+end
+
+message cl_changeinfo
+	clientid who
+	string name
+	string skin
+	range(0,1) use_custom_color
+	any color_body
+	any color_feet
+end
+
+message sv_weapon_pickup
+	range(0,NUM_WEAPONS-1) weapon
+end
+
+message sv_emoticon
+	clientid cid
+	range(0,NUM_EMOTICONS-1) emoticon
+end
+
+message cl_emoticon
+	range(0,NUM_EMOTICONS-1) emoticon
+end
+
+message cl_kill
+end
+
+message sv_tune_params
+end
+
+message sv_extra_projectile
+end
+
+message sv_ready_to_enter
+end
diff --git a/src/game/server/gs_server.cpp b/src/game/server/gs_server.cpp
index 724ef36f..356a2fba 100644
--- a/src/game/server/gs_server.cpp
+++ b/src/game/server/gs_server.cpp
@@ -28,29 +28,29 @@ class player *closest_player(vec2 pos, float radius, entity *notthis);
 
 game_world *world;
 
-void send_chat(int cid, int team, const char *msg)
+void send_chat(int cid, int team, const char *text)
 {
 	if(cid >= 0 && cid < MAX_CLIENTS)
-		dbg_msg("chat", "%d:%d:%s: %s", cid, team, server_clientname(cid), msg);
+		dbg_msg("chat", "%d:%d:%s: %s", cid, team, server_clientname(cid), text);
 	else
-		dbg_msg("chat", "*** %s", msg);
+		dbg_msg("chat", "*** %s", text);
 
 	if(team == -1)
 	{
-		msg_pack_start(MSG_CHAT, MSGFLAG_VITAL);
-		msg_pack_int(cid);
-		msg_pack_int(0);
-		msg_pack_string(msg, 512);
-		msg_pack_end();
+		NETMSG_SV_CHAT msg;
+		msg.team = 0;
+		msg.cid = cid;
+		msg.message = text;
+		msg.pack(MSGFLAG_VITAL);
 		server_send_msg(-1);
 	}
 	else
 	{
-		msg_pack_start(MSG_CHAT, MSGFLAG_VITAL);
-		msg_pack_int(cid);
-		msg_pack_int(1);
-		msg_pack_string(msg, 512);
-		msg_pack_end();
+		NETMSG_SV_CHAT msg;
+		msg.team = 1;
+		msg.cid = cid;
+		msg.message = text;
+		msg.pack(MSGFLAG_VITAL);
 
 		for(int i = 0; i < MAX_CLIENTS; i++)
 		{
@@ -63,7 +63,7 @@ void send_chat(int cid, int team, const char *msg)
 
 void send_tuning_params(int cid)
 {
-	msg_pack_start(MSG_TUNE_PARAMS, MSGFLAG_VITAL);
+	msg_pack_start(NETMSGTYPE_SV_TUNE_PARAMS, MSGFLAG_VITAL);
 	int *params = (int *)&tuning;
 	for(unsigned i = 0; i < sizeof(tuning_params)/sizeof(int); i++)
 		msg_pack_int(params[i]);
@@ -1022,7 +1022,7 @@ void player::fire_weapon()
 			NETOBJ_PROJECTILE p;
 			proj->fill_info(&p);
 			
-			msg_pack_start(MSG_EXTRA_PROJECTILE, 0);
+			msg_pack_start(NETMSGTYPE_SV_EXTRA_PROJECTILE, 0);
 			msg_pack_int(1);
 			for(unsigned i = 0; i < sizeof(NETOBJ_PROJECTILE)/sizeof(int); i++)
 				msg_pack_int(((int *)&p)[i]);
@@ -1046,7 +1046,7 @@ void player::fire_weapon()
 			NETOBJ_PROJECTILE p;
 			proj->fill_info(&p);
 			
-			msg_pack_start(MSG_EXTRA_PROJECTILE, 0);
+			msg_pack_start(NETMSGTYPE_SV_EXTRA_PROJECTILE, 0);
 			msg_pack_int(1);
 			for(unsigned i = 0; i < sizeof(NETOBJ_PROJECTILE)/sizeof(int); i++)
 				msg_pack_int(((int *)&p)[i]);
@@ -1060,7 +1060,7 @@ void player::fire_weapon()
 		{
 			int shotspread = 2;
 
-			msg_pack_start(MSG_EXTRA_PROJECTILE, 0);
+			msg_pack_start(NETMSGTYPE_SV_EXTRA_PROJECTILE, 0);
 			msg_pack_int(shotspread*2+1);
 			
 			for(int i = -shotspread; i <= shotspread; i++)
@@ -1507,12 +1507,12 @@ void player::die(int killer, int weapon)
 		client_id, server_clientname(client_id), weapon, mode_special);
 
 	// send the kill message
-	msg_pack_start(MSG_KILLMSG, MSGFLAG_VITAL);
-	msg_pack_int(killer);
-	msg_pack_int(client_id);
-	msg_pack_int(weapon);
-	msg_pack_int(mode_special);
-	msg_pack_end();
+	NETMSG_SV_KILLMSG msg;
+	msg.killer = killer;
+	msg.victim = client_id;
+	msg.weapon = weapon;
+	msg.mode_special = mode_special;
+	msg.pack(MSGFLAG_VITAL);
 	server_send_msg(-1);
 
 	// a nice sound
@@ -1939,8 +1939,9 @@ void create_sound_global(int sound, int target)
 	if (sound < 0)
 		return;
 
-	msg_pack_start(MSG_SOUND_GLOBAL, MSGFLAG_VITAL);
-	msg_pack_int(sound);
+	NETMSG_SV_SOUND_GLOBAL msg;
+	msg.soundid = sound;
+	msg.pack(MSGFLAG_VITAL);
 	server_send_msg(target);
 }
 
@@ -2097,31 +2098,32 @@ void mods_client_predicted_input(int client_id, void *input)
 
 void send_info(int who, int to_who)
 {
-	msg_pack_start(MSG_SETINFO, MSGFLAG_VITAL);
-	msg_pack_int(who);
-	msg_pack_string(server_clientname(who), 64);
-	msg_pack_string(players[who].skin_name, 64);
-	msg_pack_int(players[who].use_custom_color);
-	msg_pack_int(players[who].color_body);
-	msg_pack_int(players[who].color_feet);
-	msg_pack_end();
+	NETMSG_SV_SETINFO msg;
+	msg.cid = who;
+	msg.name = server_clientname(who);
+	msg.skin = players[who].skin_name;
+	msg.use_custom_color = players[who].use_custom_color;
+	msg.color_body = players[who].color_body;
+	msg.color_feet =players[who].color_feet;
+	msg.pack(MSGFLAG_VITAL);
+	
 	server_send_msg(to_who);
 }
 
 void send_emoticon(int cid, int emoticon)
 {
-	msg_pack_start(MSG_EMOTICON, MSGFLAG_VITAL);
-	msg_pack_int(cid);
-	msg_pack_int(emoticon % 16);
-	msg_pack_end();
+	NETMSG_SV_EMOTICON msg;
+	msg.cid = cid;
+	msg.emoticon = emoticon;
+	msg.pack(MSGFLAG_VITAL);
 	server_send_msg(-1);
 }
 
 void send_weapon_pickup(int cid, int weapon)
 {
-	msg_pack_start(MSG_WEAPON_PICKUP, MSGFLAG_VITAL);
-	msg_pack_int(weapon);
-	msg_pack_end();
+	NETMSG_SV_WEAPON_PICKUP msg;
+	msg.weapon = weapon;
+	msg.pack(MSGFLAG_VITAL);
 	server_send_msg(cid);
 }
 
@@ -2158,10 +2160,10 @@ void mods_connected(int client_id)
 			players[client_id].team = gameobj->getteam(client_id);
 	}
 
-	// send motd	
-	msg_pack_start(MSG_MOTD, MSGFLAG_VITAL);
-	msg_pack_string(config.sv_motd, 900);
-	msg_pack_end();
+	// send motd
+	NETMSG_SV_MOTD msg;
+	msg.message = config.sv_motd;
+	msg.pack(MSGFLAG_VITAL);
 	server_send_msg(client_id);
 }
 
@@ -2179,22 +2181,32 @@ void mods_client_drop(int client_id)
 	players[client_id].client_id = -1;
 }
 
-void mods_message(int msg, int client_id)
+void mods_message(int msgtype, int client_id)
 {
-	if(msg == MSG_SAY)
+	void *rawmsg = netmsg_secure_unpack(msgtype);
+	if(!rawmsg)
+	{
+		dbg_msg("server", "dropped weird message '%s' (%d)", netmsg_get_name(msgtype), msgtype);
+		return;
+	}
+	
+	if(msgtype == NETMSGTYPE_CL_SAY)
 	{
-		int team = msg_unpack_int();
-		const char *text = msg_unpack_string();
+		NETMSG_CL_SAY *msg = (NETMSG_CL_SAY *)rawmsg;
+		
+		int team = msg->team;
 		if(team)
 			team = players[client_id].team;
 		else
 			team = -1;
-		send_chat(client_id, team, text);
+		send_chat(client_id, msg->team, msg->message);
 	}
-	else if (msg == MSG_SETTEAM)
+	else if (msgtype == NETMSGTYPE_CL_SETTEAM)
 	{
+		NETMSG_CL_SETTEAM *msg = (NETMSG_CL_SETTEAM *)rawmsg;
+
 		// Switch team on given client and kill/respawn him
-		players[client_id].set_team(msg_unpack_int());
+		players[client_id].set_team(msg->team);
 		gameobj->on_player_info_change(&players[client_id]);
 		
 		// send all info to this client
@@ -2204,38 +2216,38 @@ void mods_message(int msg, int client_id)
 				send_info(i, -1);
 		}		
 	}
-	else if (msg == MSG_CHANGEINFO || msg == MSG_STARTINFO)
+	else if (msgtype == NETMSGTYPE_CL_CHANGEINFO || msgtype == NETMSGTYPE_CL_STARTINFO)
 	{
-		const char *name = msg_unpack_string();
-		const char *skin_name = msg_unpack_string();
-		players[client_id].use_custom_color = msg_unpack_int();
-		players[client_id].color_body = msg_unpack_int();
-		players[client_id].color_feet = msg_unpack_int();
+		NETMSG_CL_CHANGEINFO *msg = (NETMSG_CL_CHANGEINFO *)rawmsg;
+		players[client_id].use_custom_color = msg->use_custom_color;
+		players[client_id].color_body = msg->color_body;
+		players[client_id].color_feet = msg->color_feet;
 
 		// check for invalid chars
+		/*
 		unsigned char *p = (unsigned char *)name;
 		while (*p)
 		{
 			if(*p < 32)
 				*p = ' ';
 			p++;
-		}
+		}*/
 
 		//
-		if(msg == MSG_CHANGEINFO && strcmp(name, server_clientname(client_id)) != 0)
+		if(msgtype == NETMSGTYPE_CL_CHANGEINFO && strcmp(msg->name, server_clientname(client_id)) != 0)
 		{
-			char msg[256];
-			str_format(msg, sizeof(msg), "*** %s changed name to %s", server_clientname(client_id), name);
-			send_chat(-1, -1, msg);
+			char chattext[256];
+			str_format(chattext, sizeof(chattext), "*** %s changed name to %s", server_clientname(client_id), msg->name);
+			send_chat(-1, -1, chattext);
 		}
 
 		//send_set_name(client_id, players[client_id].name, name);
-		str_copy(players[client_id].skin_name, skin_name, sizeof(players[client_id].skin_name));
-		server_setclientname(client_id, name);
+		str_copy(players[client_id].skin_name, msg->skin, sizeof(players[client_id].skin_name));
+		server_setclientname(client_id, msg->name);
 		
 		gameobj->on_player_info_change(&players[client_id]);
 		
-		if(msg == MSG_STARTINFO)
+		if(msgtype == NETMSGTYPE_CL_STARTINFO)
 		{
 			// a client that connected!
 			
@@ -2250,22 +2262,20 @@ void mods_message(int msg, int client_id)
 			send_tuning_params(client_id);
 			
 			//
-			msg_pack_start(MSG_READY_TO_ENTER, MSGFLAG_VITAL);
-			msg_pack_end();
+			NETMSG_SV_READY_TO_ENTER m;
+			m.pack(MSGFLAG_VITAL);
 			server_send_msg(client_id);			
 		}
 		
 		send_info(client_id, -1);
 	}
-	else if (msg == MSG_EMOTICON)
+	else if (msgtype == NETMSGTYPE_CL_EMOTICON)
 	{
-		int emoteicon = msg_unpack_int();
-		send_emoticon(client_id, emoteicon % 16);
+		NETMSG_CL_EMOTICON *msg = (NETMSG_CL_EMOTICON *)rawmsg;
+		send_emoticon(client_id, msg->emoticon);
 	}
-	else if (msg == MSG_KILL)
+	else if (msgtype == NETMSGTYPE_CL_KILL)
 	{
-		//int kill_client_id = msg_unpack_int(); // to be used to kill players from rcon? hihi
-
 		player *pplayer = get_player(client_id);
 		pplayer->die(client_id, -1);
 	}