about summary refs log tree commit diff
path: root/src/engine/server
diff options
context:
space:
mode:
authorMagnus Auvinen <magnus.auvinen@gmail.com>2007-08-14 18:37:16 +0000
committerMagnus Auvinen <magnus.auvinen@gmail.com>2007-08-14 18:37:16 +0000
commit2cde04ddcec3f3c083527c464f93bf8c30b6e790 (patch)
tree2666b20bf713f7d5244af1aec9f2d2f54d193f35 /src/engine/server
parent8809084d253be4e9923307a13c8830c593dfefc0 (diff)
downloadzcatch-2cde04ddcec3f3c083527c464f93bf8c30b6e790.tar.gz
zcatch-2cde04ddcec3f3c083527c464f93bf8c30b6e790.zip
merged over all stuff from 0.2 to trunk
Diffstat (limited to 'src/engine/server')
-rw-r--r--src/engine/server/server.cpp233
1 files changed, 150 insertions, 83 deletions
diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp
index 3769157e..984292e9 100644
--- a/src/engine/server/server.cpp
+++ b/src/engine/server/server.cpp
@@ -30,6 +30,97 @@ void *snap_new_item(int type, int id, int size)
 	return builder.new_item(type, id, size);
 }
 
+
+struct snap_id
+{
+	short next;
+	short state; // 0 = free, 1 = alloced, 2 = timed
+	int timeout_tick;
+};
+
+static const int MAX_IDS = 8*1024; // should be lowered
+static snap_id snap_ids[8*1024];
+static int snap_first_free_id;
+static int snap_first_timed_id;
+static int snap_last_timed_id;
+static int snap_id_usage;
+static int snap_id_inusage;
+
+static int snap_id_inited = 0;
+
+void snap_init_id()
+{
+	for(int i = 0; i < MAX_IDS; i++)
+	{
+		snap_ids[i].next = i+1;
+		snap_ids[i].state = 0;
+	}
+		
+	snap_ids[MAX_IDS-1].next = -1;
+	snap_first_free_id = 0;
+	snap_first_timed_id = -1;
+	snap_last_timed_id = -1;
+	snap_id_usage = 0;
+	snap_id_inusage = 0;
+	
+	snap_id_inited = 1;
+}
+
+int snap_new_id()
+{
+	dbg_assert(snap_id_inited == 1, "requesting id too soon");
+	
+	// process timed ids
+	while(snap_first_timed_id != -1 && snap_ids[snap_first_timed_id].timeout_tick < server_tick())
+	{
+		int next_timed = snap_ids[snap_first_timed_id].next;
+		
+		// add it to the free list
+		snap_ids[snap_first_timed_id].next = snap_first_free_id;
+		snap_ids[snap_first_timed_id].state = 0;
+		snap_first_free_id = snap_first_timed_id;
+		
+		// remove it from the timed list
+		snap_first_timed_id = next_timed;
+		if(snap_first_timed_id == -1)
+			snap_last_timed_id = -1;
+			
+		snap_id_usage--;
+	}
+	
+	int id = snap_first_free_id;
+	dbg_assert(id != -1, "id error");
+	snap_first_free_id = snap_ids[snap_first_free_id].next;
+	snap_ids[id].state = 1;
+	snap_id_usage++;
+	snap_id_inusage++;
+	return id;
+}
+
+void snap_free_id(int id)
+{
+	dbg_assert(snap_ids[id].state == 1, "id is not alloced");
+
+	snap_id_inusage--;
+	snap_ids[id].state = 2;
+	snap_ids[id].timeout_tick = server_tick() + server_tickspeed()*5;
+	snap_ids[id].next = -1;
+	
+	if(snap_last_timed_id != -1)
+	{
+		snap_ids[snap_last_timed_id].next = id;
+		snap_last_timed_id = id;
+	}
+	else
+	{
+		snap_first_timed_id = id;
+		snap_last_timed_id = id;
+	}
+}
+
+
+
+
 //
 class client
 {
@@ -132,31 +223,51 @@ int server_send_msg(int client_id)
 		net.send(&packet);
 	return 0;
 }
+
+static int new_client_callback(int cid, void *user)
+{
+	clients[cid].state = client::STATE_CONNECTING;
+	clients[cid].name[0] = 0;
+	clients[cid].clan[0] = 0;
+	clients[cid].snapshots.purge_all();
+	clients[cid].last_acked_snapshot = -1;
+	return 0;
+}
+
+static int del_client_callback(int cid, void *user)
+{
+	clients[cid].state = client::STATE_EMPTY;
+	clients[cid].name[0] = 0;
+	clients[cid].clan[0] = 0;
+	clients[cid].snapshots.purge_all();
 	
+	mods_client_drop(cid);
+	return 0;
+}
+		
 // TODO: remove this class
 class server
 {
 public:
 	//socket_udp4 game_socket;
-
-	const char *map_name;
 	int64 lasttick;
 	int64 lastheartbeat;
 	netaddr4 master_server;
 
 	int biggest_snapshot;
 
-	bool run(const char *mapname)
+	bool run()
 	{
 		biggest_snapshot = 0;
 
 		net_init(); // For Windows compatibility.
-		map_name = mapname;
+		
+		snap_init_id();
 
 		// load map
-		if(!map_load(mapname))
+		if(!map_load(config.sv_map))
 		{
-			dbg_msg("server", "failed to load map. mapname='%s'", mapname);
+			dbg_msg("server", "failed to load map. mapname='%s'", config.sv_map);
 			return false;
 		}
 		
@@ -173,12 +284,14 @@ public:
 			bindaddr.port = config.sv_port;
 		}
 		
-		if(!net.open(bindaddr, 0, 0))
+		if(!net.open(bindaddr, config.sv_max_clients, 0))
 		{
-			dbg_msg("network/server", "couldn't open socket");
+			dbg_msg("server", "couldn't open socket. port might already be in use");
 			return false;
 		}
-
+		
+		net.set_callbacks(new_client_callback, del_client_callback, 0);
+		
 		dbg_msg("server", "server name is '%s'", config.sv_name);
 		dbg_msg("server", "masterserver is '%s'", config.masterserver);
 		if (net_host_lookup(config.masterserver, MASTERSERVER_PORT, &master_server) != 0)
@@ -242,12 +355,16 @@ public:
 
 			if(reporttime < time_get())
 			{
-				dbg_msg("server/report", "sim=%.02fms snap=%.02fms net=%.02fms total=%.02fms load=%.02f%%",
-					(simulationtime/reportinterval)/(double)time_freq()*1000,
-					(snaptime/reportinterval)/(double)time_freq()*1000,
-					(networktime/reportinterval)/(double)time_freq()*1000,
-					(totaltime/reportinterval)/(double)time_freq()*1000,
-					(totaltime)/reportinterval/(double)time_freq()*100.0f);
+				if(config.debug)
+				{
+					dbg_msg("server", "sim=%.02fms snap=%.02fms net=%.02fms total=%.02fms load=%.02f%% ids=%d/%d",
+						(simulationtime/reportinterval)/(double)time_freq()*1000,
+						(snaptime/reportinterval)/(double)time_freq()*1000,
+						(networktime/reportinterval)/(double)time_freq()*1000,
+						(totaltime/reportinterval)/(double)time_freq()*1000,
+						(totaltime)/reportinterval/(double)time_freq()*100.0f,
+						snap_id_inusage, snap_id_usage);
+				}
 
 				simulationtime = 0;
 				snaptime = 0;
@@ -313,8 +430,6 @@ public:
 						delta_tick = clients[i].last_acked_snapshot;
 						deltashot = (snapshot *)delta_data;
 					}
-					else
-						dbg_msg("server", "no delta, sending full snapshot");
 				}
 				
 				// create delta
@@ -337,6 +452,7 @@ public:
 
 					const int max_size = MAX_SNAPSHOT_PACKSIZE;
 					int numpackets = (snapshot_size+max_size-1)/max_size;
+					(void)numpackets;
 					for(int n = 0, left = snapshot_size; left; n++)
 					{
 						int chunk = left < max_size ? left : max_size;
@@ -373,14 +489,13 @@ public:
 	void send_map(int cid)
 	{
 		msg_pack_start_system(NETMSG_MAP, MSGFLAG_VITAL);
-		msg_pack_string(map_name, 0);
+		msg_pack_string(config.sv_map, 0);
 		msg_pack_end();
 		server_send_msg(cid);
 	}
 	
 	void send_heartbeat()
 	{
-		dbg_msg("server", "sending heartbeat");
 		NETPACKET packet;
 		packet.client_id = -1;
 		packet.address = master_server;
@@ -397,7 +512,7 @@ public:
 
 		clients[cid].state = client::STATE_EMPTY;
 		mods_client_drop(cid);
-		dbg_msg("game", "player dropped. reason='%s' cid=%x name='%s'", reason, cid, clients[cid].name);
+		dbg_msg("server", "player dropped. reason='%s' cid=%x name='%s'", reason, cid, clients[cid].name);
 	}
 
 	void process_client_packet(NETPACKET *packet)
@@ -434,7 +549,7 @@ public:
 			{
 				if(clients[cid].state != client::STATE_INGAME)
 				{
-					dbg_msg("game", "player as entered the game. cid=%x", cid);
+					dbg_msg("server", "player as entered the game. cid=%x", cid);
 					clients[cid].state = client::STATE_INGAME;
 					mods_client_enter(cid);
 				}
@@ -483,7 +598,7 @@ public:
 		packer.reset();
 		packer.add_raw(SERVERBROWSE_INFO, sizeof(SERVERBROWSE_INFO));
 		packer.add_string(config.sv_name, 128);
-		packer.add_string(map_name, 128);
+		packer.add_string(config.sv_map, 128);
 		packer.add_int(MAX_CLIENTS); // max_players
 		int c = 0;
 		for(int i = 0; i < MAX_CLIENTS; i++)
@@ -537,7 +652,8 @@ public:
 				else if(packet.data_size == sizeof(SERVERBROWSE_FWOK) &&
 					memcmp(packet.data, SERVERBROWSE_FWOK, sizeof(SERVERBROWSE_FWOK)) == 0)
 				{
-					dbg_msg("server", "no firewall/nat problems detected");
+					if(config.debug)
+						dbg_msg("server", "no firewall/nat problems detected");
 				}
 				else if(packet.data_size == sizeof(SERVERBROWSE_FWERROR) &&
 					memcmp(packet.data, SERVERBROWSE_FWERROR, sizeof(SERVERBROWSE_FWERROR)) == 0)
@@ -549,35 +665,6 @@ public:
 			else
 				process_client_packet(&packet);
 		}
-		
-		// check for removed clients
-		while(1)
-		{
-			int cid = net.delclient();
-			if(cid == -1)
-				break;
-			
-			clients[cid].state = client::STATE_EMPTY;
-			clients[cid].name[0] = 0;
-			clients[cid].clan[0] = 0;
-			clients[cid].snapshots.purge_all();
-			
-			mods_client_drop(cid);
-		}
-		
-		// check for new clients
-		while(1)
-		{
-			int cid = net.newclient();
-			if(cid == -1)
-				break;
-			
-			clients[cid].state = client::STATE_CONNECTING;
-			clients[cid].name[0] = 0;
-			clients[cid].clan[0] = 0;
-			clients[cid].snapshots.purge_all();
-			clients[cid].last_acked_snapshot = -1;
-		}
 	}
 };
 
@@ -586,50 +673,30 @@ int main(int argc, char **argv)
 	dbg_msg("server", "starting...");
 
 	config_reset();
+
 #ifdef CONF_PLATFORM_MACOSX
-		config_load("~/.teewars");
+	const char *config_filename = "~/.teewars";
 #else
-		config_load("default.cfg");
+	const char *config_filename = "default.cfg";
 #endif
 
-	const char *mapname = "dm1";
-	
-	// parse arguments
 	for(int i = 1; i < argc; i++)
 	{
-		if(argv[i][0] == '-' && argv[i][1] == 'm' && argv[i][2] == 0 && argc - i > 1)
+		if(argv[i][0] == '-' && argv[i][1] == 'f' && argv[i][2] == 0 && argc - i > 1)
 		{
-			// -m map
+			config_filename = argv[i+1];
 			i++;
-			mapname = argv[i];
-		}
-		else if(argv[i][0] == '-' && argv[i][1] == 'n' && argv[i][2] == 0 && argc - i > 1)
-		{
-			// -n server name
-			i++;
-			config_set_sv_name(&config, argv[i]);
-		}
-		else if(argv[i][0] == '-' && argv[i][1] == 'p' && argv[i][2] == 0)
-		{
-			// -p (private server)
-			config_set_sv_sendheartbeats(&config, 0);
-		}
-		else if(argv[i][0] == '-' && argv[i][1] == 'o' && argv[i][2] == 0)
-		{
-			// -o port
-			i++;
-			config_set_sv_port(&config, atol(argv[i]));
 		}
 	}
 
-	if(!mapname)
-	{
-		dbg_msg("server", "no map given (-m MAPNAME)");
-		return 0;
-	}
+	config_load(config_filename);
+
+	// parse arguments
+	for(int i = 1; i < argc; i++)
+		config_set(argv[i]);
 
 	server_init();
 	server s;
-	s.run(mapname);
+	s.run();
 	return 0;
 }