r4005 - in branches/nexuiz-2.0: . data data/qcsrc/client data/qcsrc/common data/qcsrc/server misc

DONOTREPLY at icculus.org DONOTREPLY at icculus.org
Sat Aug 2 06:20:26 EDT 2008


Author: div0
Date: 2008-08-02 06:20:24 -0400 (Sat, 02 Aug 2008)
New Revision: 4005

Modified:
   branches/nexuiz-2.0/.patchsets
   branches/nexuiz-2.0/data/defaultNexuiz.cfg
   branches/nexuiz-2.0/data/qcsrc/client/Main.qc
   branches/nexuiz-2.0/data/qcsrc/client/main.qh
   branches/nexuiz-2.0/data/qcsrc/client/miscfunctions.qc
   branches/nexuiz-2.0/data/qcsrc/client/sbar.qc
   branches/nexuiz-2.0/data/qcsrc/client/teamplay.qc
   branches/nexuiz-2.0/data/qcsrc/common/constants.qh
   branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc
   branches/nexuiz-2.0/data/qcsrc/server/clientcommands.qc
   branches/nexuiz-2.0/data/qcsrc/server/scores.qc
   branches/nexuiz-2.0/data/qcsrc/server/scores.qh
   branches/nexuiz-2.0/data/qcsrc/server/scores_rules.qc
   branches/nexuiz-2.0/data/qcsrc/server/sv_main.qc
   branches/nexuiz-2.0/misc/makebuild.sh
Log:
make CSQC scores safer against packet loss/rearrangements
work around broken ClientConnect/ClientDisconnect
in "cmd maplist", leave out the maps that won't work in the current game mode anyway
new packet loss column ("pl")
allow downloading csprogs.dat out of a pack
build script update (csqc)


Modified: branches/nexuiz-2.0/.patchsets
===================================================================
--- branches/nexuiz-2.0/.patchsets	2008-08-02 10:18:46 UTC (rev 4004)
+++ branches/nexuiz-2.0/.patchsets	2008-08-02 10:20:24 UTC (rev 4005)
@@ -1,2 +1,2 @@
 master = svn://svn.icculus.org/nexuiz/trunk
-revisions_applied = 1-3990
+revisions_applied = 1-4004

Modified: branches/nexuiz-2.0/data/defaultNexuiz.cfg
===================================================================
--- branches/nexuiz-2.0/data/defaultNexuiz.cfg	2008-08-02 10:18:46 UTC (rev 4004)
+++ branches/nexuiz-2.0/data/defaultNexuiz.cfg	2008-08-02 10:20:24 UTC (rev 4005)
@@ -1061,3 +1061,5 @@
 // these entities are not referenced by anything directly, they just represent
 // teams and are found by find() when needed
 prvm_leaktest_ignore_classnames "ctf_team dom_team tdm_team"
+
+sv_allowdownloads_inarchive 1 // for csprogs.dat

Modified: branches/nexuiz-2.0/data/qcsrc/client/Main.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/Main.qc	2008-08-02 10:18:46 UTC (rev 4004)
+++ branches/nexuiz-2.0/data/qcsrc/client/Main.qc	2008-08-02 10:20:24 UTC (rev 4005)
@@ -55,6 +55,7 @@
 	menu_show = menu_show_error;
 	menu_action = menu_sub_null;
 	using_gps = false;
+	maxclients = 255; // we later get the real maxclients to speed up stuff
 	//ctf_temp_1 = "";
 	// localcmd("alias order \"cmd order $*\""); enable if ctf-command thingy is used
 	//registercmd("ctf_menu");
@@ -79,7 +80,7 @@
 	teams = Sort_Spawn();
 	players = Sort_Spawn();
 	
-	teamspec = AddTeam(COLOR_SPECTATOR); // add specs first
+	GetTeam(COLOR_SPECTATOR, true); // add specs first
 }
 
 // CSQC_Shutdown : Called every time the CSQC code is shutdown (changing maps, quitting, etc)
@@ -95,25 +96,98 @@
 	remove(teams);
 	remove(players);
 	db_close(configdb);
-	buf_del(databuf);
 }
 
+.float has_team;
+float SetTeam(entity o, float Team)
+{
+	entity tm;
+	if(Team == -1) // leave
+	{
+		if(o.has_team)
+		{
+			//print("(DISCONNECT) leave team ", ftos(o.team), "\n");
+			tm = GetTeam(o.team, false);
+			tm.team_size -= 1;
+			o.has_team = 0;
+			return TRUE;
+		}
+	}
+	else
+	{
+		if not(o.has_team)
+		{
+			//print("(CONNECT) enter team ", ftos(o.team), "\n");
+			o.team = Team;
+			tm = GetTeam(Team, true);
+			tm.team_size += 1;
+			o.has_team = 1;
+			return TRUE;
+		}
+		else if(Team != o.team)
+		{
+			//print("(CHANGE) leave team ", ftos(o.team), "\n");
+			tm = GetTeam(o.team, false);
+			tm.team_size -= 1;
+			o.team = Team;
+			//print("(CHANGE) enter team ", ftos(o.team), "\n");
+			tm = GetTeam(Team, true);
+			tm.team_size += 1;
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+void Playerchecker_Think()
+{
+	entity pl;
+	float i;
+	for(i = 0; i < maxclients; ++i)
+	{
+		if(getplayerkey(i, "name") == "")
+		{
+			if(playerslots[i].sort_prev)
+			{
+				//print("playerchecker: KILL KILL KILL\n");
+				// player disconnected
+				SetTeam(playerslots[i], -1);
+				RemovePlayer(playerslots[i]);
+				playerslots[i].sort_prev = world;
+				playerslots[i].gotscores = 0;
+			}
+		}
+		else
+		{
+			if not(playerslots[i].sort_prev)
+			{
+				//print("playerchecker: SPAWN SPAWN SPAWN\n");
+				// player connected
+				if not(playerslots[i])
+					playerslots[i] = spawn();
+				playerslots[i].sv_entnum = i;
+				playerslots[i].gotscores = 0;
+				SetTeam(playerslots[i], COLOR_SPECTATOR);
+				RegisterPlayer(playerslots[i]);
+				Sbar_UpdatePlayerPos(playerslots[i]);
+			}
+		}
+	}
+	self.nextthink = time + 0.2;
+}
+
 void PostInit(void)
 {
 	float i;
 
 	print(strcat("PostInit\n    maxclients = ", ftos(maxclients), "\n"));
-	databuf = buf_create();
-	for(i = 0; i < maxclients; ++i)
-	{
-		bufstr_set(databuf, DATABUF_PING + i, "N/A");
-		bufstr_set(databuf, DATABUF_DEATHS + i, "0");
-		bufstr_set(databuf, DATABUF_CAPTURES + i, "0");
-		bufstr_set(databuf, DATABUF_RETURNS + i, "0");
-	}
-	
 	localcmd(strcat("\nsbar_columns_set ", cvar_string("sbar_columns"), ";\n"));
 
+	entity playerchecker;
+	playerchecker = spawn();
+	playerchecker.think = Playerchecker_Think;
+	playerchecker.nextthink = time + 0.2;
+
 	postinit = true;
 }
 
@@ -230,70 +304,45 @@
 	}
 }
 
-void Gamemode_Init();
-void Ent_ReadScoresInfo()
-{
-	float i;
-	gametype = ReadByte();
-	for(i = 0; i < MAX_SCORE; ++i)
-	{
-		scores_label[i] = strzone(ReadString());
-		scores_flags[i] = ReadByte();
-	}
-	for(i = 0; i < MAX_TEAMSCORE; ++i)
-	{
-		teamscores_label[i] = strzone(ReadString());
-		teamscores_flags[i] = ReadByte();
-	}
-	Sbar_InitScores();
-	Gamemode_Init();
-}
-
 void Ent_ReadPlayerScore(float isNew)
 {
 	float i, Team;
-	entity tm;
+	entity tm, o;
 
 	// damnit -.- don't want to go change every single .sv_entnum in sbar.qc AGAIN
 	// (no I've never heard of M-x replace-string, sed, or anything like that)
+	isNew = !self.owner; // workaround for DP bug
 	self.sv_entnum = ReadByte()-1;
 	Team = GetPlayerColor(self.sv_entnum);
 
-	if(isNew)
-		RegisterPlayer(self);
+	if not(playerslots[self.sv_entnum])
+		playerslots[self.sv_entnum] = spawn();
+	o = self.owner = playerslots[self.sv_entnum];
+	o.sv_entnum = self.sv_entnum;
+	o.gotscores = 1;
+	if not(o.sort_prev)
+		RegisterPlayer(o);
 
-	if(isNew || Team != self.team)
-	{
-		if(!isNew)
-		{
-			tm = GetTeam(self.team, false);
-			tm.team_size -= 1;
-		}
-		
-		self.team = Team;
-		tm = GetTeam(Team, true);
-		tm.team_size += 1;
-	}
+	SetTeam(o, Team);
 
 	for(i = 0; i < MAX_SCORE; ++i)
-		self.(scores[i]) = ReadShort();
+		o.(scores[i]) = ReadShort();
 
-	Sbar_UpdatePlayerPos(self);
+	Sbar_UpdatePlayerPos(o);
 }
 
 void Ent_ReadTeamScore(float isNew)
 {
 	float i;
+	entity o;
 	
 	self.team = ReadByte();
+	o = self.owner = GetTeam(self.team, true);
 
-	if(isNew)
-		RegisterTeam(self);
-
 	for(i = 0; i < MAX_TEAMSCORE; ++i)
-		self.(teamscores[i]) = ReadShort();
+		o.(teamscores[i]) = ReadShort();
 
-	Sbar_UpdateTeamPos(self);
+	Sbar_UpdateTeamPos(o);
 }
 
 // CSQC_Ent_Update : Called every frame that the server has indicated an update to the SSQC / CSQC entity has occured.
@@ -317,8 +366,6 @@
 			}
 		}
 	}
-	else if(self.enttype == ENT_CLIENT_SCORES_INFO)
-		Ent_ReadScoresInfo();
 	else if(self.enttype == ENT_CLIENT_SCORES)
 		Ent_ReadPlayerScore(bIsNewEntity);
 	else if(self.enttype == ENT_CLIENT_TEAMSCORES)
@@ -347,20 +394,23 @@
 					ent.chain = self.chain;
 			}
 		}
-	} else if(self.enttype == ENT_CLIENT_SCORES_INFO)
-	{
-		// OH NOES!! WE LOST DA SCORES INFO ENTITY
-		print("The world is going to explode.");
-		// kkthxbai
 	} else if(self.enttype == ENT_CLIENT_SCORES)
 	{
 		entity tm;
-		tm = GetTeam(self.team, false);
-		tm.team_size -= 1;
-		RemovePlayer(self);
+		if(self.owner)
+		{
+			SetTeam(self.owner, -1);
+			RemovePlayer(self.owner);
+			self.owner.sort_prev = NULL;
+		}
 	} else if(self.enttype == ENT_CLIENT_TEAMSCORES)
 	{
-		RemoveTeam(self);
+		/*
+		if(self.owner)
+			RemoveTeam(self.owner);
+		*/
+		// we don't NEED to remove them... they won't display anyway
+		// plus, svqc never does this anyway
 	}
 	remove(self);
 }
@@ -440,45 +490,31 @@
 
 void CSQC_CheckRevision();
 
-void Net_ReadInit()
+void Gamemode_Init();
+void Net_ReadScoresInfo()
 {
-	csqc_revision = ReadShort();
-	maxclients = ReadByte();
-
-	CSQC_CheckRevision();
-}
-
-void Net_ReadPings()
-{
-	float plnum, ping;
-	for(plnum = ReadByte(); plnum != 0; plnum = ReadByte())
+	float i;
+	gametype = ReadByte();
+	for(i = 0; i < MAX_SCORE; ++i)
 	{
-		ping = ReadShort();
-		bufstr_set(databuf, DATABUF_PING + plnum-1, ftos(ping));
+		scores_label[i] = strzone(ReadString());
+		scores_flags[i] = ReadByte();
 	}
-}
-
-void Net_ReadCaptures()
-{
-	float plnum, caps, mode;
-	mode = ReadByte();
-	caps_team1 = ReadByte();
-	caps_team2 = ReadByte();
-	for(plnum = ReadByte(); plnum != 0; plnum = ReadByte())
+	for(i = 0; i < MAX_TEAMSCORE; ++i)
 	{
-		caps = ReadByte();
-		bufstr_set(databuf, DATABUF_CAPTURES + plnum-1, ftos(caps));
+		teamscores_label[i] = strzone(ReadString());
+		teamscores_flags[i] = ReadByte();
 	}
+	Sbar_InitScores();
+	Gamemode_Init();
 }
 
-void Net_ReadDatabuf(float ofs)
+void Net_ReadInit()
 {
-	float plnum, data;
-	for(plnum = ReadByte(); plnum != 0; plnum = ReadByte())
-	{
-		data = ReadByte();
-		bufstr_set(databuf, ofs + plnum-1, ftos(data));
-	}
+	csqc_revision = ReadShort();
+	maxclients = ReadByte();
+
+	CSQC_CheckRevision();
 }
 
 string Net_ReadPicture()
@@ -529,22 +565,6 @@
 			Net_ReadInit();
 			bHandled = true;
 			break;
-		case TE_CSQC_PING:
-			Net_ReadPings();
-			bHandled = true;
-			break;
-		case TE_CSQC_CAPTURES:
-			Net_ReadCaptures();
-			bHandled = true;
-			break;
-		case TE_CSQC_RETURNS:
-			Net_ReadDatabuf(DATABUF_RETURNS);
-			bHandled = true;
-			break;
-		case TE_CSQC_DEATHS:
-			Net_ReadDatabuf(DATABUF_DEATHS);
-			bHandled = true;
-			break;
 		case TE_CSQC_MAPVOTE:
 			Net_Mapvote();
 			bHandled = true;
@@ -553,6 +573,10 @@
 			Net_Config();
 			bHandled = true;
 			break;
+		case TE_CSQC_SCORESINFO:
+			Net_ReadScoresInfo();
+			bHandled = true;
+			break;
 		default:
 			// No special logic for this temporary entity; return 0 so the engine can handle it
 			bHandled = false;

Modified: branches/nexuiz-2.0/data/qcsrc/client/main.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/main.qh	2008-08-02 10:18:46 UTC (rev 4004)
+++ branches/nexuiz-2.0/data/qcsrc/client/main.qh	2008-08-02 10:20:24 UTC (rev 4005)
@@ -73,6 +73,7 @@
 #define SP_NAME -3
 #define SP_KDRATIO -4
 #define SP_CLRATIO -5
+#define SP_PL -6
 
 #define SP_SEPARATOR -100
 
@@ -101,3 +102,8 @@
 #define CSQC_FLAG_READPICTURE 1
 
 string config_get(string key, string defaultvalue);
+
+entity playerslots[255]; // 255 is engine limit on maxclients
+entity teamslots[17];    // 17 teams (including "spectator team")
+.float gotscores;
+.entity owner;

Modified: branches/nexuiz-2.0/data/qcsrc/client/miscfunctions.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/miscfunctions.qc	2008-08-02 10:18:46 UTC (rev 4004)
+++ branches/nexuiz-2.0/data/qcsrc/client/miscfunctions.qc	2008-08-02 10:20:24 UTC (rev 4005)
@@ -9,7 +9,7 @@
 	entity pl;
 	for(pl = players.sort_next; pl; pl = pl.sort_next)
 		if(pl == player)
-			return false;
+			error("Player already registered!");
 	player.sort_next = players.sort_next;
 	player.sort_prev = players;
 	if(players.sort_next)
@@ -35,19 +35,6 @@
 		player.sort_next.sort_prev = parent;
 }
 
-entity AddTeam(float num)
-{
-	entity tm;
-	tm = spawn();
-	tm.team = num;
-	tm.sort_next = teams.sort_next;
-	tm.sort_prev = teams;
-	if(teams.sort_next)
-		teams.sort_next.sort_prev = tm;
-	teams.sort_next = tm;
-	return tm;
-}
-
 void MoveToLast(entity e)
 {
 	other = e.sort_next;
@@ -65,7 +52,7 @@
 	entity tm;
 	for(tm = teams.sort_next; tm; tm = tm.sort_next)
 		if(tm == Team)
-			return false;
+			error("Team already registered!");
 	Team.sort_next = teams.sort_next;
 	Team.sort_prev = teams;
 	if(teams.sort_next)
@@ -91,19 +78,20 @@
 		Team.sort_next.sort_prev = parent;
 }
 
-entity GetTeam(float num, float add)
+entity GetTeam(float Team, float add)
 {
+	float num;
 	entity tm;
-	for(tm = teams.sort_next; tm; tm = tm.sort_next)
-	{
-		if(tm.team == num)
-			return tm;
-	}
-	
-	if(add)
-		return AddTeam(num);
-	
-	return NULL;
+	num = (Team == COLOR_SPECTATOR) ? 16 : Team;
+	if(teamslots[num])
+		return teamslots[num];
+	if not(add)
+		return NULL;
+	tm = spawn();
+	tm.team = Team;
+	teamslots[num] = tm;
+	RegisterTeam(tm);
+	return tm;
 }
 
 float stringwidth_oldfont(string text, float handleColors)

Modified: branches/nexuiz-2.0/data/qcsrc/client/sbar.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/sbar.qc	2008-08-02 10:18:46 UTC (rev 4004)
+++ branches/nexuiz-2.0/data/qcsrc/client/sbar.qc	2008-08-02 10:20:24 UTC (rev 4005)
@@ -20,8 +20,6 @@
 float ps_primary, ps_secondary;
 float ts_primary, ts_secondary;
 
-entity team1, team2, team3, team4, teamspec;
-
 void CSQC_kh_hud();
 void CSQC_ctf_hud();
 void MapVote_Draw();
@@ -162,6 +160,8 @@
 }
 
 void Sbar_UpdatePlayerPos(entity pl);
+float SetTeam(entity pl, float Team);
+//float lastpnum;
 void Sbar_UpdatePlayerTeams()
 {
 	float Team;
@@ -173,15 +173,8 @@
 	{
 		num += 1;
 		Team = GetPlayerColor(pl.sv_entnum);
-		if(pl.team != Team)
+		if(SetTeam(pl, Team))
 		{
-			tmp = GetTeam(pl.team, false);
-			tmp.team_size -= 1;
-			tmp = GetTeam(Team, true);
-			tmp.team_size += 1;
-			
-			pl.team = Team;
-
 			tmp = pl.sort_prev;
 			Sbar_UpdatePlayerPos(pl);
 			if(tmp)
@@ -190,7 +183,11 @@
 				pl = players.sort_next;
 		}
 	}
-	//print(strcat("PNUM: ", ftos(num), "\n"));
+	/*
+	if(num != lastpnum)
+		print(strcat("PNUM: ", ftos(num), "\n"));
+	lastpnum = num;
+	*/
 }
 
 float Sbar_ComparePlayerScores(entity left, entity right)
@@ -204,6 +201,15 @@
 	if(vl < vr)
 		return false;
 
+	if(vl == COLOR_SPECTATOR)
+	{
+		// FIRST the one with scores (spectators), THEN the ones without (downloaders)
+		// no other sorting
+		if(!left.gotscores && right.gotscores)
+			return true;
+		return false;
+	}
+
 	vl = left.scores[ps_primary];
 	vr = right.scores[ps_primary];
 	if(vl > vr)
@@ -305,7 +311,7 @@
 
 string Sbar_DefaultColumnLayout()
 {
-	return "ping name | -ctf,kh/kills -ctf,kh/deaths +lms/lives +lms/rank +kh,ctf/caps +kh/pushes +kh/destroyed -lms/score";
+	return "ping pl name | -ctf,kh/kills -ctf,kh/deaths +lms/lives +lms/rank +kh,ctf/caps +kh/pushes +kh/destroyed -lms/score";
 }
 
 void Cmd_Sbar_SetFields(float argc)
@@ -387,6 +393,8 @@
 
 		if(str == "ping") {
 			sbar_field[sbar_num_fields] = SP_PING;
+		} else if(str == "pl") {
+			sbar_field[sbar_num_fields] = SP_PL;
 		} else if(str == "name" || str == "nick") {
 			sbar_field[sbar_num_fields] = SP_NAME;
 			sbar_size[sbar_num_fields] = MIN_NAMELEN; // minimum size? any use?
@@ -496,11 +504,25 @@
 	switch(field)
 	{
 		case SP_PING:
-			str = bufstr_get(databuf, DATABUF_PING + pl.sv_entnum);
+			if not(pl.gotscores)
+				return "\x8D\x8D\x8D"; // >>> sign
+			str = getplayerkey(pl.sv_entnum, "ping");
+			if(str == "0")
+				return "N/A";
 			tmp = max(0, min(220, stof(str)-80)) / 220;
 			sbar_field_rgb = '1 1 1' - '0 1 1'*tmp;
 			return str;
 		
+		case SP_PL:
+			if not(pl.gotscores)
+				return "N/A";
+			str = getplayerkey(pl.sv_entnum, "pl");
+			if(str == "0")
+				return "";
+			tmp = bound(0, stof(str), 20) / 20; // 20% is REALLY BAD pl
+			sbar_field_rgb = '1 0.5 0.5' - '0 0.5 0.5'*tmp;
+			return str;
+		
 		case SP_NAME:
 			return getplayerkey(pl.sv_entnum, "name");
 
@@ -693,6 +715,7 @@
 	}
 }
 
+float lastpingstime;
 void Sbar_DrawScoreboard()
 {
 	//float xmin, ymin, xmax, ymax;
@@ -701,6 +724,12 @@
 	float specs, i;
 	float center_x;
 
+	if(time > lastpingstime + 10)
+	{
+		localcmd("pings\n");
+		lastpingstime = time;
+	}
+
 	sbar_fontsize = Sbar_GetFontsize();
 	if(sbar_fontsize_x == 0)
 		sbar_fontsize = '8 8 0';
@@ -1125,6 +1154,8 @@
 		return 1;
 	else if (intermission == 2)
 		return 1;
+	else if (getstati(STAT_HEALTH) <= 0 && cvar("cl_deathscoreboard"))
+		return 1;
 	return 0;
 }
 

Modified: branches/nexuiz-2.0/data/qcsrc/client/teamplay.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/client/teamplay.qc	2008-08-02 10:18:46 UTC (rev 4004)
+++ branches/nexuiz-2.0/data/qcsrc/client/teamplay.qc	2008-08-02 10:20:24 UTC (rev 4005)
@@ -16,8 +16,10 @@
 
 float GetPlayerColor(float i)
 {
-	if(getplayerkey(i, "frags") == "-666")
+	if not(playerslots[i].gotscores) // unconnected
 		return COLOR_SPECTATOR;
+	else if(getplayerkey(i, "frags") == "-666")
+		return COLOR_SPECTATOR;
 	else if(!teamplay)
 		return 0;
 	else

Modified: branches/nexuiz-2.0/data/qcsrc/common/constants.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/common/constants.qh	2008-08-02 10:18:46 UTC (rev 4004)
+++ branches/nexuiz-2.0/data/qcsrc/common/constants.qh	2008-08-02 10:20:24 UTC (rev 4005)
@@ -4,7 +4,9 @@
 // Revision 3: optimized map vote protocol
 // Revision 4: CSQC config var system
 // Revision 5: mapvote time fix
-#define CSQC_REVISION 5
+// Revision 6: more robust against packet loss/delays, also show not yet connected clients
+// Revision 7: packet loss column
+#define CSQC_REVISION 7
 
 // probably put these in common/
 // so server/ and client/ can be synced better
@@ -180,6 +182,7 @@
 const float TE_CSQC_PICTURE = 105;
 const float TE_CSQC_MAPVOTE = 106;
 const float TE_CSQC_CONFIG = 107;
+const float TE_CSQC_SCORESINFO = 108;
 
 const float STAT_KH_KEYS = 32;
 const float STAT_CTF_STATE = 33;

Modified: branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc	2008-08-02 10:18:46 UTC (rev 4004)
+++ branches/nexuiz-2.0/data/qcsrc/server/cl_client.qc	2008-08-02 10:20:24 UTC (rev 4005)
@@ -984,6 +984,12 @@
 	local string s;
 	float wep;
 
+	if(self.flags & FL_CLIENT)
+	{
+		print("Warning: ClientConnect, but already connected!\n");
+		return;
+	}
+
 	if(Ban_IsClientBanned(self))
 	{
 		s = strcat("^1NOTE:^7 banned client ", self.netaddress, " just tried to enter\n");
@@ -995,6 +1001,7 @@
 	DecodeLevelParms();
 
 	self.classname = "player_joining";
+
 	self.flags = self.flags | FL_CLIENT;
 	self.version_nagtime = time + 10 + random() * 10;
 
@@ -1138,6 +1145,7 @@
 			MapVote_SendData(MSG_ONE);
 			MapVote_UpdateData(MSG_ONE);
 		}
+		ScoreInfo_Write(MSG_ONE);
 	}
 
 	if(g_lms)
@@ -1165,6 +1173,12 @@
 {
 	float save;
 
+	if not(self.flags & FL_CLIENT)
+	{
+		print("Warning: ClientDisconnect without ClientConnect\n");
+		return;
+	}
+
 	bot_clientdisconnect();
 
 	if(entcs_start)
@@ -1222,10 +1236,7 @@
 	}
 	*/
 
-	if(self.flags & FL_CLIENT)
-		PlayerScore_Detach(self);
-	else
-		print("Warning: ClientDisconnect without ClientConnect\n");
+	PlayerScore_Detach(self);
 
 	if(self.netname_previous)
 		strunzone(self.netname_previous);

Modified: branches/nexuiz-2.0/data/qcsrc/server/clientcommands.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/clientcommands.qc	2008-08-02 10:18:46 UTC (rev 4004)
+++ branches/nexuiz-2.0/data/qcsrc/server/clientcommands.qc	2008-08-02 10:20:24 UTC (rev 4005)
@@ -282,17 +282,21 @@
 			}
 		}
 	} else if(argv(0) == "maplist") {
-		local float n;
+		local float n, j;
 		local string col;
 		n = tokenize(cvar_string("g_maplist"));
 		sprint(self, "^7Maps in list: ");
-		for(i = 0; i < n; ++i)
+		for(i = 0, j = 0; i < n; ++i)
 		{
-			if(mod(i, 2))
-				col = "^2";
-			else
-				col = "^3";
-			sprint(self, strcat(col, argv(i), " "));
+			if(MapInfo_CheckMap(argv(i)))
+			{
+				if(mod(j, 2))
+					col = "^2";
+				else
+					col = "^3";
+				sprint(self, strcat(col, argv(i), " "));
+				++j;
+			}
 		}
 		sprint(self, "\n");
 #ifdef MAPINFO

Modified: branches/nexuiz-2.0/data/qcsrc/server/scores.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/scores.qc	2008-08-02 10:18:46 UTC (rev 4004)
+++ branches/nexuiz-2.0/data/qcsrc/server/scores.qc	2008-08-02 10:20:24 UTC (rev 4005)
@@ -121,26 +121,29 @@
 		teamscores_primary = teamscores[i];
 }
 
-float ScoreInfo_SendEntity(entity to)
+void ScoreInfo_Write(float targ)
 {
-	WriteByte(MSG_ENTITY, ENT_CLIENT_SCORES_INFO);
 	float i;
-	WriteByte(MSG_ENTITY, game);
+	if not(scores_initialized)
+		return;
+	WriteByte(targ, SVC_TEMPENTITY);
+	WriteByte(targ, TE_CSQC_SCORESINFO);
+	WriteByte(targ, game);
 	for(i = 0; i < MAX_SCORE; ++i)
 	{
-		WriteString(MSG_ENTITY, scores_label[i]);
-		WriteByte(MSG_ENTITY, scores_flags[i]);
+		WriteString(targ, scores_label[i]);
+		WriteByte(targ, scores_flags[i]);
 	}
 	for(i = 0; i < MAX_TEAMSCORE; ++i)
 	{
-		WriteString(MSG_ENTITY, teamscores_label[i]);
-		WriteByte(MSG_ENTITY, teamscores_flags[i]);
+		WriteString(targ, teamscores_label[i]);
+		WriteByte(targ, teamscores_flags[i]);
 	}
-	return TRUE;
 }
 
 void ScoreInfo_Init(float teams)
 {
+	entity pl;
 	scores_initialized = 1;
 	if(teams >= 1)
 		TeamScore_Spawn(COLOR_TEAM1, "Red");
@@ -150,12 +153,8 @@
 		TeamScore_Spawn(COLOR_TEAM3, "Yellow");
 	if(teams >= 4)
 		TeamScore_Spawn(COLOR_TEAM4, "Pink");
-	entity si;
-	si = spawn();
-	Net_LinkEntity(si);
-	si.classname = "csqc_score_info";
-	si.SendEntity = ScoreInfo_SendEntity;
-	si.Version = 1;
+	FOR_EACH_REALCLIENT(msg_entity) // cannot use MSG_ALL here, as that may come too early on level changes (that SUCKS)
+		ScoreInfo_Write(MSG_ONE);
 }
 
 /*

Modified: branches/nexuiz-2.0/data/qcsrc/server/scores.qh
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/scores.qh	2008-08-02 10:18:46 UTC (rev 4004)
+++ branches/nexuiz-2.0/data/qcsrc/server/scores.qh	2008-08-02 10:20:24 UTC (rev 4005)
@@ -51,12 +51,6 @@
 #define PlayerTeamScore_AddScore(p,s) PlayerTeamScore_Add(p, SP_SCORE, ST_SCORE, s)
 
 /**
- * Initialize the scores info for the given number of teams.
- * Immediately set all labels afterwards.
- */
-void ScoreInfo_Init(float teams);
-
-/**
  * Set the label of a team score item, as well as the scoring flags.
  */
 void ScoreInfo_SetLabel_TeamScore(float i, string label, float scoreflags);
@@ -67,6 +61,18 @@
 void ScoreInfo_SetLabel_PlayerScore(float i, string label, float scoreflags);
 
 /**
+ * Initialize the scores info for the given number of teams.
+ * Set all labels right before this call.
+ */
+void ScoreInfo_Init(float teams);
+
+/**
+ * Writes the scores info to the given stream. Use this in ClientConnect to
+ * notify newly connecting players.
+ */
+void ScoreInfo_Write(float targ);
+
+/**
  * Clear ALL scores (for ready-restart).
  */
 void Score_ClearAll();

Modified: branches/nexuiz-2.0/data/qcsrc/server/scores_rules.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/scores_rules.qc	2008-08-02 10:18:46 UTC (rev 4004)
+++ branches/nexuiz-2.0/data/qcsrc/server/scores_rules.qc	2008-08-02 10:20:24 UTC (rev 4005)
@@ -3,9 +3,10 @@
 
 // NOTE: SP_ constants may not be >= MAX_SCORE; ST_constants may not be >= MAX_TEAMSCORE
 // scores that should be in all modes:
+float ScoreRules_teams;
 void ScoreRules_basics(float teams, float sprio)
 {
-	ScoreInfo_Init(teams);
+	ScoreRules_teams = teams;
 	if(sprio)
 		ScoreInfo_SetLabel_TeamScore  (ST_SCORE,        "score",     sprio);
 	ScoreInfo_SetLabel_PlayerScore(SP_KILLS,        "kills",     0);
@@ -14,6 +15,10 @@
 	if(sprio)
 		ScoreInfo_SetLabel_PlayerScore(SP_SCORE,        "score",     sprio);
 }
+void ScoreRules_basics_end()
+{
+	ScoreInfo_Init(ScoreRules_teams);
+}
 void ScoreRules_generic()
 {
 	CheckAllowedTeams(world);
@@ -24,6 +29,7 @@
 	}
 	else
 		ScoreRules_basics(0, SFL_SORT_PRIO_PRIMARY);
+	ScoreRules_basics_end();
 }
 
 // g_ctf
@@ -59,6 +65,7 @@
 	ScoreInfo_SetLabel_PlayerScore(SP_CTF_PICKUPS,  "pickups",   0);
 	ScoreInfo_SetLabel_PlayerScore(SP_CTF_FCKILLS,  "fckills",   0);
 	ScoreInfo_SetLabel_PlayerScore(SP_CTF_RETURNS,  "returns",   0);
+	ScoreRules_basics_end();
 }
 
 // g_domination
@@ -78,6 +85,7 @@
 	ScoreInfo_SetLabel_TeamScore  (ST_DOM_TICKS,    "ticks",     sp_domticks);
 	ScoreInfo_SetLabel_PlayerScore(SP_DOM_TICKS,    "ticks",     sp_domticks);
 	ScoreInfo_SetLabel_PlayerScore(SP_DOM_TAKES,    "takes",     0);
+	ScoreRules_basics_end();
 }
 
 // LMS stuff
@@ -88,6 +96,7 @@
 	ScoreRules_basics(0, 0);
 	ScoreInfo_SetLabel_PlayerScore(SP_LMS_LIVES,    "lives",     SFL_SORT_PRIO_SECONDARY);
 	ScoreInfo_SetLabel_PlayerScore(SP_LMS_RANK,     "rank",      SFL_LOWER_IS_BETTER | SFL_RANK | SFL_SORT_PRIO_PRIMARY | SFL_ALLOW_HIDE);
+	ScoreRules_basics_end();
 }
 
 // Key hunt stuff
@@ -108,4 +117,5 @@
 	ScoreInfo_SetLabel_PlayerScore(SP_KH_PICKUPS,   "pickups",   0);
 	ScoreInfo_SetLabel_PlayerScore(SP_KH_KCKILLS,   "kckills",   0);
 	ScoreInfo_SetLabel_PlayerScore(SP_KH_LOSSES,    "losses",    SFL_LOWER_IS_BETTER);
+	ScoreRules_basics_end();
 }

Modified: branches/nexuiz-2.0/data/qcsrc/server/sv_main.qc
===================================================================
--- branches/nexuiz-2.0/data/qcsrc/server/sv_main.qc	2008-08-02 10:18:46 UTC (rev 4004)
+++ branches/nexuiz-2.0/data/qcsrc/server/sv_main.qc	2008-08-02 10:20:24 UTC (rev 4005)
@@ -137,19 +137,6 @@
 }
 
 
-void BroadcastPings()
-{
-	entity pl;
-	WriteByte(MSG_BROADCAST, SVC_TEMPENTITY);
-	WriteByte(MSG_BROADCAST, TE_CSQC_PING);
-	FOR_EACH_CLIENT(pl)
-	{
-		WriteByte(MSG_BROADCAST, num_for_edict(pl));
-		WriteShort(MSG_BROADCAST, pl.ping);
-	}
-	WriteByte(MSG_BROADCAST, 0);
-}
-
 /*
 =============
 StartFrame
@@ -197,10 +184,4 @@
 		self = RandomSelection_chosen_ent;
 		SelectSpawnPoint(0);
 	}
-
-	if(next_pingtime < time)
-	{
-		BroadcastPings();
-		next_pingtime = time + 10;
-	}
 }

Modified: branches/nexuiz-2.0/misc/makebuild.sh
===================================================================
--- branches/nexuiz-2.0/misc/makebuild.sh	2008-08-02 10:18:46 UTC (rev 4004)
+++ branches/nexuiz-2.0/misc/makebuild.sh	2008-08-02 10:20:24 UTC (rev 4005)
@@ -33,7 +33,7 @@
 		;;
 esac
 
-basepk3=$base/data20080229.pk3
+basepk3=$base/data20080229.pk3 # 2.4
 hotbasepk3=
 nexdir=$base/nexuiz
 nexprodir=$base/nexuiz/pro
@@ -202,12 +202,9 @@
 rm -f *.o *.bin
 make
 
-cd "$tmpdir/data/qcsrc/$menuqc"
-"$fteqccdir/fteqcc.bin" $fteqccflags
+cd "$tmpdir/data"
+make FTEQCC="$fteqccdir/fteqcc.bin"
 
-cd "$tmpdir/data/qcsrc/server"
-"$fteqccdir/fteqcc.bin" $fteqccflags
-
 rm -rf "$tmpdir/data/qcsrc"
 
 cd "$tmpdir/Docs"




More information about the nexuiz-commits mailing list