about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMagnus Auvinen <magnus.auvinen@gmail.com>2007-09-23 22:54:31 +0000
committerMagnus Auvinen <magnus.auvinen@gmail.com>2007-09-23 22:54:31 +0000
commit06c341be51a75fd8a24f2441654e184fd3fdefcd (patch)
tree6531724f2acaf5a56fdb9af0f8a0c9271467848b
parente55ba53ba7aa993279bf3f6a21b1e771fda74f1d (diff)
downloadzcatch-06c341be51a75fd8a24f2441654e184fd3fdefcd.tar.gz
zcatch-06c341be51a75fd8a24f2441654e184fd3fdefcd.zip
dynamic map change
-rw-r--r--src/engine/client/client.c66
-rw-r--r--src/engine/interface.h1
-rw-r--r--src/engine/map.c9
-rw-r--r--src/engine/server/server.c58
-rw-r--r--src/game/server/game_server.cpp82
-rw-r--r--src/game/server/game_server.h2
6 files changed, 131 insertions, 87 deletions
diff --git a/src/engine/client/client.c b/src/engine/client/client.c
index 87a3481f..1fce3833 100644
--- a/src/engine/client/client.c
+++ b/src/engine/client/client.c
@@ -231,14 +231,6 @@ int snap_num_items(int snapid)
 	return snapshots[snapid]->snap->num_items;
 }
 
-static void snap_init()
-{
-	snapshots[SNAP_CURRENT] = 0;
-	snapshots[SNAP_PREV] = 0;
-	recived_snapshots = 0;
-	current_predtick = 0;
-}
-
 // ------ time functions ------
 float client_intratick() { return intratick; }
 float client_intrapredtick() { return intrapredtick; }
@@ -268,8 +260,6 @@ int client_send_msg()
 
 static void client_send_info()
 {
-	recived_snapshots = 0;
-
 	msg_pack_start_system(NETMSG_INFO, MSGFLAG_VITAL);
 	msg_pack_string(modc_net_version(), 128);
 	msg_pack_string(config.player_name, 128);
@@ -472,6 +462,23 @@ static void client_set_state(int s)
 		modc_statechange(state, old);
 }
 
+/* called when the map is loaded and we should init for a new round */
+static void client_on_enter_game()
+{
+	// reset input
+	int i;
+	for(i = 0; i < 200; i++)
+		inputs[i].tick = -1;
+	current_input = 0;
+
+	// reset snapshots
+	snapshots[SNAP_CURRENT] = 0;
+	snapshots[SNAP_PREV] = 0;
+	snapstorage_purge_all(&snapshot_storage);
+	recived_snapshots = 0;
+	current_predtick = 0;
+	current_recv_tick = 0;
+}
 
 void client_connect(const char *server_address_str)
 {
@@ -500,14 +507,6 @@ void client_connect(const char *server_address_str)
 	
 	netclient_connect(net, &server_address);
 	client_set_state(CLIENTSTATE_CONNECTING);	
-	
-	current_recv_tick = 0;
-	
-	// reset input
-	int i;
-	for(i = 0; i < 200; i++)
-		inputs[i].tick = -1;
-	current_input = 0;
 }
 
 void client_disconnect()
@@ -692,13 +691,15 @@ static void client_process_packet(NETPACKET *packet)
 					dbg_msg("client/network", "loading done");
 					// now we will wait for two snapshots
 					// to finish the connection
+					
+					client_on_enter_game();
 				}
 				else
 				{
 					client_error("failure to load map");
 				}
 			}
-			else if(msg == NETMSG_SNAP || msg == NETMSG_SNAPEMPTY) //|| msg == NETMSG_SNAPSMALL || msg == NETMSG_SNAPEMPTY)
+			else if(msg == NETMSG_SNAP || msg == NETMSG_SNAPEMPTY)
 			{
 				//dbg_msg("client/network", "got snapshot");
 				int game_tick = msg_unpack_int();
@@ -791,12 +792,13 @@ static void client_process_packet(NETPACKET *packet)
 						if(msg != NETMSG_SNAPEMPTY && snapshot_crc((SNAPSHOT*)tmpbuffer3) != crc)
 						{
 							if(config.debug)
-								dbg_msg("client", "snapshot crc error");
+								dbg_msg("client", "snapshot crc error %d", snapcrcerrors);
 							snapcrcerrors++;
-							if(snapcrcerrors > 25)
+							if(snapcrcerrors > 10)
 							{
 								// to many errors, send reset
 								ack_game_tick = -1;
+								client_send_input();
 								snapcrcerrors = 0;
 							}
 							return;
@@ -845,27 +847,8 @@ static void client_process_packet(NETPACKET *packet)
 						}
 						
 						st_update(&game_time, (game_tick-2)*time_freq()/50);
-						//client_send_input();
-
-						//st_update(&predicted_time, game_tick*time_freq());
-
-						/*
-						int64 now = time_get();
-						int64 t = now - game_tick*time_freq()/50;
-						if(game_start_time == -1 || t < game_start_time)
-						{
-							if(config.debug)
-								dbg_msg("client", "adjusted time");
-							game_start_time = t;
-						}
-						
-						int64 wanted = game_start_time+(game_tick*time_freq())/50;
-						float current_latency = (now-wanted)/(float)time_freq();
-						snapshot_latency = snapshot_latency*0.95f+current_latency*0.05f;
-						*/
 						
 						// ack snapshot
-						//dbg_msg("snap!", "%d", game_tick);
 						ack_game_tick = game_tick;
 					}
 				}
@@ -932,9 +915,6 @@ static void client_run(const char *direct_connect_server)
 	// init menu
 	modmenu_init(); // TODO: remove
 	
-	// init snapshotting
-	snap_init();
-	
 	// init the mod
 	modc_init();
 	dbg_msg("client", "version %s", modc_net_version());
diff --git a/src/engine/interface.h b/src/engine/interface.h
index 97a4b684..b2412de7 100644
--- a/src/engine/interface.h
+++ b/src/engine/interface.h
@@ -805,6 +805,7 @@ void snap_free_id(int id);
 
 /* other */
 void map_unload_data(int index);
+void map_set(void *m);
 
 #ifdef __cplusplus
 }
diff --git a/src/engine/map.c b/src/engine/map.c
index 53ade00a..dfb8b691 100644
--- a/src/engine/map.c
+++ b/src/engine/map.c
@@ -1,7 +1,7 @@
 #include <stdio.h>
 #include "datafile.h"
 
-static DATAFILE *map;
+static DATAFILE *map = 0;
 
 void *map_get_data(int index)
 {
@@ -51,3 +51,10 @@ int map_load(const char *mapname)
 	map = datafile_load(buf);
 	return map != 0;
 }
+
+void map_set(void *m)
+{
+	if(map)
+		map_unload();
+	map = (DATAFILE*)m;
+}
diff --git a/src/engine/server/server.c b/src/engine/server/server.c
index 57f315f7..db911819 100644
--- a/src/engine/server/server.c
+++ b/src/engine/server/server.c
@@ -15,6 +15,7 @@
 #include <engine/network.h>
 #include <engine/config.h>
 #include <engine/packer.h>
+#include <engine/datafile.h>
 
 #include <mastersrv/mastersrv.h>
 
@@ -26,7 +27,8 @@ static int current_tick = 0;
 static int64 lastheartbeat;
 static NETADDR4 master_server;
 
-static int biggest_snapshot;
+static char current_map[64];
+
 
 void *snap_new_item(int type, int id, int size)
 {
@@ -304,9 +306,6 @@ static void server_do_snap()
 				int compsize = zerobit_compress(intdata, intsize, compdata);
 				snapshot_size = compsize;
 
-				if(snapshot_size > biggest_snapshot)
-					biggest_snapshot = snapshot_size;
-
 				const int max_size = MAX_SNAPSHOT_PACKSIZE;
 				int numpackets = (snapshot_size+max_size-1)/max_size;
 				(void)numpackets;
@@ -565,17 +564,29 @@ static void server_pump_network()
 	}
 }
 
+static int server_load_map(const char *mapname)
+{
+	DATAFILE *df;
+	char buf[512];
+	sprintf(buf, "data/maps/%s.map", mapname);
+	df = datafile_load(buf);
+	if(!df)
+		return 0;
+		
+	strcpy(current_map, mapname);
+	map_set(df);
+	return 1;
+}
+
 
 static int server_run()
 {
-	biggest_snapshot = 0;
-
 	net_init(); /* For Windows compatibility. */
 	
 	snap_init_id();
 
 	/* load map */
-	if(!map_load(config.sv_map))
+	if(!server_load_map(config.sv_map))
 	{
 		dbg_msg("server", "failed to load map. mapname='%s'", config.sv_map);
 		return -1;
@@ -632,6 +643,39 @@ static int server_run()
 
 	while(1)
 	{
+		/* load new map TODO: don't poll this */
+		if(strcmp(config.sv_map, current_map) != 0)
+		{
+			/* load map */
+			if(server_load_map(config.sv_map))
+			{
+				int c;
+				
+				/* new map loaded */
+				mods_shutdown();
+				
+				for(c = 0; c < MAX_CLIENTS; c++)
+				{
+					if(clients[c].state == SRVCLIENT_STATE_EMPTY)
+						continue;
+					
+					server_send_map(c);
+					clients[c].state = SRVCLIENT_STATE_CONNECTING;
+					clients[c].last_acked_snapshot = -1;
+					snapstorage_purge_all(&clients[c].snapshots);
+				}
+				
+				mods_init();
+				game_start_time = time_get();
+				current_tick = 0;
+			}
+			else
+			{
+				dbg_msg("server", "failed to load map. mapname='%s'", config.sv_map);
+				config_set_sv_map(&config, current_map);
+			}
+		}
+		
 		int64 t = time_get();
 		if(t > server_tick_start_time(current_tick+1))
 		{
diff --git a/src/game/server/game_server.cpp b/src/game/server/game_server.cpp
index 7ad4ec09..9d28a38c 100644
--- a/src/game/server/game_server.cpp
+++ b/src/game/server/game_server.cpp
@@ -19,6 +19,8 @@ void create_sound(vec2 pos, int sound, int loopflags = 0);
 void create_targetted_sound(vec2 pos, int sound, int target, int loopflags = 0);
 class player *intersect_player(vec2 pos0, vec2 pos1, vec2 &new_pos, class entity *notthis = 0);
 
+game_world *world;
+
 //////////////////////////////////////////////////
 // Event handler
 //////////////////////////////////////////////////
@@ -253,8 +255,6 @@ void game_world::tick()
 	remove_entities();
 }
 
-game_world world;
-
 //////////////////////////////////////////////////
 // game object
 //////////////////////////////////////////////////
@@ -288,14 +288,14 @@ gameobject::gameobject()
 
 void gameobject::endround()
 {
-	world.paused = true;
+	world->paused = true;
 	game_over_tick = server_tick();
 	sudden_death = 0;
 }
 
 void gameobject::resetgame()
 {
-	world.reset_requested = true;
+	world->reset_requested = true;
 }
 
 void gameobject::startround()
@@ -305,7 +305,7 @@ void gameobject::startround()
 	round_start_tick = server_tick();
 	sudden_death = 0;
 	game_over_tick = -1;
-	world.paused = false;
+	world->paused = false;
 }
 
 void gameobject::post_reset()
@@ -424,7 +424,7 @@ void gameobject::tick()
 void gameobject::snap(int snapping_client)
 {
 	obj_game *game = (obj_game *)snap_new_item(OBJTYPE_GAME, 0, sizeof(obj_game));
-	game->paused = world.paused;
+	game->paused = world->paused;
 	game->game_over = game_over_tick==-1?0:1;
 	game->sudden_death = sudden_death;
 	
@@ -469,12 +469,12 @@ projectile::projectile(int type, int owner, vec2 pos, vec2 vel, int span, entity
 	this->sound_impact = sound_impact;
 	this->weapon = weapon;
 	this->bounce = 0;
-	world.insert_entity(this);
+	world->insert_entity(this);
 }
 
 void projectile::reset()
 {
-	world.destroy_entity(this);
+	world->destroy_entity(this);
 }
 
 void projectile::tick()
@@ -514,7 +514,7 @@ void projectile::tick()
 			targetplayer->take_damage(normalize(vel) * max(0.001f, force), damage, owner, weapon);
 		}
 			
-		world.destroy_entity(this);
+		world->destroy_entity(this);
 	}
 }
 
@@ -551,7 +551,7 @@ void projectile_backpackrocket::tick()
 {
 	lifespan--;
 	if(!lifespan)
-		world.destroy_entity(this);
+		world->destroy_entity(this);
 		
 	vec2 oldpos = pos;
 		
@@ -592,7 +592,7 @@ void projectile_backpackrocket::tick()
 			
 		create_explosion(oldpos, owner, weapon, false);
 			
-		world.destroy_entity(this);
+		world->destroy_entity(this);
 	}	
 }
 
@@ -706,7 +706,7 @@ void player::try_respawn()
 	// check if the position is occupado
 	entity *ents[2] = {0};
 	int types[] = {OBJTYPE_PLAYER};
-	int num_ents = world.find_entities(spawnpos, 64, ents, 2, types, 1);
+	int num_ents = world->find_entities(spawnpos, 64, ents, 2, types, 1);
 	for(int i = 0; i < num_ents; i++)
 	{
 		if(ents[i] != this)
@@ -770,7 +770,7 @@ void player::release_hooks()
 {
 	/*
 	// TODO: loop thru players only
-	for(entity *ent = world.first_entity; ent; ent = ent->next_entity)
+	for(entity *ent = world->first_entity; ent; ent = ent->next_entity)
 	{
 		if(ent && ent->objtype == OBJTYPE_PLAYER)
 		{
@@ -839,7 +839,7 @@ int player::handle_ninja()
 			vec2 dir = pos - oldpos;
 			float radius = phys_size * 2.0f; //length(dir * 0.5f);
 			vec2 center = oldpos + dir * 0.5f;
-			int num = world.find_entities(center, radius, ents, 64, &type, 1);
+			int num = world->find_entities(center, radius, ents, 64, &type, 1);
 			
 			for (int i = 0; i < num; i++)
 			{
@@ -999,7 +999,7 @@ int player::handle_weapons()
 		vec2 dir = lookdir * data->weapons[active_weapon].meleereach;
 		float radius = length(dir * 0.5f);
 		vec2 center = pos + dir * 0.5f;
-		int num = world.find_entities(center, radius, ents, 64, &type, 1);
+		int num = world->find_entities(center, radius, ents, 64, &type, 1);
 		
 		for (int i = 0; i < num; i++)
 		{
@@ -1106,7 +1106,7 @@ void player::tick()
 	
 	
 	// handle weapons
-	int retflags = handle_weapons();
+	handle_weapons();
 	/*
 	if (!(retflags & (MODIFIER_RETURNFLAGS_OVERRIDEVELOCITY | MODIFIER_RETURNFLAGS_OVERRIDEPOSITION)))
 	{
@@ -1329,7 +1329,7 @@ powerup::powerup(int _type, int _subtype)
 	reset();
 	
 	// TODO: should this be done here?
-	world.insert_entity(this);
+	world->insert_entity(this);
 }
 
 void powerup::reset()
@@ -1412,7 +1412,7 @@ void powerup::tick()
 				// loop through all players, setting their emotes
 				entity *ents[64];
 				const int types[] = {OBJTYPE_PLAYER};
-				int num = world.find_entities(vec2(0, 0), 1000000, ents, 64, types, 1);
+				int num = world->find_entities(vec2(0, 0), 1000000, ents, 64, types, 1);
 				for (int i = 0; i < num; i++)
 				{
 					player *p = (player *)ents[i];
@@ -1467,7 +1467,7 @@ flag::flag(int _team)
 	reset();
 	
 	// TODO: should this be done here?
-	world.insert_entity(this);
+	world->insert_entity(this);
 }
 
 void flag::reset()
@@ -1477,7 +1477,7 @@ void flag::reset()
 
 void flag::tick()
 {
-	// THIS CODE NEEDS TO BE REWRITTEN. ITS NOT SAVE AT ALL
+	// THIS CODE NEEDS TO BE REWRITTEN. ITS NOT SAFE AT ALL
 	
 	// wait for respawn
 	if(spawntick > 0)
@@ -1493,7 +1493,7 @@ void flag::tick()
 	{
 		player *players[MAX_CLIENTS];
 		int types[] = {OBJTYPE_PLAYER};
-		int num = world.find_entities(pos, 32.0f, (entity**)players, MAX_CLIENTS, types, 1);
+		int num = world->find_entities(pos, 32.0f, (entity**)players, MAX_CLIENTS, types, 1);
 		for(int i = 0; i < num; i++)
 		{
 			if(players[i]->team != team)
@@ -1589,7 +1589,7 @@ void create_explosion(vec2 p, int owner, int weapon, bool bnodamage)
 		entity *ents[64];
 		const float radius = 128.0f;
 		const float innerradius = 42.0f;
-		int num = world.find_entities(p, radius, ents, 64);
+		int num = world->find_entities(p, radius, ents, 64);
 		for(int i = 0; i < num; i++)
 		{
 			vec2 diff = ents[i]->pos - p;
@@ -1667,7 +1667,7 @@ player* intersect_player(vec2 pos0, vec2 pos1, vec2& new_pos, entity* notthis)
 	float radius = length(dir * 0.5f);
 	vec2 center = pos0 + dir * 0.5f;
 	const int types[] = {OBJTYPE_PLAYER};
-	int num = world.find_entities(center, radius, ents, 64, types, 1);
+	int num = world->find_entities(center, radius, ents, 64, types, 1);
 	for (int i = 0; i < num; i++)
 	{
 		// Check if entity is a player
@@ -1686,9 +1686,9 @@ void mods_tick()
 {
 	// clear all events
 	events.clear();
-	world.tick();
+	world->tick();
 	
-	if(world.paused) // make sure that the game object always updates
+	if(world->paused) // make sure that the game object always updates
 		gameobj->tick();
 
 	if(config.dbg_bots)
@@ -1715,13 +1715,13 @@ void mods_tick()
 
 void mods_snap(int client_id)
 {
-	world.snap(client_id);
+	world->snap(client_id);
 	events.snap(client_id);
 }
 
 void mods_client_input(int client_id, void *input)
 {
-	if(!world.paused)
+	if(!world->paused)
 	{
 		if (memcmp(&players[client_id].input, input, sizeof(player_input)) != 0)
 			players[client_id].last_action = server_tick();
@@ -1771,7 +1771,7 @@ void mods_client_enter(int client_id)
 {
 	players[client_id].init();
 	players[client_id].client_id = client_id;
-	world.insert_entity(&players[client_id]);
+	world->insert_entity(&players[client_id]);
 	players[client_id].respawn();
 	
 	CLIENT_INFO info; // fetch login name
@@ -1822,7 +1822,7 @@ void mods_client_drop(int client_id)
 
 	dbg_msg("game", "leave player='%d:%s'", client_id, players[client_id].name);
 	
-	world.remove_entity(&players[client_id]);
+	world->remove_entity(&players[client_id]);
 	players[client_id].client_id = -1;
 }
 
@@ -1863,17 +1863,20 @@ extern unsigned char internal_data[];
 
 void mods_init()
 {
-	data = load_data_from_memory(internal_data);
+	if(!data) /* only load once */
+		data = load_data_from_memory(internal_data);
+		
 	col_init(32);
 
+	world = new game_world;
 	players = new player[MAX_CLIENTS];
 	gameobj = new gameobject;
 	
 	// setup core world	
 	for(int i = 0; i < MAX_CLIENTS; i++)
 	{
-		players[i].core.world = &world.core;
-		world.core.players[i] = &players[i].core;
+		players[i].core.world = &world->core;
+		world->core.players[i] = &players[i].core;
 	}
 
 	//
@@ -1942,15 +1945,24 @@ void mods_init()
 
 			flag *f = new flag(i);
 			f->pos = gameobj->flagsstands[i];
-			//world.insert_entity(f);
+			//world->insert_entity(f);
 			dbg_msg("game", "flag at %f,%f", f->pos.x, f->pos.y);
 		}
 	}
 	
-	world.insert_entity(gameobj);
+	world->insert_entity(gameobj);
 }
 
-void mods_shutdown() {}
+void mods_shutdown()
+{
+	delete [] players;
+	delete gameobj;
+	delete world;
+	gameobj = 0;
+	players = 0;
+	world = 0;
+}
+	
 void mods_presnap() {}
 void mods_postsnap() {}
 
diff --git a/src/game/server/game_server.h b/src/game/server/game_server.h
index 56f668f6..59044a4c 100644
--- a/src/game/server/game_server.h
+++ b/src/game/server/game_server.h
@@ -100,7 +100,7 @@ public:
 	void tick();
 };
 
-extern game_world world;
+extern game_world *world;
 
 // game object
 class gameobject : public entity