about summary refs log tree commit diff
path: root/src/game/server
diff options
context:
space:
mode:
authorMagnus Auvinen <magnus.auvinen@gmail.com>2008-09-23 18:08:19 +0000
committerMagnus Auvinen <magnus.auvinen@gmail.com>2008-09-23 18:08:19 +0000
commitd9d37b945ee5796553794ef33249c22490494391 (patch)
tree03c1c97c02732095316fdcbc46fdf777de2ab9b0 /src/game/server
parentc10ce4d17b4e21effecb28e0b43df2386ae1baaf (diff)
downloadzcatch-d9d37b945ee5796553794ef33249c22490494391.tar.gz
zcatch-d9d37b945ee5796553794ef33249c22490494391.zip
some server restructure. added hook no attach sound
Diffstat (limited to 'src/game/server')
-rw-r--r--src/game/server/entities/character.cpp15
-rw-r--r--src/game/server/entities/character.hpp12
-rw-r--r--src/game/server/entities/laser.cpp2
-rw-r--r--src/game/server/entities/projectile.cpp2
-rw-r--r--src/game/server/eventhandler.cpp2
-rw-r--r--src/game/server/gamecontext.cpp24
-rw-r--r--src/game/server/gamecontext.hpp2
-rw-r--r--src/game/server/gamecontroller.cpp52
-rw-r--r--src/game/server/gamemodes/ctf.cpp10
-rw-r--r--src/game/server/hooks.cpp30
-rw-r--r--src/game/server/player.cpp33
-rw-r--r--src/game/server/player.hpp5
12 files changed, 108 insertions, 81 deletions
diff --git a/src/game/server/entities/character.cpp b/src/game/server/entities/character.cpp
index 8f47fbe7..60acdca8 100644
--- a/src/game/server/entities/character.cpp
+++ b/src/game/server/entities/character.cpp
@@ -45,8 +45,11 @@ void CHARACTER::reset()
 
 bool CHARACTER::spawn(PLAYER *player, vec2 pos, int team)
 {
+	/*
+	~CHARACTER();
 	mem_zero(this, sizeof(CHARACTER));
-	new(this) CHARACTER();
+	new(this) CHARACTER();*/
+	
 	player_state = PLAYERSTATE_UNKNOWN;
 	emote_stop = -1;
 	last_action = -1;
@@ -657,7 +660,7 @@ void CHARACTER::tick_defered()
 		//if(events&COREEVENT_HOOK_LAUNCH) snd_play_random(CHN_WORLD, SOUND_HOOK_LOOP, 1.0f, pos);
 		if(events&COREEVENT_HOOK_ATTACH_PLAYER) game.create_sound(pos, SOUND_HOOK_ATTACH_PLAYER, cmask_all());
 		if(events&COREEVENT_HOOK_ATTACH_GROUND) game.create_sound(pos, SOUND_HOOK_ATTACH_GROUND, mask);
-		if(events&COREEVENT_HOOK_HIT_NOHOOK) game.create_sound(pos, SOUND_HOOK_LOOP, mask);
+		if(events&COREEVENT_HOOK_HIT_NOHOOK) game.create_sound(pos, SOUND_HOOK_NOATTACH, mask);
 		//if(events&COREEVENT_HOOK_RETRACT) snd_play_random(CHN_WORLD, SOUND_PLAYER_JUMP, 1.0f, pos);
 	//}
 	
@@ -705,7 +708,7 @@ void CHARACTER::die(int killer, int weapon)
 {
 	/*if (dead || team == -1)
 		return;*/
-	int mode_special = game.controller->on_character_death(this, &game.players[killer], weapon);
+	int mode_special = game.controller->on_character_death(this, game.players[killer], weapon);
 
 	dbg_msg("game", "kill killer='%d:%s' victim='%d:%s' weapon=%d special=%d",
 		killer, server_clientname(killer),
@@ -789,7 +792,7 @@ bool CHARACTER::take_damage(vec2 force, int dmg, int from, int weapon)
 
 	// do damage hit sound
 	if(from >= 0 && from != player->client_id)
-		game.create_sound(game.players[from].view_pos, SOUND_HIT, cmask_one(from));
+		game.create_sound(game.players[from]->view_pos, SOUND_HIT, cmask_one(from));
 
 	// check for death
 	if(health <= 0)
@@ -799,7 +802,7 @@ bool CHARACTER::take_damage(vec2 force, int dmg, int from, int weapon)
 		// set attacker's face to happy (taunt!)
 		if (from >= 0 && from != player->client_id)
 		{
-			CHARACTER *chr = &game.players[from].character;
+			CHARACTER *chr = game.players[from]->get_character();
 			chr->emote_type = EMOTE_HAPPY;
 			chr->emote_stop = server_tick() + server_tickspeed();
 		}
@@ -821,7 +824,7 @@ bool CHARACTER::take_damage(vec2 force, int dmg, int from, int weapon)
 
 void CHARACTER::snap(int snaping_client)
 {
-	if(distance(game.players[snaping_client].view_pos, pos) > 1000.0f)
+	if(distance(game.players[snaping_client]->view_pos, pos) > 1000.0f)
 		return;
 	
 	NETOBJ_CHARACTER *character = (NETOBJ_CHARACTER *)snap_new_item(NETOBJTYPE_CHARACTER, player->client_id, sizeof(NETOBJ_CHARACTER));
diff --git a/src/game/server/entities/character.hpp b/src/game/server/entities/character.hpp
index e9909c96..9bd441ba 100644
--- a/src/game/server/entities/character.hpp
+++ b/src/game/server/entities/character.hpp
@@ -11,7 +11,19 @@
 
 class CHARACTER : public ENTITY
 {
+	/*static CHARACTER pool_data[MAX_CLIENTS];
+	static int pool_used[MAX_CLIENTS];*/
 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/entities/laser.cpp b/src/game/server/entities/laser.cpp
index 226d52a9..4e9909ba 100644
--- a/src/game/server/entities/laser.cpp
+++ b/src/game/server/entities/laser.cpp
@@ -100,7 +100,7 @@ void LASER::tick()
 
 void LASER::snap(int snapping_client)
 {
-	if(distance(game.players[snapping_client].view_pos, pos) > 1000.0f)
+	if(distance(game.players[snapping_client]->view_pos, pos) > 1000.0f)
 		return;
 
 	NETOBJ_LASER *obj = (NETOBJ_LASER *)snap_new_item(NETOBJTYPE_LASER, id, sizeof(NETOBJ_LASER));
diff --git a/src/game/server/entities/projectile.cpp b/src/game/server/entities/projectile.cpp
index adcd8977..a2e10437 100644
--- a/src/game/server/entities/projectile.cpp
+++ b/src/game/server/entities/projectile.cpp
@@ -100,7 +100,7 @@ void PROJECTILE::snap(int snapping_client)
 {
 	float ct = (server_tick()-start_tick)/(float)server_tickspeed();
 	
-	if(distance(game.players[snapping_client].view_pos, get_pos(ct)) > 1000.0f)
+	if(distance(game.players[snapping_client]->view_pos, get_pos(ct)) > 1000.0f)
 		return;
 
 	NETOBJ_PROJECTILE *proj = (NETOBJ_PROJECTILE *)snap_new_item(NETOBJTYPE_PROJECTILE, id, sizeof(NETOBJ_PROJECTILE));
diff --git a/src/game/server/eventhandler.cpp b/src/game/server/eventhandler.cpp
index 8f50da1e..ce6a3b71 100644
--- a/src/game/server/eventhandler.cpp
+++ b/src/game/server/eventhandler.cpp
@@ -39,7 +39,7 @@ void EVENTHANDLER::snap(int snapping_client)
 		if(cmask_is_set(client_masks[i], snapping_client))
 		{
 			NETEVENT_COMMON *ev = (NETEVENT_COMMON *)&data[offsets[i]];
-			if(distance(game.players[snapping_client].view_pos, vec2(ev->x, ev->y)) < 1500.0f)
+			if(distance(game.players[snapping_client]->view_pos, vec2(ev->x, ev->y)) < 1500.0f)
 			{
 				void *d = snap_new_item(types[i], i, sizes[i]);
 				mem_copy(d, &data[offsets[i]], sizes[i]);
diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp
index 0f81167d..7866e0f0 100644
--- a/src/game/server/gamecontext.cpp
+++ b/src/game/server/gamecontext.cpp
@@ -7,7 +7,11 @@ GAMECONTEXT game;
 GAMECONTEXT::GAMECONTEXT()
 {
 	for(int i = 0; i < MAX_CLIENTS; i++)
-		players[i].init(-1);
+	{
+		players[i] = 0;
+		/*players = new PLAYER();
+		players[i].init(-1);*/
+	}
 }
 
 GAMECONTEXT::~GAMECONTEXT()
@@ -169,7 +173,7 @@ void GAMECONTEXT::send_chat(int chatter_cid, int team, const char *text)
 
 		for(int i = 0; i < MAX_CLIENTS; i++)
 		{
-			if(game.players[i].client_id != -1 && game.players[i].team == team)
+			if(game.players[i] && game.players[i]->team == team)
 				server_send_msg(i);
 		}
 	}
@@ -181,10 +185,10 @@ void GAMECONTEXT::send_info(int who, int to_who)
 	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.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);
@@ -228,8 +232,8 @@ void GAMECONTEXT::tick()
 		
 	for(int i = 0; i < MAX_CLIENTS; i++)
 	{
-		if(players[i].client_id != -1)
-			players[i].tick();
+		if(players[i])
+			players[i]->tick();
 	}
 }
 
@@ -241,7 +245,7 @@ void GAMECONTEXT::snap(int client_id)
 	
 	for(int i = 0; i < MAX_CLIENTS; i++)
 	{
-		if(players[i].client_id != -1)
-			players[i].snap(client_id);
+		if(players[i])
+			players[i]->snap(client_id);
 	}
 }
diff --git a/src/game/server/gamecontext.hpp b/src/game/server/gamecontext.hpp
index 4ef495fd..4c7079c8 100644
--- a/src/game/server/gamecontext.hpp
+++ b/src/game/server/gamecontext.hpp
@@ -37,7 +37,7 @@ public:
 	void clear();
 	
 	EVENTHANDLER events;
-	PLAYER players[MAX_CLIENTS];
+	PLAYER *players[MAX_CLIENTS];
 	
 	GAMECONTROLLER *controller;
 	GAMEWORLD world;
diff --git a/src/game/server/gamecontroller.cpp b/src/game/server/gamecontroller.cpp
index dc4ec129..7db92486 100644
--- a/src/game/server/gamecontroller.cpp
+++ b/src/game/server/gamecontroller.cpp
@@ -258,8 +258,8 @@ void GAMECONTROLLER::post_reset()
 {
 	for(int i = 0; i < MAX_CLIENTS; i++)
 	{
-		if(game.players[i].client_id != -1)
-			game.players[i].respawn();
+		if(game.players[i])
+			game.players[i]->respawn();
 	}
 }
 	
@@ -319,7 +319,7 @@ bool GAMECONTROLLER::is_friendly_fire(int cid1, int cid2)
 	
 	if(is_teamplay())
 	{
-		if(game.players[cid1].team == game.players[cid2].team)
+		if(game.players[cid1]->team == game.players[cid2]->team)
 			return true;
 	}
 	
@@ -364,8 +364,8 @@ void GAMECONTROLLER::tick()
 		int t[2] = {0,0};
 		for(int i = 0; i < MAX_CLIENTS; i++)
 		{
-			if(game.players[i].client_id != -1 && game.players[i].team != -1)
-				t[game.players[i].team]++;
+			if(game.players[i] && game.players[i]->team != -1)
+				t[game.players[i]->team]++;
 		}
 		
 		int m = (t[0] > t[1]) ? 0 : 1;
@@ -379,13 +379,13 @@ void GAMECONTROLLER::tick()
 			int pd = teamscore[m];
 			for(int i = 0; i < MAX_CLIENTS; i++)
 			{
-				if(game.players[i].client_id == -1)
+				if(!game.players[i])
 					continue;
 				
-				if(game.players[i].team == m && (!p || abs(scorediff - game.players[i].score) < pd))
+				if(game.players[i]->team == m && (!p || abs(scorediff - game.players[i]->score) < pd))
 				{
-					p = &(game.players[i]);
-					pd = abs(scorediff - game.players[i].score);
+					p = game.players[i];
+					pd = abs(scorediff - game.players[i]->score);
 				}
 			}
 			
@@ -418,8 +418,8 @@ void GAMECONTROLLER::tick()
 		{
 			for(int i = 0; i < MAX_CLIENTS; i++)
 			{
-				if(game.players[i].client_id != -1)
-					prog = max(prog, (game.players[i].score*100)/config.sv_scorelimit);
+				if(game.players[i])
+					prog = max(prog, (game.players[i]->score*100)/config.sv_scorelimit);
 			}
 		}
 	}
@@ -453,7 +453,7 @@ void GAMECONTROLLER::snap(int snapping_client)
 	gameobj->round_num = (strlen(config.sv_maprotation) || config.sv_rounds_per_map > 1) ? config.sv_rounds_per_map : 0;
 	gameobj->round_current = round_count+1;
 	
-	gameobj->teamscore_red = is_teamplay() ? teamscore[0] : game.players[snapping_client].score;
+	gameobj->teamscore_red = is_teamplay() ? teamscore[0] : game.players[snapping_client]->score;
 	gameobj->teamscore_blue = teamscore[1];
 }
 
@@ -462,10 +462,10 @@ int GAMECONTROLLER::get_auto_team(int notthisid)
 	int numplayers[2] = {0,0};
 	for(int i = 0; i < MAX_CLIENTS; i++)
 	{
-		if(game.players[i].client_id != -1 && game.players[i].client_id != notthisid)
+		if(game.players[i] && i != notthisid)
 		{
-			if(game.players[i].team == 0 || game.players[i].team == 1)
-				numplayers[game.players[i].team]++;
+			if(game.players[i]->team == 0 || game.players[i]->team == 1)
+				numplayers[game.players[i]->team]++;
 		}
 	}
 
@@ -484,10 +484,10 @@ bool GAMECONTROLLER::can_join_team(int team, int notthisid)
 	int numplayers[2] = {0,0};
 	for(int i = 0; i < MAX_CLIENTS; i++)
 	{
-		if(game.players[i].client_id != -1 && game.players[i].client_id != notthisid)
+		if(game.players[i] && i != notthisid)
 		{
-			if(game.players[i].team >= 0 || game.players[i].team == 1)
-				numplayers[game.players[i].team]++;
+			if(game.players[i]->team >= 0 || game.players[i]->team == 1)
+				numplayers[game.players[i]->team]++;
 		}
 	}
 	
@@ -502,8 +502,8 @@ bool GAMECONTROLLER::check_team_balance()
 	int t[2] = {0, 0};
 	for(int i = 0; i < MAX_CLIENTS; i++)
 	{
-		PLAYER *p = &(game.players[i]);
-		if(p->client_id != -1 && p->team != -1)
+		PLAYER *p = game.players[i];
+		if(p && p->team != -1)
 			t[p->team]++;
 	}
 	
@@ -531,8 +531,8 @@ bool GAMECONTROLLER::can_change_team(PLAYER *pplayer, int jointeam)
 	
 	for(int i = 0; i < MAX_CLIENTS; i++)
 	{
-		PLAYER *p = &(game.players[i]);
-		if(p->client_id != -1 && p->team != -1)
+		PLAYER *p = game.players[i];
+		if(p && p->team != -1)
 			t[p->team]++;
 	}
 	
@@ -563,14 +563,14 @@ void GAMECONTROLLER::do_player_score_wincheck()
 		int topscore_count = 0;
 		for(int i = 0; i < MAX_CLIENTS; i++)
 		{
-			if(game.players[i].client_id != -1)
+			if(game.players[i])
 			{
-				if(game.players[i].score > topscore)
+				if(game.players[i]->score > topscore)
 				{
-					topscore = game.players[i].score;
+					topscore = game.players[i]->score;
 					topscore_count = 1;
 				}
-				else if(game.players[i].score == topscore)
+				else if(game.players[i]->score == topscore)
 					topscore_count++;
 			}
 		}
diff --git a/src/game/server/gamemodes/ctf.cpp b/src/game/server/gamemodes/ctf.cpp
index 1188b891..c8e2e931 100644
--- a/src/game/server/gamemodes/ctf.cpp
+++ b/src/game/server/gamemodes/ctf.cpp
@@ -41,7 +41,7 @@ int GAMECONTROLLER_CTF::on_character_death(class CHARACTER *victim, class PLAYER
 	for(int fi = 0; fi < 2; fi++)
 	{
 		FLAG *f = flags[fi];
-		if(f && f->carrying_character == &killer->character)
+		if(f && f->carrying_character == killer->get_character())
 			had_flag |= 2;
 		if(f && f->carrying_character == victim)
 		{
@@ -139,13 +139,13 @@ void GAMECONTROLLER_CTF::tick()
 					
 					for(int c = 0; c < MAX_CLIENTS; c++)
 					{
-						if(game.players[c].client_id == -1)
+						if(!game.players[c])
 							continue;
 							
-						if(game.players[c].team == fi)
-							game.create_sound_global(SOUND_CTF_GRAB_EN, game.players[c].client_id);
+						if(game.players[c]->team == fi)
+							game.create_sound_global(SOUND_CTF_GRAB_EN, game.players[c]->client_id);
 						else
-							game.create_sound_global(SOUND_CTF_GRAB_PL, game.players[c].client_id);
+							game.create_sound_global(SOUND_CTF_GRAB_PL, game.players[c]->client_id);
 					}
 					break;
 				}
diff --git a/src/game/server/hooks.cpp b/src/game/server/hooks.cpp
index 3b16c422..0cd6d6e1 100644
--- a/src/game/server/hooks.cpp
+++ b/src/game/server/hooks.cpp
@@ -37,13 +37,13 @@ void send_tuning_params(int cid)
 void mods_client_direct_input(int client_id, void *input)
 {
 	if(!game.world.paused)
-		game.players[client_id].on_direct_input((NETOBJ_PLAYER_INPUT *)input);
+		game.players[client_id]->on_direct_input((NETOBJ_PLAYER_INPUT *)input);
 }
 
 void mods_client_predicted_input(int client_id, void *input)
 {
 	if(!game.world.paused)
-		game.players[client_id].on_predicted_input((NETOBJ_PLAYER_INPUT *)input);
+		game.players[client_id]->on_predicted_input((NETOBJ_PLAYER_INPUT *)input);
 }
 
 // Server hooks
@@ -60,27 +60,28 @@ void mods_snap(int client_id)
 void mods_client_enter(int client_id)
 {
 	//game.world.insert_entity(&game.players[client_id]);
-	game.players[client_id].respawn();
+	game.players[client_id]->respawn();
 	dbg_msg("game", "join player='%d:%s'", client_id, server_clientname(client_id));
 
 
 	char buf[512];
-	str_format(buf, sizeof(buf), "%s entered and joined the %s", server_clientname(client_id), game.controller->get_team_name(game.players[client_id].team));
+	str_format(buf, sizeof(buf), "%s entered and joined the %s", server_clientname(client_id), game.controller->get_team_name(game.players[client_id]->team));
 	game.send_chat(-1, GAMECONTEXT::CHAT_ALL, buf); 
 
-	dbg_msg("game", "team_join player='%d:%s' team=%d", client_id, server_clientname(client_id), game.players[client_id].team);
+	dbg_msg("game", "team_join player='%d:%s' team=%d", client_id, server_clientname(client_id), game.players[client_id]->team);
 }
 
 void mods_connected(int client_id)
 {
-	game.players[client_id].init(client_id);
+	game.players[client_id] = new PLAYER(client_id);
+	//game.players[client_id].init(client_id);
 	//game.players[client_id].client_id = client_id;
 	
 	// Check which team the player should be on
 	if(config.sv_tournament_mode)
-		game.players[client_id].team = -1;
+		game.players[client_id]->team = -1;
 	else
-		game.players[client_id].team = game.controller->get_auto_team(client_id);
+		game.players[client_id]->team = game.controller->get_auto_team(client_id);
 		
 	(void) game.controller->check_team_balance();
 
@@ -93,14 +94,15 @@ void mods_connected(int client_id)
 
 void mods_client_drop(int client_id)
 {
-	game.players[client_id].on_disconnect();
+	game.players[client_id]->on_disconnect();
 	(void) game.controller->check_team_balance();
+	delete game.players[client_id];
 }
 
 void mods_message(int msgtype, int client_id)
 {
 	void *rawmsg = netmsg_secure_unpack(msgtype);
-	PLAYER *p = &game.players[client_id];
+	PLAYER *p = game.players[client_id];
 	
 	if(!rawmsg)
 	{
@@ -197,7 +199,7 @@ void mods_message(int msgtype, int client_id)
 			// send all info to this client
 			for(int i = 0; i < MAX_CLIENTS; i++)
 			{
-				if(game.players[i].client_id != -1)
+				if(game.players[i])
 					game.send_info(i, client_id);
 			}
 
@@ -293,10 +295,10 @@ static void con_set_team(void *result, void *user_data)
 	
 	dbg_msg("", "%d %d", client_id, team);
 	
-	if(game.players[client_id].client_id != client_id)
+	if(!game.players[client_id])
 		return;
 	
-	game.players[client_id].set_team(team);
+	game.players[client_id]->set_team(team);
 }
 
 void mods_console_init()
@@ -371,7 +373,7 @@ void mods_init()
 			mods_connected(MAX_CLIENTS-i-1);
 			mods_client_enter(MAX_CLIENTS-i-1);
 			if(game.controller->is_teamplay())
-				game.players[MAX_CLIENTS-i-1].team = i&1;
+				game.players[MAX_CLIENTS-i-1]->team = i&1;
 		}
 	}
 }
diff --git a/src/game/server/player.cpp b/src/game/server/player.cpp
index 84efcd81..a31cf21c 100644
--- a/src/game/server/player.cpp
+++ b/src/game/server/player.cpp
@@ -5,17 +5,22 @@
 #include "player.hpp"
 #include "gamecontext.hpp"
 
-PLAYER::PLAYER()
+PLAYER::PLAYER(int client_id)
 {
+	character = 0;
+	this->client_id = client_id;
 }
 
+/*
 void PLAYER::init(int client_id)
 {
 	// clear everything
+	~PLAYER();
 	mem_zero(this, sizeof(*this));
 	new(this) PLAYER();
+	
 	this->client_id = client_id;
-}
+}*/
 
 void PLAYER::tick()
 {
@@ -75,9 +80,6 @@ void PLAYER::on_disconnect()
 	game.send_chat(-1, GAMECONTEXT::CHAT_ALL, buf);
 
 	dbg_msg("game", "leave player='%d:%s'", client_id, server_clientname(client_id));
-
-	// clear this whole structure
-	init(-1);
 }
 
 void PLAYER::on_predicted_input(NETOBJ_PLAYER_INPUT *new_input)
@@ -105,16 +107,20 @@ void PLAYER::on_direct_input(NETOBJ_PLAYER_INPUT *new_input)
 
 CHARACTER *PLAYER::get_character()
 {
-	if(character.alive)
-		return &character;
+	if(character && character->alive)
+		return character;
 	return 0;
 }
 
 void PLAYER::kill_character()
 {
-	CHARACTER *chr = get_character();
-	if(chr)
-		chr->die(-1, -1);
+	//CHARACTER *chr = get_character();
+	if(character)
+	{
+		character->die(-1, -1);
+		delete character;
+		character = 0;
+	}
 }
 
 void PLAYER::respawn()
@@ -138,12 +144,12 @@ void PLAYER::set_team(int new_team)
 	score = 0;
 	dbg_msg("game", "team_join player='%d:%s' team=%d", client_id, server_clientname(client_id), team);
 	
-	game.controller->on_player_info_change(&game.players[client_id]);
+	game.controller->on_player_info_change(game.players[client_id]);
 
 	// send all info to this client
 	for(int i = 0; i < MAX_CLIENTS; i++)
 	{
-		if(game.players[i].client_id != -1)
+		if(game.players[i])
 			game.send_info(i, -1);
 	}
 }
@@ -162,6 +168,7 @@ void PLAYER::try_respawn()
 	if(num_ents == 0)
 	{
 		spawning = false;
-		character.spawn(this, spawnpos, team);
+		character = new CHARACTER();
+		character->spawn(this, spawnpos, team);
 	}
 }
diff --git a/src/game/server/player.hpp b/src/game/server/player.hpp
index 55833d11..9836bffc 100644
--- a/src/game/server/player.hpp
+++ b/src/game/server/player.hpp
@@ -7,8 +7,9 @@
 // player object
 class PLAYER
 {
+	CHARACTER *character;
 public:
-	PLAYER();
+	PLAYER(int client_id);
 
 	// TODO: clean this up
 	char skin_name[64];
@@ -41,8 +42,6 @@ public:
 		int max;	
 	} latency;
 	
-	CHARACTER character;
-	
 	// this is used for snapping so we know how we can clip the view for the player
 	vec2 view_pos;