changeset 16223:87eaf077e2a1 draft

(svn r20924) -Codechange: make the game connection packet handling look more like UDP/content packet handling
author rubidium <rubidium@openttd.org>
date Fri, 15 Oct 2010 13:47:37 +0000
parents 1a34081a4bc4
children 8192961db36e
files src/network/core/tcp_content.cpp src/network/core/tcp_game.cpp src/network/core/tcp_game.h src/network/network.cpp src/network/network_client.cpp src/network/network_client.h src/network/network_server.cpp src/network/network_server.h
diffstat 8 files changed, 387 insertions(+), 303 deletions(-) [+]
line wrap: on
line diff
--- a/src/network/core/tcp_content.cpp
+++ b/src/network/core/tcp_content.cpp
@@ -115,7 +115,7 @@
 }
 
 /**
- * Receive a packet at UDP level
+ * Receive a packet at TCP level
  */
 void NetworkContentSocketHandler::Recv_Packets()
 {
--- a/src/network/core/tcp_game.cpp
+++ b/src/network/core/tcp_game.cpp
@@ -18,6 +18,7 @@
 #include "../network.h"
 #include "../network_internal.h"
 #include "../../core/pool_func.hpp"
+#include "../../debug.h"
 
 #include "table/strings.h"
 
@@ -63,4 +64,147 @@
 	return NetworkCloseClient(this, error ? NETWORK_RECV_STATUS_SERVER_ERROR : NETWORK_RECV_STATUS_CONN_LOST);
 }
 
+
+/**
+ * Defines a simple (switch) case for each network packet
+ * @param type the packet type to create the case for
+ */
+#define GAME_COMMAND(type) case type: return this->NetworkPacketReceive_ ## type ## _command(p); break;
+
+/**
+ * Handle the given packet, i.e. pass it to the right parser receive command.
+ * @param p the packet to handle
+ * @return #NetworkRecvStatus of handling.
+ */
+NetworkRecvStatus NetworkClientSocket::HandlePacket(Packet *p)
+{
+	PacketGameType type = (PacketGameType)p->Recv_uint8();
+
+	switch (this->HasClientQuit() ? PACKET_END : type) {
+		GAME_COMMAND(PACKET_SERVER_FULL)
+		GAME_COMMAND(PACKET_SERVER_BANNED)
+		GAME_COMMAND(PACKET_CLIENT_JOIN)
+		GAME_COMMAND(PACKET_SERVER_ERROR)
+		GAME_COMMAND(PACKET_CLIENT_COMPANY_INFO)
+		GAME_COMMAND(PACKET_SERVER_COMPANY_INFO)
+		GAME_COMMAND(PACKET_SERVER_CLIENT_INFO)
+		GAME_COMMAND(PACKET_SERVER_NEED_GAME_PASSWORD)
+		GAME_COMMAND(PACKET_SERVER_NEED_COMPANY_PASSWORD)
+		GAME_COMMAND(PACKET_CLIENT_GAME_PASSWORD)
+		GAME_COMMAND(PACKET_CLIENT_COMPANY_PASSWORD)
+		GAME_COMMAND(PACKET_SERVER_WELCOME)
+		GAME_COMMAND(PACKET_CLIENT_GETMAP)
+		GAME_COMMAND(PACKET_SERVER_WAIT)
+		GAME_COMMAND(PACKET_SERVER_MAP)
+		GAME_COMMAND(PACKET_CLIENT_MAP_OK)
+		GAME_COMMAND(PACKET_SERVER_JOIN)
+		GAME_COMMAND(PACKET_SERVER_FRAME)
+		GAME_COMMAND(PACKET_SERVER_SYNC)
+		GAME_COMMAND(PACKET_CLIENT_ACK)
+		GAME_COMMAND(PACKET_CLIENT_COMMAND)
+		GAME_COMMAND(PACKET_SERVER_COMMAND)
+		GAME_COMMAND(PACKET_CLIENT_CHAT)
+		GAME_COMMAND(PACKET_SERVER_CHAT)
+		GAME_COMMAND(PACKET_CLIENT_SET_PASSWORD)
+		GAME_COMMAND(PACKET_CLIENT_SET_NAME)
+		GAME_COMMAND(PACKET_CLIENT_QUIT)
+		GAME_COMMAND(PACKET_CLIENT_ERROR)
+		GAME_COMMAND(PACKET_SERVER_QUIT)
+		GAME_COMMAND(PACKET_SERVER_ERROR_QUIT)
+		GAME_COMMAND(PACKET_SERVER_SHUTDOWN)
+		GAME_COMMAND(PACKET_SERVER_NEWGAME)
+		GAME_COMMAND(PACKET_SERVER_RCON)
+		GAME_COMMAND(PACKET_CLIENT_RCON)
+		GAME_COMMAND(PACKET_SERVER_CHECK_NEWGRFS)
+		GAME_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED)
+		GAME_COMMAND(PACKET_SERVER_MOVE)
+		GAME_COMMAND(PACKET_CLIENT_MOVE)
+		GAME_COMMAND(PACKET_SERVER_COMPANY_UPDATE)
+		GAME_COMMAND(PACKET_SERVER_CONFIG_UPDATE)
+
+		default:
+			this->CloseConnection();
+
+			if (this->HasClientQuit()) {
+				DEBUG(net, 0, "[tcp/game] received invalid packet type %d from client %d", type, this->client_id);
+			} else {
+				DEBUG(net, 0, "[tcp/game] received illegal packet from client %d", this->client_id);
+			}
+			return NETWORK_RECV_STATUS_MALFORMED_PACKET;
+	}
+}
+
+/**
+ * Do the actual receiving of packets.
+ * As long as HandlePacket returns OKAY packets are handled. Upon
+ * failure, or no more packets to process the last result of
+ * HandlePacket is returned.
+ * @return #NetworkRecvStatus of the last handled packet.
+ */
+NetworkRecvStatus NetworkClientSocket::Recv_Packets()
+{
+	Packet *p;
+	while ((p = this->Recv_Packet()) != NULL) {
+		NetworkRecvStatus res = HandlePacket(p);
+		if (res != NETWORK_RECV_STATUS_OKAY) return res;
+	}
+
+	return NETWORK_RECV_STATUS_OKAY;
+}
+
+/**
+ * Create stub implementations for all receive commands that only
+ * show a warning that the given command is not available for the
+ * socket where the packet came from.
+ * @param type the packet type to create the stub for
+ */
+#define DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(type) \
+NetworkRecvStatus NetworkClientSocket::NetworkPacketReceive_## type ##_command(Packet *p) \
+{ \
+	DEBUG(net, 0, "[tcp/game] received illegal packet type %d from client %d", \
+			type, this->client_id); \
+	return NETWORK_RECV_STATUS_MALFORMED_PACKET; \
+}
+
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_FULL)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_BANNED)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_JOIN)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_ERROR)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_INFO)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_COMPANY_INFO)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_CLIENT_INFO)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_NEED_GAME_PASSWORD)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_NEED_COMPANY_PASSWORD)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_GAME_PASSWORD)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_PASSWORD)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_WELCOME)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_GETMAP)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_WAIT)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_MAP)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_MAP_OK)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_JOIN)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_FRAME)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_SYNC)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_ACK)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_COMMAND)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_CHAT)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_CHAT)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_SET_PASSWORD)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_SET_NAME)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_QUIT)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_ERROR)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_QUIT)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_ERROR_QUIT)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_SHUTDOWN)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_NEWGAME)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_RCON)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_RCON)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_CHECK_NEWGRFS)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_MOVE)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_MOVE)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_COMPANY_UPDATE)
+DEFINE_UNAVAILABLE_GAME_RECEIVE_COMMAND(PACKET_SERVER_CONFIG_UPDATE)
+
 #endif /* ENABLE_NETWORK */
--- a/src/network/core/tcp_game.h
+++ b/src/network/core/tcp_game.h
@@ -27,7 +27,7 @@
  * it protects old clients from joining newer servers
  * (because SERVER_ERROR is the respond to a wrong revision)
  */
-enum TCPPacketType {
+enum PacketGameType {
 	PACKET_SERVER_FULL,
 	PACKET_SERVER_BANNED,
 	PACKET_CLIENT_JOIN,
@@ -113,12 +113,59 @@
 typedef Pool<NetworkClientSocket, ClientIndex, 8, MAX_CLIENT_SLOTS> NetworkClientSocketPool;
 extern NetworkClientSocketPool _networkclientsocket_pool;
 
+#define DECLARE_GAME_RECEIVE_COMMAND(type) virtual NetworkRecvStatus NetworkPacketReceive_## type ##_command(Packet *p)
+#define DEF_GAME_RECEIVE_COMMAND(cls, type) NetworkRecvStatus cls ##NetworkGameSocketHandler::NetworkPacketReceive_ ## type ## _command(Packet *p)
+
 /** Base socket handler for all TCP sockets */
 class NetworkGameSocketHandler : public NetworkClientSocketPool::PoolItem<&_networkclientsocket_pool>, public NetworkTCPSocketHandler {
 /* TODO: rewrite into a proper class */
 private:
 	NetworkClientInfo *info;  ///< Client info related to this socket
+
 protected:
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_FULL);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_BANNED);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_JOIN);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_ERROR);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_INFO);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_COMPANY_INFO);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_CLIENT_INFO);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_NEED_GAME_PASSWORD);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_NEED_COMPANY_PASSWORD);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_GAME_PASSWORD);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_PASSWORD);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_WELCOME);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_GETMAP);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_WAIT);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_MAP);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_MAP_OK);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_JOIN);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_FRAME);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_SYNC);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_ACK);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_COMMAND);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_CHAT);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_CHAT);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_SET_PASSWORD);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_SET_NAME);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_QUIT);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_ERROR);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_QUIT);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_ERROR_QUIT);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_SHUTDOWN);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_NEWGAME);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_RCON);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_RCON);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_CHECK_NEWGRFS);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_MOVE);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_MOVE);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_COMPANY_UPDATE);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_CONFIG_UPDATE);
+
+	NetworkRecvStatus HandlePacket(Packet *p);
+
 	NetworkGameSocketHandler(SOCKET s);
 public:
 	ClientID client_id;       ///< Client identifier
@@ -137,6 +184,8 @@
 	inline void SetInfo(NetworkClientInfo *info) { assert(info != NULL && this->info == NULL); this->info = info; }
 	inline NetworkClientInfo *GetInfo() const { return this->info; }
 
+	NetworkRecvStatus Recv_Packets();
+
 	const char *Recv_Command(Packet *p, CommandPacket *cp);
 	void Send_Command(Packet *p, const CommandPacket *cp);
 };
--- a/src/network/network.cpp
+++ b/src/network/network.cpp
@@ -939,14 +939,14 @@
 		cs->writable = !!FD_ISSET(cs->sock, &write_fd);
 		if (FD_ISSET(cs->sock, &read_fd)) {
 			if (_network_server) {
-				NetworkServer_ReadPackets(cs);
+				cs->Recv_Packets();
 			} else {
 				NetworkRecvStatus res;
 
 				/* The client already was quiting! */
 				if (cs->HasClientQuit()) return false;
 
-				res = NetworkClient_ReadPackets(cs);
+				res = cs->Recv_Packets();
 				if (res != NETWORK_RECV_STATUS_OKAY) {
 					/* The client made an error of which we can not recover
 					 *   close the client and drop back to main menu */
--- a/src/network/network_client.cpp
+++ b/src/network/network_client.cpp
@@ -392,7 +392,7 @@
 extern bool SafeSaveOrLoad(const char *filename, int mode, GameMode newgm, Subdirectory subdir);
 extern StringID _switch_mode_errorstr;
 
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_FULL)
+DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_FULL)
 {
 	/* We try to join a server which is full */
 	_switch_mode_errorstr = STR_NETWORK_ERROR_SERVER_FULL;
@@ -401,7 +401,7 @@
 	return NETWORK_RECV_STATUS_SERVER_FULL;
 }
 
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_BANNED)
+DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_BANNED)
 {
 	/* We try to join a server where we are banned */
 	_switch_mode_errorstr = STR_NETWORK_ERROR_SERVER_BANNED;
@@ -410,11 +410,11 @@
 	return NETWORK_RECV_STATUS_SERVER_BANNED;
 }
 
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_COMPANY_INFO)
+DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_COMPANY_INFO)
 {
 	byte company_info_version = p->Recv_uint8();
 
-	if (!MY_CLIENT->HasClientQuit() && company_info_version == NETWORK_COMPANY_INFO_VERSION) {
+	if (!this->HasClientQuit() && company_info_version == NETWORK_COMPANY_INFO_VERSION) {
 		/* We have received all data... (there are no more packets coming) */
 		if (!p->Recv_bool()) return NETWORK_RECV_STATUS_CLOSE_QUERY;
 
@@ -452,7 +452,7 @@
 /* This packet contains info about the client (playas and name)
  *  as client we save this in NetworkClientInfo, linked via 'client_id'
  *  which is always an unique number on a server. */
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_CLIENT_INFO)
+DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_CLIENT_INFO)
 {
 	NetworkClientInfo *ci;
 	ClientID client_id = (ClientID)p->Recv_uint32();
@@ -461,7 +461,7 @@
 
 	p->Recv_string(name, sizeof(name));
 
-	if (MY_CLIENT->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
+	if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
 
 	ci = NetworkFindClientInfoFromClientID(client_id);
 	if (ci != NULL) {
@@ -488,7 +488,7 @@
 	/* We don't have this client_id yet, find an empty client_id, and put the data there */
 	ci = new NetworkClientInfo(client_id);
 	ci->client_playas = playas;
-	if (client_id == _network_own_client_id) MY_CLIENT->SetInfo(ci);
+	if (client_id == _network_own_client_id) this->SetInfo(ci);
 
 	strecpy(ci->client_name, name, lastof(ci->client_name));
 
@@ -497,7 +497,7 @@
 	return NETWORK_RECV_STATUS_OKAY;
 }
 
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_ERROR)
+DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_ERROR)
 {
 	NetworkErrorCode error = (NetworkErrorCode)p->Recv_uint8();
 
@@ -535,7 +535,7 @@
 	return NETWORK_RECV_STATUS_SERVER_ERROR;
 }
 
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_CHECK_NEWGRFS)
+DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_CHECK_NEWGRFS)
 {
 	uint grf_count = p->Recv_uint8();
 	NetworkRecvStatus ret = NETWORK_RECV_STATUS_OKAY;
@@ -543,7 +543,7 @@
 	/* Check all GRFs */
 	for (; grf_count > 0; grf_count--) {
 		GRFIdentifier c;
-		MY_CLIENT->Recv_GRFIdentifier(p, &c);
+		this->Recv_GRFIdentifier(p, &c);
 
 		/* Check whether we know this GRF */
 		const GRFConfig *f = FindGRFConfig(c.grfid, c.md5sum);
@@ -566,7 +566,7 @@
 	return ret;
 }
 
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_NEED_GAME_PASSWORD)
+DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_NEED_GAME_PASSWORD)
 {
 	const char *password = _network_join_server_password;
 	if (!StrEmpty(password)) {
@@ -578,11 +578,11 @@
 	return NETWORK_RECV_STATUS_OKAY;
 }
 
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_NEED_COMPANY_PASSWORD)
+DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_NEED_COMPANY_PASSWORD)
 {
 	_password_game_seed = p->Recv_uint32();
 	p->Recv_string(_password_server_id, sizeof(_password_server_id));
-	if (MY_CLIENT->HasClientQuit()) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
+	if (this->HasClientQuit()) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
 
 	const char *password = _network_join_company_password;
 	if (!StrEmpty(password)) {
@@ -594,7 +594,7 @@
 	return NETWORK_RECV_STATUS_OKAY;
 }
 
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_WELCOME)
+DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_WELCOME)
 {
 	_network_own_client_id = (ClientID)p->Recv_uint32();
 
@@ -606,7 +606,7 @@
 	return SEND_COMMAND(PACKET_CLIENT_GETMAP)();
 }
 
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_WAIT)
+DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_WAIT)
 {
 	_network_join_status = NETWORK_JOIN_STATUS_WAITING;
 	_network_join_waiting = p->Recv_uint8();
@@ -619,7 +619,7 @@
 	return NETWORK_RECV_STATUS_OKAY;
 }
 
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_MAP)
+DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_MAP)
 {
 	static FILE *file_pointer;
 
@@ -627,7 +627,7 @@
 
 	maptype = p->Recv_uint8();
 
-	if (MY_CLIENT->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
+	if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
 
 	/* First packet, init some stuff */
 	if (maptype == MAP_PACKET_START) {
@@ -647,7 +647,7 @@
 		 * do a division by zero. When the connection is lost, we just return
 		 * that. If kbytes_total is 0, the packet must be malformed as a
 		 * savegame less than 1 kilobyte is practically impossible. */
-		if (MY_CLIENT->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
+		if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
 		if (_network_join_bytes_total == 0) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
 
 		_network_join_status = NETWORK_JOIN_STATUS_DOWNLOADING;
@@ -708,7 +708,7 @@
 	return NETWORK_RECV_STATUS_OKAY;
 }
 
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_FRAME)
+DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_FRAME)
 {
 	_frame_counter_server = p->Recv_uint32();
 	_frame_counter_max = p->Recv_uint32();
@@ -736,7 +736,7 @@
 	return NETWORK_RECV_STATUS_OKAY;
 }
 
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_SYNC)
+DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_SYNC)
 {
 	_sync_frame = p->Recv_uint32();
 	_sync_seed_1 = p->Recv_uint32();
@@ -747,10 +747,10 @@
 	return NETWORK_RECV_STATUS_OKAY;
 }
 
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_COMMAND)
+DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_COMMAND)
 {
 	CommandPacket cp;
-	const char *err = MY_CLIENT->Recv_Command(p, &cp);
+	const char *err = this->Recv_Command(p, &cp);
 	cp.frame    = p->Recv_uint32();
 	cp.my_cmd   = p->Recv_bool();
 
@@ -759,12 +759,12 @@
 		return NETWORK_RECV_STATUS_MALFORMED_PACKET;
 	}
 
-	MY_CLIENT->incoming_queue.Append(&cp);
+	this->incoming_queue.Append(&cp);
 
 	return NETWORK_RECV_STATUS_OKAY;
 }
 
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_CHAT)
+DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_CHAT)
 {
 	char name[NETWORK_NAME_LENGTH], msg[NETWORK_CHAT_LENGTH];
 	const NetworkClientInfo *ci = NULL, *ci_to;
@@ -814,7 +814,7 @@
 	return NETWORK_RECV_STATUS_OKAY;
 }
 
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_ERROR_QUIT)
+DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_ERROR_QUIT)
 {
 	ClientID client_id = (ClientID)p->Recv_uint32();
 
@@ -829,7 +829,7 @@
 	return NETWORK_RECV_STATUS_OKAY;
 }
 
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_QUIT)
+DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_QUIT)
 {
 	NetworkClientInfo *ci;
 
@@ -849,7 +849,7 @@
 	return NETWORK_RECV_STATUS_OKAY;
 }
 
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_JOIN)
+DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_JOIN)
 {
 	ClientID client_id = (ClientID)p->Recv_uint32();
 
@@ -863,14 +863,14 @@
 	return NETWORK_RECV_STATUS_OKAY;
 }
 
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_SHUTDOWN)
+DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_SHUTDOWN)
 {
 	_switch_mode_errorstr = STR_NETWORK_MESSAGE_SERVER_SHUTDOWN;
 
 	return NETWORK_RECV_STATUS_SERVER_ERROR;
 }
 
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_NEWGAME)
+DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_NEWGAME)
 {
 	/* To trottle the reconnects a bit, every clients waits
 	 *  his _local_company value before reconnecting
@@ -882,7 +882,7 @@
 	return NETWORK_RECV_STATUS_SERVER_ERROR;
 }
 
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_RCON)
+DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_RCON)
 {
 	char rcon_out[NETWORK_RCONCOMMAND_LENGTH];
 
@@ -894,7 +894,7 @@
 	return NETWORK_RECV_STATUS_OKAY;
 }
 
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_MOVE)
+DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_MOVE)
 {
 	/* Nothing more in this packet... */
 	ClientID client_id   = (ClientID)p->Recv_uint32();
@@ -920,7 +920,7 @@
 	return NETWORK_RECV_STATUS_OKAY;
 }
 
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_CONFIG_UPDATE)
+DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_CONFIG_UPDATE)
 {
 	_network_server_max_companies = p->Recv_uint8();
 	_network_server_max_spectators = p->Recv_uint8();
@@ -928,7 +928,7 @@
 	return NETWORK_RECV_STATUS_OKAY;
 }
 
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_COMPANY_UPDATE)
+DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_COMPANY_UPDATE)
 {
 	_network_company_passworded = p->Recv_uint16();
 	SetWindowClassesDirty(WC_COMPANY);
@@ -936,60 +936,6 @@
 	return NETWORK_RECV_STATUS_OKAY;
 }
 
-
-/* The layout for the receive-functions by the client */
-typedef NetworkRecvStatus NetworkClientPacket(Packet *p);
-
-/* This array matches PacketType. At an incoming
- *  packet it is matches against this array
- *  and that way the right function to handle that
- *  packet is found. */
-static NetworkClientPacket * const _network_client_packet[] = {
-	RECEIVE_COMMAND(PACKET_SERVER_FULL),
-	RECEIVE_COMMAND(PACKET_SERVER_BANNED),
-	NULL, // PACKET_CLIENT_JOIN,
-	RECEIVE_COMMAND(PACKET_SERVER_ERROR),
-	NULL, // PACKET_CLIENT_COMPANY_INFO,
-	RECEIVE_COMMAND(PACKET_SERVER_COMPANY_INFO),
-	RECEIVE_COMMAND(PACKET_SERVER_CLIENT_INFO),
-	RECEIVE_COMMAND(PACKET_SERVER_NEED_GAME_PASSWORD),
-	RECEIVE_COMMAND(PACKET_SERVER_NEED_COMPANY_PASSWORD),
-	NULL, // PACKET_CLIENT_GAME_PASSWORD,
-	NULL, // PACKET_CLIENT_COMPANY_PASSWORD,
-	RECEIVE_COMMAND(PACKET_SERVER_WELCOME),
-	NULL, // PACKET_CLIENT_GETMAP,
-	RECEIVE_COMMAND(PACKET_SERVER_WAIT),
-	RECEIVE_COMMAND(PACKET_SERVER_MAP),
-	NULL, // PACKET_CLIENT_MAP_OK,
-	RECEIVE_COMMAND(PACKET_SERVER_JOIN),
-	RECEIVE_COMMAND(PACKET_SERVER_FRAME),
-	RECEIVE_COMMAND(PACKET_SERVER_SYNC),
-	NULL, // PACKET_CLIENT_ACK,
-	NULL, // PACKET_CLIENT_COMMAND,
-	RECEIVE_COMMAND(PACKET_SERVER_COMMAND),
-	NULL, // PACKET_CLIENT_CHAT,
-	RECEIVE_COMMAND(PACKET_SERVER_CHAT),
-	NULL, // PACKET_CLIENT_SET_PASSWORD,
-	NULL, // PACKET_CLIENT_SET_NAME,
-	NULL, // PACKET_CLIENT_QUIT,
-	NULL, // PACKET_CLIENT_ERROR,
-	RECEIVE_COMMAND(PACKET_SERVER_QUIT),
-	RECEIVE_COMMAND(PACKET_SERVER_ERROR_QUIT),
-	RECEIVE_COMMAND(PACKET_SERVER_SHUTDOWN),
-	RECEIVE_COMMAND(PACKET_SERVER_NEWGAME),
-	RECEIVE_COMMAND(PACKET_SERVER_RCON),
-	NULL, // PACKET_CLIENT_RCON,
-	RECEIVE_COMMAND(PACKET_SERVER_CHECK_NEWGRFS),
-	NULL, // PACKET_CLIENT_NEWGRFS_CHECKED,
-	RECEIVE_COMMAND(PACKET_SERVER_MOVE),
-	NULL, // PACKET_CLIENT_MOVE
-	RECEIVE_COMMAND(PACKET_SERVER_COMPANY_UPDATE),
-	RECEIVE_COMMAND(PACKET_SERVER_CONFIG_UPDATE),
-};
-
-/* If this fails, check the array above with network_data.h */
-assert_compile(lengthof(_network_client_packet) == PACKET_END);
-
 /* Is called after a client is connected to the server */
 void NetworkClient_Connected()
 {
@@ -1001,27 +947,6 @@
 	SEND_COMMAND(PACKET_CLIENT_JOIN)();
 }
 
-/* Reads the packets from the socket-stream, if available */
-NetworkRecvStatus NetworkClient_ReadPackets(NetworkClientSocket *cs)
-{
-	Packet *p;
-	NetworkRecvStatus res = NETWORK_RECV_STATUS_OKAY;
-
-	while (res == NETWORK_RECV_STATUS_OKAY && (p = cs->Recv_Packet()) != NULL) {
-		byte type = p->Recv_uint8();
-		if (type < PACKET_END && _network_client_packet[type] != NULL && !MY_CLIENT->HasClientQuit()) {
-			res = _network_client_packet[type](p);
-		} else {
-			res = NETWORK_RECV_STATUS_MALFORMED_PACKET;
-			DEBUG(net, 0, "[client] received invalid packet type %d", type);
-		}
-
-		delete p;
-	}
-
-	return res;
-}
-
 void NetworkClientSendRcon(const char *password, const char *command)
 {
 	SEND_COMMAND(PACKET_CLIENT_RCON)(password, command);
--- a/src/network/network_client.h
+++ b/src/network/network_client.h
@@ -18,6 +18,31 @@
 
 /** Class for handling the client side of the game connection. */
 class ClientNetworkGameSocketHandler : public NetworkGameSocketHandler {
+protected:
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_FULL);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_BANNED);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_ERROR);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_COMPANY_INFO);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_CLIENT_INFO);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_NEED_GAME_PASSWORD);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_NEED_COMPANY_PASSWORD);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_WELCOME);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_WAIT);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_MAP);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_JOIN);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_FRAME);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_SYNC);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_COMMAND);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_CHAT);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_QUIT);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_ERROR_QUIT);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_SHUTDOWN);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_NEWGAME);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_RCON);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_CHECK_NEWGRFS);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_MOVE);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_COMPANY_UPDATE);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_SERVER_CONFIG_UPDATE);
 public:
 	ClientNetworkGameSocketHandler(SOCKET s);
 };
@@ -36,7 +61,6 @@
 DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_RCON)(const char *pass, const char *command);
 DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_MOVE)(CompanyID company, const char *pass);
 
-NetworkRecvStatus NetworkClient_ReadPackets(NetworkClientSocket *cs);
 void NetworkClient_Connected();
 
 extern CompanyID _network_join_as;
--- a/src/network/network_server.cpp
+++ b/src/network/network_server.cpp
@@ -682,37 +682,37 @@
  *   DEF_SERVER_RECEIVE_COMMAND has parameter: NetworkClientSocket *cs, Packet *p
  ************/
 
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_INFO)
+DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_COMPANY_INFO)
 {
-	return SEND_COMMAND(PACKET_SERVER_COMPANY_INFO)(cs);
+	return SEND_COMMAND(PACKET_SERVER_COMPANY_INFO)(this);
 }
 
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED)
+DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_NEWGRFS_CHECKED)
 {
-	if (cs->status != STATUS_NEWGRFS_CHECK) {
+	if (this->status != STATUS_NEWGRFS_CHECK) {
 		/* Illegal call, return error and ignore the packet */
-		return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
+		return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_NOT_EXPECTED);
 	}
 
-	NetworkClientInfo *ci = cs->GetInfo();
+	NetworkClientInfo *ci = this->GetInfo();
 
 	/* We now want a password from the client else we do not allow him in! */
 	if (!StrEmpty(_settings_client.network.server_password)) {
-		return SEND_COMMAND(PACKET_SERVER_NEED_GAME_PASSWORD)(cs);
+		return SEND_COMMAND(PACKET_SERVER_NEED_GAME_PASSWORD)(this);
 	}
 
 	if (Company::IsValidID(ci->client_playas) && !StrEmpty(_network_company_states[ci->client_playas].password)) {
-		return SEND_COMMAND(PACKET_SERVER_NEED_COMPANY_PASSWORD)(cs);
+		return SEND_COMMAND(PACKET_SERVER_NEED_COMPANY_PASSWORD)(this);
 	}
 
-	return SEND_COMMAND(PACKET_SERVER_WELCOME)(cs);
+	return SEND_COMMAND(PACKET_SERVER_WELCOME)(this);
 }
 
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_JOIN)
+DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_JOIN)
 {
-	if (cs->status != STATUS_INACTIVE) {
+	if (this->status != STATUS_INACTIVE) {
 		/* Illegal call, return error and ignore the packet */
-		return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
+		return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_NOT_EXPECTED);
 	}
 
 	char name[NETWORK_CLIENT_NAME_LENGTH];
@@ -726,30 +726,30 @@
 	/* Check if the client has revision control enabled */
 	if (!IsNetworkCompatibleVersion(client_revision)) {
 		/* Different revisions!! */
-		return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_WRONG_REVISION);
+		return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_WRONG_REVISION);
 	}
 
 	p->Recv_string(name, sizeof(name));
 	playas = (Owner)p->Recv_uint8();
 	client_lang = (NetworkLanguage)p->Recv_uint8();
 
-	if (cs->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
+	if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
 
 	/* join another company does not affect these values */
 	switch (playas) {
 		case COMPANY_NEW_COMPANY: // New company
 			if (Company::GetNumItems() >= _settings_client.network.max_companies) {
-				return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_FULL);
+				return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_FULL);
 			}
 			break;
 		case COMPANY_SPECTATOR: // Spectator
 			if (NetworkSpectatorCount() >= _settings_client.network.max_spectators) {
-				return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_FULL);
+				return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_FULL);
 			}
 			break;
 		default: // Join another company (companies 1-8 (index 0-7))
 			if (!Company::IsValidHumanID(playas)) {
-				return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_COMPANY_MISMATCH);
+				return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_COMPANY_MISMATCH);
 			}
 			break;
 	}
@@ -759,10 +759,10 @@
 
 	if (!NetworkFindName(name)) { // Change name if duplicate
 		/* We could not create a name for this client */
-		return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NAME_IN_USE);
+		return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_NAME_IN_USE);
 	}
 
-	ci = cs->GetInfo();
+	ci = this->GetInfo();
 
 	strecpy(ci->client_name, name, lastof(ci->client_name));
 	ci->client_playas = playas;
@@ -772,20 +772,20 @@
 	/* Make sure companies to which people try to join are not autocleaned */
 	if (Company::IsValidID(playas)) _network_company_states[playas].months_empty = 0;
 
-	cs->status = STATUS_NEWGRFS_CHECK;
+	this->status = STATUS_NEWGRFS_CHECK;
 
 	if (_grfconfig == NULL) {
 		/* Behave as if we received PACKET_CLIENT_NEWGRFS_CHECKED */
-		return RECEIVE_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED)(cs, NULL);
+		return this->RECEIVE_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED)(NULL);
 	}
 
-	return SEND_COMMAND(PACKET_SERVER_CHECK_NEWGRFS)(cs);
+	return SEND_COMMAND(PACKET_SERVER_CHECK_NEWGRFS)(this);
 }
 
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_GAME_PASSWORD)
+DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_GAME_PASSWORD)
 {
-	if (cs->status != STATUS_AUTH_GAME) {
-		return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
+	if (this->status != STATUS_AUTH_GAME) {
+		return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_NOT_EXPECTED);
 	}
 
 	char password[NETWORK_PASSWORD_LENGTH];
@@ -795,22 +795,22 @@
 	if (!StrEmpty(_settings_client.network.server_password) &&
 			strcmp(password, _settings_client.network.server_password) != 0) {
 		/* Password is invalid */
-		return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_WRONG_PASSWORD);
+		return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_WRONG_PASSWORD);
 	}
 
-	const NetworkClientInfo *ci = cs->GetInfo();
+	const NetworkClientInfo *ci = this->GetInfo();
 	if (Company::IsValidID(ci->client_playas) && !StrEmpty(_network_company_states[ci->client_playas].password)) {
-		return SEND_COMMAND(PACKET_SERVER_NEED_COMPANY_PASSWORD)(cs);
+		return SEND_COMMAND(PACKET_SERVER_NEED_COMPANY_PASSWORD)(this);
 	}
 
 	/* Valid password, allow user */
-	return SEND_COMMAND(PACKET_SERVER_WELCOME)(cs);
+	return SEND_COMMAND(PACKET_SERVER_WELCOME)(this);
 }
 
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_PASSWORD)
+DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_COMPANY_PASSWORD)
 {
-	if (cs->status != STATUS_AUTH_COMPANY) {
-		return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
+	if (this->status != STATUS_AUTH_COMPANY) {
+		return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_NOT_EXPECTED);
 	}
 
 	char password[NETWORK_PASSWORD_LENGTH];
@@ -819,17 +819,17 @@
 	/* Check company password. Allow joining if we cleared the password meanwhile.
 	 * Also, check the company is still valid - client could be moved to spectators
 	 * in the middle of the authorization process */
-	CompanyID playas = cs->GetInfo()->client_playas;
+	CompanyID playas = this->GetInfo()->client_playas;
 	if (Company::IsValidID(playas) && !StrEmpty(_network_company_states[playas].password) &&
 			strcmp(password, _network_company_states[playas].password) != 0) {
 		/* Password is invalid */
-		return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_WRONG_PASSWORD);
+		return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_WRONG_PASSWORD);
 	}
 
-	return SEND_COMMAND(PACKET_SERVER_WELCOME)(cs);
+	return SEND_COMMAND(PACKET_SERVER_WELCOME)(this);
 }
 
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_GETMAP)
+DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_GETMAP)
 {
 	NetworkClientSocket *new_cs;
 
@@ -844,112 +844,111 @@
 		if (_openttd_newgrf_version != p->Recv_uint32()) {
 			/* The version we get from the client differs, it must have the
 			 * wrong version. The client must be wrong. */
-			return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
+			return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_NOT_EXPECTED);
 		}
 	} else if (p->size != 3) {
 		/* We received a packet from a version that claims to be stable.
 		 * That shouldn't happen. The client must be wrong. */
-		return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
+		return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_NOT_EXPECTED);
 	}
 
 	/* The client was never joined.. so this is impossible, right?
 	 *  Ignore the packet, give the client a warning, and close his connection */
-	if (cs->status < STATUS_AUTHORIZED || cs->HasClientQuit()) {
-		return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED);
+	if (this->status < STATUS_AUTHORIZED || this->HasClientQuit()) {
+		return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_NOT_AUTHORIZED);
 	}
 
 	/* Check if someone else is receiving the map */
 	FOR_ALL_CLIENT_SOCKETS(new_cs) {
 		if (new_cs->status == STATUS_MAP) {
 			/* Tell the new client to wait */
-			cs->status = STATUS_MAP_WAIT;
-			return SEND_COMMAND(PACKET_SERVER_WAIT)(cs);
+			this->status = STATUS_MAP_WAIT;
+			return SEND_COMMAND(PACKET_SERVER_WAIT)(this);
 		}
 	}
 
 	/* We receive a request to upload the map.. give it to the client! */
-	return SEND_COMMAND(PACKET_SERVER_MAP)(cs);
+	return SEND_COMMAND(PACKET_SERVER_MAP)(this);
 }
 
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_MAP_OK)
+DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_MAP_OK)
 {
 	/* Client has the map, now start syncing */
-	if (cs->status == STATUS_DONE_MAP && !cs->HasClientQuit()) {
+	if (this->status == STATUS_DONE_MAP && !this->HasClientQuit()) {
 		char client_name[NETWORK_CLIENT_NAME_LENGTH];
 		NetworkClientSocket *new_cs;
 
-		NetworkGetClientName(client_name, sizeof(client_name), cs);
+		NetworkGetClientName(client_name, sizeof(client_name), this);
 
-		NetworkTextMessage(NETWORK_ACTION_JOIN, CC_DEFAULT, false, client_name, NULL, cs->client_id);
+		NetworkTextMessage(NETWORK_ACTION_JOIN, CC_DEFAULT, false, client_name, NULL, this->client_id);
 
 		/* Mark the client as pre-active, and wait for an ACK
 		 *  so we know he is done loading and in sync with us */
-		cs->status = STATUS_PRE_ACTIVE;
-		NetworkHandleCommandQueue(cs);
-		SEND_COMMAND(PACKET_SERVER_FRAME)(cs);
-		SEND_COMMAND(PACKET_SERVER_SYNC)(cs);
+		this->status = STATUS_PRE_ACTIVE;
+		NetworkHandleCommandQueue(this);
+		SEND_COMMAND(PACKET_SERVER_FRAME)(this);
+		SEND_COMMAND(PACKET_SERVER_SYNC)(this);
 
 		/* This is the frame the client receives
 		 *  we need it later on to make sure the client is not too slow */
-		cs->last_frame = _frame_counter;
-		cs->last_frame_server = _frame_counter;
+		this->last_frame = _frame_counter;
+		this->last_frame_server = _frame_counter;
 
 		FOR_ALL_CLIENT_SOCKETS(new_cs) {
 			if (new_cs->status > STATUS_AUTHORIZED) {
-				SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(new_cs, cs->GetInfo());
-				SEND_COMMAND(PACKET_SERVER_JOIN)(new_cs, cs->client_id);
+				SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(new_cs, this->GetInfo());
+				SEND_COMMAND(PACKET_SERVER_JOIN)(new_cs, this->client_id);
 			}
 		}
 
 		/* also update the new client with our max values */
-		SEND_COMMAND(PACKET_SERVER_CONFIG_UPDATE)(cs);
+		SEND_COMMAND(PACKET_SERVER_CONFIG_UPDATE)(this);
 
 		/* quickly update the syncing client with company details */
-		return SEND_COMMAND(PACKET_SERVER_COMPANY_UPDATE)(cs);
+		return SEND_COMMAND(PACKET_SERVER_COMPANY_UPDATE)(this);
 	}
 
 	/* Wrong status for this packet, give a warning to client, and close connection */
-	return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
+	return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_NOT_EXPECTED);
 }
 
 /**
  * The client has done a command and wants us to handle it
- * @param *cs the connected client that has sent the command
- * @param *p the packet in which the command was sent
+ * @param p the packet in which the command was sent
  */
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND)
+DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_COMMAND)
 {
 	/* The client was never joined.. so this is impossible, right?
 	 *  Ignore the packet, give the client a warning, and close his connection */
-	if (cs->status < STATUS_DONE_MAP || cs->HasClientQuit()) {
-		return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
+	if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) {
+		return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_NOT_EXPECTED);
 	}
 
-	if (cs->incoming_queue.Count() >= _settings_client.network.max_commands_in_queue) {
-		return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_TOO_MANY_COMMANDS);
+	if (this->incoming_queue.Count() >= _settings_client.network.max_commands_in_queue) {
+		return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_TOO_MANY_COMMANDS);
 	}
 
 	CommandPacket cp;
-	const char *err = cs->Recv_Command(p, &cp);
+	const char *err = this->Recv_Command(p, &cp);
 
-	if (cs->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
+	if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
 
-	NetworkClientInfo *ci = cs->GetInfo();
+	NetworkClientInfo *ci = this->GetInfo();
 
 	if (err != NULL) {
 		IConsolePrintF(CC_ERROR, "WARNING: %s from client %d (IP: %s).", err, ci->client_id, GetClientIP(ci));
-		return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
+		return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_NOT_EXPECTED);
 	}
 
 
 	if ((GetCommandFlags(cp.cmd) & CMD_SERVER) && ci->client_id != CLIENT_ID_SERVER) {
 		IConsolePrintF(CC_ERROR, "WARNING: server only command from: client %d (IP: %s), kicking...", ci->client_id, GetClientIP(ci));
-		return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_KICKED);
+		return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_KICKED);
 	}
 
 	if ((GetCommandFlags(cp.cmd) & CMD_SPECTATOR) == 0 && !Company::IsValidID(cp.company) && ci->client_id != CLIENT_ID_SERVER) {
 		IConsolePrintF(CC_ERROR, "WARNING: spectator issueing command from client %d (IP: %s), kicking...", ci->client_id, GetClientIP(ci));
-		return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_KICKED);
+		return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_KICKED);
 	}
 
 	/**
@@ -960,12 +959,12 @@
 	if (!(cp.cmd == CMD_COMPANY_CTRL && cp.p1 == 0 && ci->client_playas == COMPANY_NEW_COMPANY) && ci->client_playas != cp.company) {
 		IConsolePrintF(CC_ERROR, "WARNING: client %d (IP: %s) tried to execute a command as company %d, kicking...",
 		               ci->client_playas + 1, GetClientIP(ci), cp.company + 1);
-		return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_COMPANY_MISMATCH);
+		return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_COMPANY_MISMATCH);
 	}
 
 	if (cp.cmd == CMD_COMPANY_CTRL) {
 		if (cp.p1 != 0 || cp.company != COMPANY_SPECTATOR) {
-			return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_CHEATER);
+			return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_CHEATER);
 		}
 
 		/* Check if we are full - else it's possible for spectators to send a CMD_COMPANY_CTRL and the company is created regardless of max_companies! */
@@ -975,13 +974,13 @@
 		}
 	}
 
-	if (GetCommandFlags(cp.cmd) & CMD_CLIENT_ID) cp.p2 = cs->client_id;
+	if (GetCommandFlags(cp.cmd) & CMD_CLIENT_ID) cp.p2 = this->client_id;
 
-	cs->incoming_queue.Append(&cp);
+	this->incoming_queue.Append(&cp);
 	return NETWORK_RECV_STATUS_OKAY;
 }
 
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_ERROR)
+DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_ERROR)
 {
 	/* This packets means a client noticed an error and is reporting this
 	 *  to us. Display the error and report it to the other clients */
@@ -991,12 +990,12 @@
 	NetworkErrorCode errorno = (NetworkErrorCode)p->Recv_uint8();
 
 	/* The client was never joined.. thank the client for the packet, but ignore it */
-	if (cs->status < STATUS_DONE_MAP || cs->HasClientQuit()) {
-		cs->CloseConnection();
+	if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) {
+		this->CloseConnection();
 		return NETWORK_RECV_STATUS_CONN_LOST;
 	}
 
-	NetworkGetClientName(client_name, sizeof(client_name), cs);
+	NetworkGetClientName(client_name, sizeof(client_name), this);
 
 	StringID strid = GetNetworkErrorMsg(errorno);
 	GetString(str, strid, lastof(str));
@@ -1007,15 +1006,15 @@
 
 	FOR_ALL_CLIENT_SOCKETS(new_cs) {
 		if (new_cs->status > STATUS_AUTHORIZED) {
-			SEND_COMMAND(PACKET_SERVER_ERROR_QUIT)(new_cs, cs->client_id, errorno);
+			SEND_COMMAND(PACKET_SERVER_ERROR_QUIT)(new_cs, this->client_id, errorno);
 		}
 	}
 
-	cs->CloseConnection(false);
+	this->CloseConnection(false);
 	return NETWORK_RECV_STATUS_CONN_LOST;
 }
 
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_QUIT)
+DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_QUIT)
 {
 	/* The client wants to leave. Display this and report it to the other
 	 *  clients. */
@@ -1023,50 +1022,50 @@
 	char client_name[NETWORK_CLIENT_NAME_LENGTH];
 
 	/* The client was never joined.. thank the client for the packet, but ignore it */
-	if (cs->status < STATUS_DONE_MAP || cs->HasClientQuit()) {
-		cs->CloseConnection();
+	if (this->status < STATUS_DONE_MAP || this->HasClientQuit()) {
+		this->CloseConnection();
 		return NETWORK_RECV_STATUS_CONN_LOST;
 	}
 
-	NetworkGetClientName(client_name, sizeof(client_name), cs);
+	NetworkGetClientName(client_name, sizeof(client_name), this);
 
 	NetworkTextMessage(NETWORK_ACTION_LEAVE, CC_DEFAULT, false, client_name, NULL, STR_NETWORK_MESSAGE_CLIENT_LEAVING);
 
 	FOR_ALL_CLIENT_SOCKETS(new_cs) {
 		if (new_cs->status > STATUS_AUTHORIZED) {
-			SEND_COMMAND(PACKET_SERVER_QUIT)(new_cs, cs->client_id);
+			SEND_COMMAND(PACKET_SERVER_QUIT)(new_cs, this->client_id);
 		}
 	}
 
-	cs->CloseConnection(false);
+	this->CloseConnection(false);
 	return NETWORK_RECV_STATUS_CONN_LOST;
 }
 
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_ACK)
+DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_ACK)
 {
-	if (cs->status < STATUS_AUTHORIZED) {
+	if (this->status < STATUS_AUTHORIZED) {
 		/* Illegal call, return error and ignore the packet */
-		return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED);
+		return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_NOT_AUTHORIZED);
 	}
 
 	uint32 frame = p->Recv_uint32();
 
 	/* The client is trying to catch up with the server */
-	if (cs->status == STATUS_PRE_ACTIVE) {
+	if (this->status == STATUS_PRE_ACTIVE) {
 		/* The client is not yet catched up? */
 		if (frame + DAY_TICKS < _frame_counter) return NETWORK_RECV_STATUS_OKAY;
 
 		/* Now he is! Unpause the game */
-		cs->status = STATUS_ACTIVE;
+		this->status = STATUS_ACTIVE;
 
 		/* Execute script for, e.g. MOTD */
 		IConsoleCmdExec("exec scripts/on_server_connect.scr 0");
 	}
 
 	/* The client received the frame, make note of it */
-	cs->last_frame = frame;
+	this->last_frame = frame;
 	/* With those 2 values we can calculate the lag realtime */
-	cs->last_frame_server = _frame_counter;
+	this->last_frame_server = _frame_counter;
 	return NETWORK_RECV_STATUS_OKAY;
 }
 
@@ -1172,11 +1171,11 @@
 	}
 }
 
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_CHAT)
+DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_CHAT)
 {
-	if (cs->status < STATUS_AUTHORIZED) {
+	if (this->status < STATUS_AUTHORIZED) {
 		/* Illegal call, return error and ignore the packet */
-		return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED);
+		return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_NOT_AUTHORIZED);
 	}
 
 	NetworkAction action = (NetworkAction)p->Recv_uint8();
@@ -1187,7 +1186,7 @@
 	p->Recv_string(msg, NETWORK_CHAT_LENGTH);
 	int64 data = p->Recv_uint64();
 
-	NetworkClientInfo *ci = cs->GetInfo();
+	NetworkClientInfo *ci = this->GetInfo();
 	switch (action) {
 		case NETWORK_ACTION_GIVE_MONEY:
 			if (!Company::IsValidID(ci->client_playas)) break;
@@ -1195,28 +1194,28 @@
 		case NETWORK_ACTION_CHAT:
 		case NETWORK_ACTION_CHAT_CLIENT:
 		case NETWORK_ACTION_CHAT_COMPANY:
-			NetworkServerSendChat(action, desttype, dest, msg, cs->client_id, data);
+			NetworkServerSendChat(action, desttype, dest, msg, this->client_id, data);
 			break;
 		default:
 			IConsolePrintF(CC_ERROR, "WARNING: invalid chat action from client %d (IP: %s).", ci->client_id, GetClientIP(ci));
-			return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
+			return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_NOT_EXPECTED);
 			break;
 	}
 	return NETWORK_RECV_STATUS_OKAY;
 }
 
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_SET_PASSWORD)
+DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_SET_PASSWORD)
 {
-	if (cs->status != STATUS_ACTIVE) {
+	if (this->status != STATUS_ACTIVE) {
 		/* Illegal call, return error and ignore the packet */
-		return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
+		return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_NOT_EXPECTED);
 	}
 
 	char password[NETWORK_PASSWORD_LENGTH];
 	const NetworkClientInfo *ci;
 
 	p->Recv_string(password, sizeof(password));
-	ci = cs->GetInfo();
+	ci = this->GetInfo();
 
 	if (Company::IsValidID(ci->client_playas)) {
 		strecpy(_network_company_states[ci->client_playas].password, password, lastof(_network_company_states[ci->client_playas].password));
@@ -1225,20 +1224,20 @@
 	return NETWORK_RECV_STATUS_OKAY;
 }
 
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_SET_NAME)
+DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_SET_NAME)
 {
-	if (cs->status != STATUS_ACTIVE) {
+	if (this->status != STATUS_ACTIVE) {
 		/* Illegal call, return error and ignore the packet */
-		return SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
+		return SEND_COMMAND(PACKET_SERVER_ERROR)(this, NETWORK_ERROR_NOT_EXPECTED);
 	}
 
 	char client_name[NETWORK_CLIENT_NAME_LENGTH];
 	NetworkClientInfo *ci;
 
 	p->Recv_string(client_name, sizeof(client_name));
-	ci = cs->GetInfo();
+	ci = this->GetInfo();
 
-	if (cs->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
+	if (this->HasClientQuit()) return NETWORK_RECV_STATUS_CONN_LOST;
 
 	if (ci != NULL) {
 		/* Display change */
@@ -1251,7 +1250,7 @@
 	return NETWORK_RECV_STATUS_OKAY;
 }
 
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_RCON)
+DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_RCON)
 {
 	char pass[NETWORK_PASSWORD_LENGTH];
 	char command[NETWORK_RCONCOMMAND_LENGTH];
@@ -1262,19 +1261,19 @@
 	p->Recv_string(command, sizeof(command));
 
 	if (strcmp(pass, _settings_client.network.rcon_password) != 0) {
-		DEBUG(net, 0, "[rcon] wrong password from client-id %d", cs->client_id);
+		DEBUG(net, 0, "[rcon] wrong password from client-id %d", this->client_id);
 		return NETWORK_RECV_STATUS_OKAY;
 	}
 
-	DEBUG(net, 0, "[rcon] client-id %d executed: '%s'", cs->client_id, command);
+	DEBUG(net, 0, "[rcon] client-id %d executed: '%s'", this->client_id, command);
 
-	_redirect_console_to_client = cs->client_id;
+	_redirect_console_to_client = this->client_id;
 	IConsoleCmdExec(command);
 	_redirect_console_to_client = INVALID_CLIENT_ID;
 	return NETWORK_RECV_STATUS_OKAY;
 }
 
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_MOVE)
+DEF_GAME_RECEIVE_COMMAND(Server, PACKET_CLIENT_MOVE)
 {
 	CompanyID company_id = (Owner)p->Recv_uint8();
 
@@ -1289,70 +1288,16 @@
 
 		/* Incorrect password sent, return! */
 		if (strcmp(password, _network_company_states[company_id].password) != 0) {
-			DEBUG(net, 2, "[move] wrong password from client-id #%d for company #%d", cs->client_id, company_id + 1);
+			DEBUG(net, 2, "[move] wrong password from client-id #%d for company #%d", this->client_id, company_id + 1);
 			return NETWORK_RECV_STATUS_OKAY;
 		}
 	}
 
 	/* if we get here we can move the client */
-	NetworkServerDoMove(cs->client_id, company_id);
+	NetworkServerDoMove(this->client_id, company_id);
 	return NETWORK_RECV_STATUS_OKAY;
 }
 
-/* The layout for the receive-functions by the server */
-typedef NetworkRecvStatus NetworkServerPacket(NetworkClientSocket *cs, Packet *p);
-
-
-/* This array matches PacketType. At an incoming
- *  packet it is matches against this array
- *  and that way the right function to handle that
- *  packet is found. */
-static NetworkServerPacket * const _network_server_packet[] = {
-	NULL, // PACKET_SERVER_FULL,
-	NULL, // PACKET_SERVER_BANNED,
-	RECEIVE_COMMAND(PACKET_CLIENT_JOIN),
-	NULL, // PACKET_SERVER_ERROR,
-	RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_INFO),
-	NULL, // PACKET_SERVER_COMPANY_INFO,
-	NULL, // PACKET_SERVER_CLIENT_INFO,
-	NULL, // PACKET_SERVER_NEED_GAME_PASSWORD,
-	NULL, // PACKET_SERVER_NEED_COMPANY_PASSWORD,
-	RECEIVE_COMMAND(PACKET_CLIENT_GAME_PASSWORD),
-	RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_PASSWORD),
-	NULL, // PACKET_SERVER_WELCOME,
-	RECEIVE_COMMAND(PACKET_CLIENT_GETMAP),
-	NULL, // PACKET_SERVER_WAIT,
-	NULL, // PACKET_SERVER_MAP,
-	RECEIVE_COMMAND(PACKET_CLIENT_MAP_OK),
-	NULL, // PACKET_SERVER_JOIN,
-	NULL, // PACKET_SERVER_FRAME,
-	NULL, // PACKET_SERVER_SYNC,
-	RECEIVE_COMMAND(PACKET_CLIENT_ACK),
-	RECEIVE_COMMAND(PACKET_CLIENT_COMMAND),
-	NULL, // PACKET_SERVER_COMMAND,
-	RECEIVE_COMMAND(PACKET_CLIENT_CHAT),
-	NULL, // PACKET_SERVER_CHAT,
-	RECEIVE_COMMAND(PACKET_CLIENT_SET_PASSWORD),
-	RECEIVE_COMMAND(PACKET_CLIENT_SET_NAME),
-	RECEIVE_COMMAND(PACKET_CLIENT_QUIT),
-	RECEIVE_COMMAND(PACKET_CLIENT_ERROR),
-	NULL, // PACKET_SERVER_QUIT,
-	NULL, // PACKET_SERVER_ERROR_QUIT,
-	NULL, // PACKET_SERVER_SHUTDOWN,
-	NULL, // PACKET_SERVER_NEWGAME,
-	NULL, // PACKET_SERVER_RCON,
-	RECEIVE_COMMAND(PACKET_CLIENT_RCON),
-	NULL, // PACKET_CLIENT_CHECK_NEWGRFS,
-	RECEIVE_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED),
-	NULL, // PACKET_SERVER_MOVE,
-	RECEIVE_COMMAND(PACKET_CLIENT_MOVE),
-	NULL, // PACKET_SERVER_COMPANY_UPDATE,
-	NULL, // PACKET_SERVER_CONFIG_UPDATE,
-};
-
-/* If this fails, check the array above with network_data.h */
-assert_compile(lengthof(_network_server_packet) == PACKET_END);
-
 void NetworkSocketHandler::Send_CompanyInformation(Packet *p, const Company *c, const NetworkCompanyStats *stats)
 {
 	/* Grab the company name */
@@ -1597,26 +1542,6 @@
 	return true;
 }
 
-/* Reads a packet from the stream */
-void NetworkServer_ReadPackets(NetworkClientSocket *cs)
-{
-	Packet *p;
-	NetworkRecvStatus res = NETWORK_RECV_STATUS_OKAY;
-
-	while (res == NETWORK_RECV_STATUS_OKAY && (p = cs->Recv_Packet()) != NULL) {
-		byte type = p->Recv_uint8();
-		if (type < PACKET_END && _network_server_packet[type] != NULL && !cs->HasClientQuit()) {
-			res = _network_server_packet[type](cs, p);
-		} else {
-			cs->CloseConnection();
-			res = NETWORK_RECV_STATUS_MALFORMED_PACKET;
-			DEBUG(net, 0, "[server] received invalid packet type %d", type);
-		}
-
-		delete p;
-	}
-}
-
 /* Handle the local command-queue */
 static void NetworkHandleCommandQueue(NetworkClientSocket *cs)
 {
--- a/src/network/network_server.h
+++ b/src/network/network_server.h
@@ -18,6 +18,23 @@
 
 /** Class for handling the server side of the game connection. */
 class ServerNetworkGameSocketHandler : public NetworkGameSocketHandler {
+protected:
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_JOIN);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_INFO);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_GAME_PASSWORD);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_PASSWORD);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_GETMAP);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_MAP_OK);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_ACK);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_CHAT);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_SET_PASSWORD);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_SET_NAME);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_QUIT);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_ERROR);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_RCON);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_NEWGRFS_CHECKED);
+	DECLARE_GAME_RECEIVE_COMMAND(PACKET_CLIENT_MOVE);
 public:
 	ServerNetworkGameSocketHandler(SOCKET s);
 	~ServerNetworkGameSocketHandler();