about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/engine/e_network.c34
-rw-r--r--src/engine/server/es_server.c45
-rw-r--r--src/game/server/entities/character.cpp3
-rw-r--r--src/game/server/entities/character.hpp13
-rw-r--r--src/game/server/entity.hpp46
-rw-r--r--src/game/server/gamecontext.cpp15
-rw-r--r--src/game/server/gamecontext.hpp1
-rw-r--r--src/game/server/hooks.cpp2
-rw-r--r--src/game/server/player.cpp10
-rw-r--r--src/game/server/player.hpp3
10 files changed, 112 insertions, 60 deletions
diff --git a/src/engine/e_network.c b/src/engine/e_network.c
index ed9f3405..85a9117c 100644
--- a/src/engine/e_network.c
+++ b/src/engine/e_network.c
@@ -47,6 +47,7 @@ enum
 	NET_PACKETFLAG_CONTROL=1,
 	NET_PACKETFLAG_CONNLESS=2,
 	NET_PACKETFLAG_RESEND=4,
+	NET_PACKETFLAG_COMPRESSION=8,
 
 	NET_CHUNKFLAG_VITAL=1,
 	NET_CHUNKFLAG_RESEND=2,
@@ -234,24 +235,41 @@ static void send_packet_connless(NETSOCKET socket, NETADDR *addr, const void *da
 static void send_packet(NETSOCKET socket, NETADDR *addr, NETPACKETCONSTRUCT *packet)
 {
 	unsigned char buffer[NET_MAX_PACKETSIZE];
-	buffer[0] = ((packet->flags<<4)&0xf0)|((packet->ack>>8)&0xf);
-	buffer[1] = packet->ack&0xff;
-	buffer[2] = packet->num_chunks;
+	int compressed_size = -1;
+	int final_size = -1;
+	
+	/* log the data */
 	if(datalog)
 	{
 		io_write(datalog, &packet->data_size, sizeof(packet->data_size));
 		io_write(datalog, &packet->chunk_data, packet->data_size);
 	}
 	
+	/* compress if its enabled */
 	if(COMPRESSION)
+		compressed_size = huffman_compress(&huffmanstate, packet->chunk_data, packet->data_size, &buffer[3], NET_MAX_PACKETSIZE-4);
+
+	/* check if the compression was enabled, successful and good enough	*/
+	if(compressed_size > 0 && compressed_size < packet->data_size)
 	{
-		int compressed_size = huffman_compress(&huffmanstate, packet->chunk_data, packet->data_size, &buffer[3], NET_MAX_PACKETSIZE-4);
-		net_udp_send(socket, addr, buffer, NET_PACKETHEADERSIZE+compressed_size);
+		final_size = compressed_size;
+		packet->flags |= NET_PACKETFLAG_COMPRESSION;
 	}
 	else
 	{
+		/* use uncompressed data */
+		final_size = packet->data_size;
 		mem_copy(&buffer[3], packet->chunk_data, packet->data_size);
-		net_udp_send(socket, addr, buffer, NET_PACKETHEADERSIZE+packet->data_size);
+		packet->flags &= ~NET_PACKETFLAG_COMPRESSION;
+	}
+
+	/* set header and send the packet if all things are good */
+	if(final_size >= 0)
+	{
+		buffer[0] = ((packet->flags<<4)&0xf0)|((packet->ack>>8)&0xf);
+		buffer[1] = packet->ack&0xff;
+		buffer[2] = packet->num_chunks;
+		net_udp_send(socket, addr, buffer, NET_PACKETHEADERSIZE+final_size);
 	}
 }
 
@@ -261,7 +279,7 @@ static int unpack_packet(unsigned char *buffer, int size, NETPACKETCONSTRUCT *pa
 	/* check the size */
 	if(size < NET_PACKETHEADERSIZE || size > NET_MAX_PACKETSIZE)
 	{
-		dbg_msg("", "packet too small");
+		dbg_msg("", "packet too small, %d", size);
 		return -1;
 	}
 	
@@ -281,7 +299,7 @@ static int unpack_packet(unsigned char *buffer, int size, NETPACKETCONSTRUCT *pa
 	}
 	else
 	{
-		if(COMPRESSION)
+		if(packet->flags&NET_PACKETFLAG_COMPRESSION)
 			huffman_decompress(&huffmanstate, &buffer[3], packet->data_size, packet->chunk_data, sizeof(packet->chunk_data));
 		else
 			mem_copy(packet->chunk_data, &buffer[3], packet->data_size);
diff --git a/src/engine/server/es_server.c b/src/engine/server/es_server.c
index a3c8327f..6cdf835f 100644
--- a/src/engine/server/es_server.c
+++ b/src/engine/server/es_server.c
@@ -38,8 +38,6 @@ static int browseinfo_progression = -1;
 static int64 lastheartbeat;
 /*static NETADDR4 master_server;*/
 
-
-
 static char current_map[64];
 static int current_map_crc;
 static unsigned char *current_map_data = 0;
@@ -521,40 +519,40 @@ static void server_do_snap()
 }
 
 
-static int new_client_callback(int cid, void *user)
+static void reset_client(int cid)
 {
-	int i;
-	clients[cid].state = SRVCLIENT_STATE_CONNECTING;
-	clients[cid].name[0] = 0;
-	clients[cid].clan[0] = 0;
-	
 	/* reset input */
+	int i;
 	for(i = 0; i < 200; i++)
 	{
 		clients[cid].inputs[i].game_tick = -1;
 		clients[cid].inputs[i].pred_tick = -1;
 	}
 	clients[cid].current_input = 0;
-	
 	mem_zero(&clients[cid].latestinput, sizeof(clients[cid].latestinput));
-	
+
 	snapstorage_purge_all(&clients[cid].snapshots);
 	clients[cid].last_acked_snapshot = -1;
 	clients[cid].snap_rate = SRVCLIENT_SNAPRATE_INIT;
 	clients[cid].score = 0;
 	clients[cid].authed = 0;
+}
+
+static int new_client_callback(int cid, void *user)
+{
+	clients[cid].state = SRVCLIENT_STATE_CONNECTING;
+	clients[cid].name[0] = 0;
+	clients[cid].clan[0] = 0;
+	reset_client(cid);
 	return 0;
 }
 
 static int del_client_callback(int cid, void *user)
 {
 	/* notify the mod about the drop */
-	if(clients[cid].state == SRVCLIENT_STATE_READY ||
-		clients[cid].state == SRVCLIENT_STATE_INGAME)
-	{
+	if(clients[cid].state >= SRVCLIENT_STATE_READY)
 		mods_client_drop(cid);
-	}
-
+	
 	clients[cid].state = SRVCLIENT_STATE_EMPTY;
 	clients[cid].name[0] = 0;
 	clients[cid].clan[0] = 0;
@@ -682,7 +680,7 @@ static void server_process_client_packet(NETCHUNK *packet)
 			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();
@@ -690,7 +688,7 @@ static void server_process_client_packet(NETCHUNK *packet)
 			/* 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;
 				
@@ -715,7 +713,8 @@ static void server_process_client_packet(NETCHUNK *packet)
 			clients[cid].current_input %= 200;
 		
 			/* call the mod with the fresh input data */
-			mods_client_direct_input(cid, clients[cid].latestinput.data);
+			if(clients[cid].state == SRVCLIENT_STATE_INGAME)
+				mods_client_direct_input(cid, clients[cid].latestinput.data);
 		}
 		else if(msg == NETMSG_RCON_CMD)
 		{
@@ -784,7 +783,8 @@ static void server_process_client_packet(NETCHUNK *packet)
 	else
 	{
 		/* game message */
-		mods_message(msg, cid);
+		if(clients[cid].state >= SRVCLIENT_STATE_READY)
+			mods_message(msg, cid);
 	}
 }
 
@@ -992,10 +992,8 @@ static int server_run()
 							continue;
 						
 						server_send_map(c);
+						reset_client(c);
 						clients[c].state = SRVCLIENT_STATE_CONNECTING;
-						clients[c].last_acked_snapshot = -1;
-						clients[c].snap_rate = SRVCLIENT_SNAPRATE_RECOVER;
-						snapstorage_purge_all(&clients[c].snapshots);
 					}
 					
 					game_start_time = time_get();
@@ -1029,7 +1027,8 @@ static int server_run()
 						{
 							if(clients[c].inputs[i].game_tick == server_tick())
 							{
-								mods_client_predicted_input(c, clients[c].inputs[i].data);
+								if(clients[c].state == SRVCLIENT_STATE_INGAME)
+									mods_client_predicted_input(c, clients[c].inputs[i].data);
 								break;
 							}
 						}
diff --git a/src/game/server/entities/character.cpp b/src/game/server/entities/character.cpp
index 60acdca8..e79962c2 100644
--- a/src/game/server/entities/character.cpp
+++ b/src/game/server/entities/character.cpp
@@ -32,6 +32,9 @@ static INPUT_COUNT count_input(int prev, int cur)
 	return c;
 }
 
+
+MACRO_ALLOC_POOL_ID_IMPL(CHARACTER, MAX_CLIENTS)
+
 // player
 CHARACTER::CHARACTER()
 : ENTITY(NETOBJTYPE_CHARACTER)
diff --git a/src/game/server/entities/character.hpp b/src/game/server/entities/character.hpp
index 9bd441ba..c25b4b5f 100644
--- a/src/game/server/entities/character.hpp
+++ b/src/game/server/entities/character.hpp
@@ -11,19 +11,8 @@
 
 class CHARACTER : public ENTITY
 {
-	/*static CHARACTER pool_data[MAX_CLIENTS];
-	static int pool_used[MAX_CLIENTS];*/
+	MACRO_ALLOC_POOL_ID()
 public:
-/*
-	void operator delete(void *character)
-	{
-		(CHARACTER *)character 
-		int id = (CHARACTER *)character - (CHARACTER *)pool_data;
-		dbg_assert(pool_used[id], "");
-		pool_used[id] = 0;
-		mem_zero(&pool_data[id], sizeof(CHARACTER));
-	}*/
-
 	// player controlling this character
 	class PLAYER *player;
 	
diff --git a/src/game/server/entity.hpp b/src/game/server/entity.hpp
index d3ae3a1c..8ccb2d9a 100644
--- a/src/game/server/entity.hpp
+++ b/src/game/server/entity.hpp
@@ -1,14 +1,59 @@
 #ifndef GAME_SERVER_ENTITY_H
 #define GAME_SERVER_ENTITY_H
 
+#include <new>
 #include <base/vmath.hpp>
 
+#define MACRO_ALLOC_HEAP() \
+	public: \
+	void *operator new(size_t size) \
+	{ \
+		void *p = mem_alloc(size, 1); \
+		/*dbg_msg("", "++ %p %d", p, size);*/ \
+		mem_zero(p, size); \
+		return p; \
+	} \
+	void operator delete(void *p) \
+	{ \
+		/*dbg_msg("", "-- %p", p);*/ \
+		mem_free(p); \
+	} \
+	private:
+
+#define MACRO_ALLOC_POOL_ID() \
+	public: \
+	void *operator new(size_t size, int id); \
+	void operator delete(void *p); \
+	private:
+	
+#define MACRO_ALLOC_POOL_ID_IMPL(POOLTYPE, poolsize) \
+	static char pool_data_##POOLTYPE[poolsize][sizeof(POOLTYPE)] = {{0}}; \
+	static int pool_used_##POOLTYPE[poolsize] = {0}; \
+	void *POOLTYPE::operator new(size_t size, int id) \
+	{ \
+		dbg_assert(sizeof(POOLTYPE) == size, "size error"); \
+		dbg_assert(!pool_used_##POOLTYPE[id], "already used"); \
+		/*dbg_msg("pool", "++ %s %d", #POOLTYPE, id);*/ \
+		pool_used_##POOLTYPE[id] = 1; \
+		mem_zero(pool_data_##POOLTYPE[id], size); \
+		return pool_data_##POOLTYPE[id]; \
+	} \
+	void POOLTYPE::operator delete(void *p) \
+	{ \
+		int id = (POOLTYPE*)p - (POOLTYPE*)pool_data_##POOLTYPE; \
+		dbg_assert(pool_used_##POOLTYPE[id], "not used"); \
+		/*dbg_msg("pool", "-- %s %d", #POOLTYPE, id);*/ \
+		pool_used_##POOLTYPE[id] = 0; \
+		mem_zero(pool_data_##POOLTYPE[id], sizeof(POOLTYPE)); \
+	}
+	
 /*
 	Class: Entity
 		Basic entity class.
 */
 class ENTITY
 {
+	MACRO_ALLOC_HEAP()
 private:
 	friend class GAMEWORLD; // thy these?
 	ENTITY *prev_entity;
@@ -21,7 +66,6 @@ protected:
 	int id;
 	int objtype;
 public:
-	
 	ENTITY(int objtype);
 	virtual ~ENTITY();
 	
diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp
index 7866e0f0..987ce64e 100644
--- a/src/game/server/gamecontext.cpp
+++ b/src/game/server/gamecontext.cpp
@@ -7,15 +7,13 @@ GAMECONTEXT game;
 GAMECONTEXT::GAMECONTEXT()
 {
 	for(int i = 0; i < MAX_CLIENTS; i++)
-	{
 		players[i] = 0;
-		/*players = new PLAYER();
-		players[i].init(-1);*/
-	}
 }
 
 GAMECONTEXT::~GAMECONTEXT()
 {
+	for(int i = 0; i < MAX_CLIENTS; i++)
+		delete players[i];
 }
 
 void GAMECONTEXT::clear()
@@ -23,15 +21,6 @@ void GAMECONTEXT::clear()
 	this->~GAMECONTEXT();
 	mem_zero(this, sizeof(*this));
 	new (this) GAMECONTEXT();
-	// reset all players
-	/*
-	for(int i = 0; i < MAX_CLIENTS; i++)
-		players[i].init(-1);
-	
-	world.~GAMEWORLD();
-	mem_zero(&world, sizeof(world));
-	world.GAMEWORLD();
-	*/
 }
 
 
diff --git a/src/game/server/gamecontext.hpp b/src/game/server/gamecontext.hpp
index 4c7079c8..dd10ec4d 100644
--- a/src/game/server/gamecontext.hpp
+++ b/src/game/server/gamecontext.hpp
@@ -27,7 +27,6 @@
 			All players (PLAYER::snap)
 
 */
-
 class GAMECONTEXT
 {
 public:
diff --git a/src/game/server/hooks.cpp b/src/game/server/hooks.cpp
index 0cd6d6e1..494f4f62 100644
--- a/src/game/server/hooks.cpp
+++ b/src/game/server/hooks.cpp
@@ -73,7 +73,7 @@ void mods_client_enter(int client_id)
 
 void mods_connected(int client_id)
 {
-	game.players[client_id] = new PLAYER(client_id);
+	game.players[client_id] = new(client_id) PLAYER(client_id);
 	//game.players[client_id].init(client_id);
 	//game.players[client_id].client_id = client_id;
 	
diff --git a/src/game/server/player.cpp b/src/game/server/player.cpp
index a31cf21c..252e23e3 100644
--- a/src/game/server/player.cpp
+++ b/src/game/server/player.cpp
@@ -5,12 +5,20 @@
 #include "player.hpp"
 #include "gamecontext.hpp"
 
+MACRO_ALLOC_POOL_ID_IMPL(PLAYER, MAX_CLIENTS)
+
 PLAYER::PLAYER(int client_id)
 {
 	character = 0;
 	this->client_id = client_id;
 }
 
+PLAYER::~PLAYER()
+{
+	delete character;
+	character = 0;
+}
+
 /*
 void PLAYER::init(int client_id)
 {
@@ -168,7 +176,7 @@ void PLAYER::try_respawn()
 	if(num_ents == 0)
 	{
 		spawning = false;
-		character = new CHARACTER();
+		character = new(client_id) CHARACTER();
 		character->spawn(this, spawnpos, team);
 	}
 }
diff --git a/src/game/server/player.hpp b/src/game/server/player.hpp
index 9836bffc..c92265a8 100644
--- a/src/game/server/player.hpp
+++ b/src/game/server/player.hpp
@@ -7,9 +7,12 @@
 // player object
 class PLAYER
 {
+	MACRO_ALLOC_POOL_ID()
+private:
 	CHARACTER *character;
 public:
 	PLAYER(int client_id);
+	~PLAYER();
 
 	// TODO: clean this up
 	char skin_name[64];