From 8b0980ff06801da73570a34932c9d3b9986b68a4 Mon Sep 17 00:00:00 2001 From: blub0 Date: Mon, 14 Jul 2008 12:06:39 +0000 Subject: [PATCH] mapvote protocol optimized and fixed CSQC_REVISION 3 git-svn-id: svn://svn.icculus.org/nexuiz/trunk@3821 f962a42d-fe04-0410-a3ab-8c8b0445ebaa --- data/qcsrc/client/Main.qc | 9 +-- data/qcsrc/client/mapvoting.qc | 72 +++++++++++++++------- data/qcsrc/client/sbar.qc | 1 - data/qcsrc/common/constants.qh | 3 +- data/qcsrc/server/cl_client.qc | 2 +- data/qcsrc/server/g_world.qc | 109 ++++++++++++++++++++------------- 6 files changed, 122 insertions(+), 74 deletions(-) diff --git a/data/qcsrc/client/Main.qc b/data/qcsrc/client/Main.qc index 5802ad272..685c98888 100644 --- a/data/qcsrc/client/Main.qc +++ b/data/qcsrc/client/Main.qc @@ -376,7 +376,7 @@ void Net_ReadDatabuf(float ofs) } } -void Net_ReadPicture() +string Net_ReadPicture() { string img; if(csqc_flags & CSQC_FLAG_READPICTURE) @@ -394,6 +394,7 @@ void Net_ReadPicture() for(i = 0; i < psize; ++i) ReadByte(); } + return img; } // CSQC_Parse_TempEntity : Handles all temporary entity network data in the CSQC layer. @@ -430,10 +431,6 @@ float CSQC_Parse_TempEntity() Net_ReadDatabuf(DATABUF_DEATHS); bHandled = true; break; - case TE_CSQC_PICTURE: - Net_ReadPicture(); - bHandled = true; - break; case TE_CSQC_MAPVOTE: Net_Mapvote(); bHandled = true; @@ -455,7 +452,7 @@ float CSQC_Parse_TempEntity() float csqc_svn_map[CSQC_REVISION] = { 3812, // 3795, - 3815 + 3820 // mapvote protocol changed from there }; // COMMIT-TODO: Update if necessare, before committing diff --git a/data/qcsrc/client/mapvoting.qc b/data/qcsrc/client/mapvoting.qc index 865f4e70c..cefc73c32 100644 --- a/data/qcsrc/client/mapvoting.qc +++ b/data/qcsrc/client/mapvoting.qc @@ -100,10 +100,10 @@ void MapVote_Draw() string map; float i, tmp; vector pos; - vector center; float isize; + float center; - center_x = (vid_conwidth - 1)/2; + center = (vid_conwidth - 1)/2; xmin = vid_conwidth*0.2; xmax = vid_conwidth - xmin; ymin = 24; @@ -122,7 +122,7 @@ void MapVote_Draw() pos_y = ymin; pos_z = 0; - pos_x = center_x - stringwidth("Vote for a map", false) * 0.5 * 24; + pos_x = center - stringwidth("Vote for a map", false) * 0.5 * 24; drawstring(pos, "Vote for a map", '24 24', '1 1 1', 1, DRAWFLAG_NORMAL); pos_x = xmin; @@ -201,7 +201,6 @@ void MapVote_CheckPic(string pic, string pk3, float id) { if(PreviewExists(pic)) { - //print(strcat("^2Exists... ", pic, "\n")); mv_preview[id] = true; return; } @@ -210,48 +209,75 @@ void MapVote_CheckPic(string pic, string pk3, float id) void MapVote_Init() { - float i; + float i, power, m; string map, pk3; mv_num_maps = min(MAPVOTE_COUNT, ReadByte()); mv_abstain = ReadByte(); if(mv_abstain) - mv_abstain = 1; // must be 1 + mv_abstain = 1; // must be 1 for bool-true, makes stuff easier mv_detail = ReadByte(); mv_ownvote = -1; + + if(mv_num_maps <= 8) + m = ReadByte(); + else + m = ReadShort(); // Assume mv_pk3list is NULL, there should only be 1 mapvote per round mv_pk3list = NULL; // I'm still paranoid! - for(i = 0; i < mv_num_maps; ++i) + for(i = 0, power = 1; i < mv_num_maps; ++i, power *= 2) { mv_votes[i] = 0; - map = strzone(ReadString()); - pk3 = strzone(ReadString()); - mv_maps[i] = map; - mv_pk3[i] = pk3; - map = strzone(strcat("maps/", map)); - mv_pics[i] = map; - mv_preview[i] = false; + if(m & power) + { + map = strzone(ReadString()); + pk3 = strzone(ReadString()); + mv_maps[i] = map; + mv_pk3[i] = pk3; + map = strzone(strcat("maps/", map)); + mv_pics[i] = map; + + mv_preview[i] = false; - //print(strcat("RECV: ", map, " in ", pk3, "\n")); - MapVote_CheckPic(map, pk3, i); + //print(strcat("RECV: ", map, " in ", pk3, "\n")); + MapVote_CheckPic(map, pk3, i); + } + else + { + mv_maps[i] = strzone("if-you-see-this-the-code-is-broken"); + mv_pk3[i] = strzone("if-you-see-this-the-code-is-broken"); + mv_pics[i] = strzone("if-you-see-this-the-code-is-broken"); + mv_preview[i] = false; + } } } void MapVote_Update() { - float i, e; - for(i = 0; i < mv_num_maps; ++i) + float i, power; + float m; + if(mv_num_maps <= 8) + m = ReadByte(); + else + m = ReadShort(); + for(i = 0, power = 1; i < mv_num_maps; ++i, power *= 2) { - e = ReadByte(); - mv_votes[i] = ReadByte(); - if(!e) + if(m & power) + { + if(mv_detail) + mv_votes[i] = ReadByte(); + else + mv_votes[i] = 0; + } + else mv_votes[i] = -1; } } +string Net_ReadPicture(); void Net_Mapvote() { float type; @@ -260,6 +286,8 @@ void Net_Mapvote() { case MAPVOTE_NET_INIT: MapVote_Init(); + // do we NEED this, or can we handle key presses directly in CSQC? + localcmd("\nin_bind 7 1 \"impulse 1\"; in_bind 7 2 \"impulse 2\"; in_bind 7 3 \"impulse 3\"; in_bind 7 4 \"impulse 4\"; in_bind 7 5 \"impulse 5\"; in_bind 7 6 \"impulse 6\"; in_bind 7 7 \"impulse 7\"; in_bind 7 8 \"impulse 8\"; in_bind 7 9 \"impulse 9\"; in_bind 7 0 \"impulse 10\"; in_bind 7 KP_1 \"impulse 1\"; in_bind 7 KP_2 \"impulse 2\"; in_bind 7 KP_3 \"impulse 3\"; in_bind 7 KP_4 \"impulse 4\"; in_bind 7 KP_5 \"impulse 5\"; in_bind 7 KP_6 \"impulse 6\"; in_bind 7 KP_7 \"impulse 7\"; in_bind 7 KP_8 \"impulse 8\"; in_bind 7 KP_9 \"impulse 9\"; in_bind 7 KP_0 \"impulse 10\"; in_bindmap 7 0\n"); break; case MAPVOTE_NET_UPDATE: MapVote_Update(); @@ -270,7 +298,7 @@ void Net_Mapvote() case MAPVOTE_NET_PIC: type = ReadByte(); mv_preview[type] = true; - //print(strcat("MAPVOTE_NET_PIC: ^2", ftos(type), "\n")); + mv_pics[type] = strzone(Net_ReadPicture()); break; } } diff --git a/data/qcsrc/client/sbar.qc b/data/qcsrc/client/sbar.qc index 09c7c049a..a88c3187f 100644 --- a/data/qcsrc/client/sbar.qc +++ b/data/qcsrc/client/sbar.qc @@ -168,7 +168,6 @@ float Sbar_TeamCmp(entity l, entity r) void Sbar_Init() { - entity tm; sortedPlayers = Sort_New(Sbar_PlayerCmp); sortedTeams = Sort_New(Sbar_TeamCmp); team1 = Sort_Next(sortedTeams); diff --git a/data/qcsrc/common/constants.qh b/data/qcsrc/common/constants.qh index d82e203a1..27c1dfc98 100644 --- a/data/qcsrc/common/constants.qh +++ b/data/qcsrc/common/constants.qh @@ -1,7 +1,8 @@ // COMMIT-TODO: Update if necessary before committing // Revision 1: additional statistics sent (flag caps, returns, deaths) // Revision 2: Mapvote preview pictures -#define CSQC_REVISION 2 +// Revision 3: optimized map vote protocol +#define CSQC_REVISION 3 // probably put these in common/ // so server/ and client/ can be synced better diff --git a/data/qcsrc/server/cl_client.qc b/data/qcsrc/server/cl_client.qc index 01ab1a073..d29ef380e 100644 --- a/data/qcsrc/server/cl_client.qc +++ b/data/qcsrc/server/cl_client.qc @@ -732,7 +732,7 @@ void SendCSQCInfo(void) WriteByte(MSG_ONE, SVC_TEMPENTITY); WriteByte(MSG_ONE, TE_CSQC_INIT); WriteShort(MSG_ONE, CSQC_REVISION); - WriteByte(MSG_ONE, maxclients-1); + WriteByte(MSG_ONE, maxclients); } /* diff --git a/data/qcsrc/server/g_world.qc b/data/qcsrc/server/g_world.qc index f6446a5f4..31402037a 100644 --- a/data/qcsrc/server/g_world.qc +++ b/data/qcsrc/server/g_world.qc @@ -175,6 +175,15 @@ void spawnfunc_worldspawn (void) error("world already spawned - you may have EXACTLY ONE worldspawn!"); world_already_spawned = TRUE; + local entity head; + head = nextent(world); + maxclients = 0; + while(head) + { + ++maxclients; + head = nextent(head); + } + if(GotoFirstMap()) return; @@ -262,15 +271,6 @@ void spawnfunc_worldspawn (void) //if (g_domination) // dom_init(); - local entity head; - head = nextent(world); - maxclients = 0; - while(head) - { - ++maxclients; - head = nextent(head); - } - GameLogInit(); // prepare everything if(cvar("sv_eventlog")) { @@ -1933,6 +1933,7 @@ float mapvote_votes[MAPVOTE_COUNT]; float mapvote_run; float mapvote_detail; float mapvote_abstain; +float mapvote_dirty; .float mapvote; void MapVote_ClearAllVotes() @@ -2062,12 +2063,10 @@ void MapVote_SendPicture(float id) { msg_entity = self; WriteByte(MSG_ONE, SVC_TEMPENTITY); - WriteByte(MSG_ONE, TE_CSQC_PICTURE); - WritePicture(MSG_ONE, strcat("maps/", mapvote_maps[id]), 1024); - WriteByte(MSG_ONE, SVC_TEMPENTITY); WriteByte(MSG_ONE, TE_CSQC_MAPVOTE); WriteByte(MSG_ONE, MAPVOTE_NET_PIC); WriteByte(MSG_ONE, id); + WritePicture(MSG_ONE, strcat("maps/", mapvote_maps[id]), 1024); } float GameCommand_MapVote(string cmd) @@ -2086,6 +2085,16 @@ float GameCommand_MapVote(string cmd) return FALSE; } +float MapVote_GetMapMask() +{ + float mask, i, power; + mask = 0; + for(i = 0, power = 1; i < mapvote_count; ++i, power *= 2) + if(mapvote_maps[i] != "") + mask |= power; + return mask; +} + void MapVote_SendData(float targ) { string mapfile; @@ -2093,21 +2102,24 @@ void MapVote_SendData(float targ) WriteByte(targ, SVC_TEMPENTITY); WriteByte(targ, TE_CSQC_MAPVOTE); WriteByte(targ, MAPVOTE_NET_INIT); - WriteByte(targ, mapvote_count); - WriteByte(targ, mapvote_abstain); - WriteByte(targ, mapvote_detail); - for(i = 0; i < mapvote_count; ++i) - { - WriteString(targ, mapvote_maps[i]); - mapfile = strcat("maps/", mapvote_maps[i], ".bsp"); - localcmd(strcat("\ncurl --pak ", whichpack(mapfile), "\n")); - mapfile = whichpack(mapfile); - for(o = strstr(mapfile, "/", 0)+1; o > 0; o = strstr(mapfile, "/", 0)+1) - mapfile = substring(mapfile, o, 999); - for(o = strstr(mapfile, "\\", 0)+1; o > 0; o = strstr(mapfile, "\\", 0)+1) - mapfile = substring(mapfile, o, 999); - WriteString(targ, mapfile); - } + + WriteByte(targ, mapvote_count); + WriteByte(targ, mapvote_abstain); + WriteByte(targ, mapvote_detail); + if(mapvote_count <= 8) + WriteByte(targ, MapVote_GetMapMask()); + else + WriteShort(targ, MapVote_GetMapMask()); + for(i = 0; i < mapvote_count; ++i) + if(mapvote_maps[i] != "") + { + WriteString(targ, mapvote_maps[i]); + mapfile = strcat("maps/", mapvote_maps[i], ".bsp"); + mapfile = whichpack(mapfile); + for(o = strstr(mapfile, "/", 0)+1; o > 0; o = strstr(mapfile, "/", 0)+1) + mapfile = substring(mapfile, o, 999); + WriteString(targ, mapfile); + } } void MapVote_UpdateData(float targ) @@ -2116,15 +2128,16 @@ void MapVote_UpdateData(float targ) WriteByte(targ, SVC_TEMPENTITY); WriteByte(targ, TE_CSQC_MAPVOTE); WriteByte(targ, MAPVOTE_NET_UPDATE); - for(i = 0; i < mapvote_count; ++i) - { - if(strlen(mapvote_maps[i]) <= 0) - WriteByte(targ, 0); - else - WriteByte(targ, 1); - WriteByte(targ, mapvote_votes[i]); - } + if(mapvote_count <= 8) + WriteByte(targ, MapVote_GetMapMask()); + else + WriteShort(targ, MapVote_GetMapMask()); + if(mapvote_detail) + for(i = 0; i < mapvote_count; ++i) + if(mapvote_maps[i] != "") + WriteByte(targ, mapvote_votes[i]); } + void MapVote_TellVote(float targ, float vote) { float i; @@ -2191,13 +2204,6 @@ void MapVote_CheckRules_1() mapvote_votes[i] = mapvote_votes[i] + 1; } } - - if(!cvar("g_maplist_textonly")) - { - MapVote_UpdateData(MSG_BROADCAST); - FOR_EACH_REALCLIENT(msg_entity) - MapVote_TellVote(MSG_ONE, msg_entity.mapvote); - } } float MapVote_CheckRules_2() @@ -2239,6 +2245,7 @@ float MapVote_CheckRules_2() if(time > mapvote_keeptwotime || (mapvote_voters_real - firstPlaceVotes - secondPlaceVotes) < secondPlaceVotes) { float didntvote; + mapvote_dirty = TRUE; mapvote_message = "Now decide between the TOP TWO!"; mapvote_keeptwotime = 0; result = strcat(":vote:keeptwo:", mapvote_maps[firstPlace]); @@ -2292,7 +2299,9 @@ void MapVote_Tick() other.impulse = 0; if(clienttype(other) == CLIENTTYPE_REAL) { - stuffcmd(other, "\nin_bind 7 1 \"impulse 1\"; in_bind 7 2 \"impulse 2\"; in_bind 7 3 \"impulse 3\"; in_bind 7 4 \"impulse 4\"; in_bind 7 5 \"impulse 5\"; in_bind 7 6 \"impulse 6\"; in_bind 7 7 \"impulse 7\"; in_bind 7 8 \"impulse 8\"; in_bind 7 9 \"impulse 9\"; in_bind 7 0 \"impulse 10\"; in_bind 7 KP_1 \"impulse 1\"; in_bind 7 KP_2 \"impulse 2\"; in_bind 7 KP_3 \"impulse 3\"; in_bind 7 KP_4 \"impulse 4\"; in_bind 7 KP_5 \"impulse 5\"; in_bind 7 KP_6 \"impulse 6\"; in_bind 7 KP_7 \"impulse 7\"; in_bind 7 KP_8 \"impulse 8\"; in_bind 7 KP_9 \"impulse 9\"; in_bind 7 KP_0 \"impulse 10\"; in_bindmap 7 0\n"); + if(cvar("g_maplist_textonly")) + stuffcmd(other, "\nin_bind 7 1 \"impulse 1\"; in_bind 7 2 \"impulse 2\"; in_bind 7 3 \"impulse 3\"; in_bind 7 4 \"impulse 4\"; in_bind 7 5 \"impulse 5\"; in_bind 7 6 \"impulse 6\"; in_bind 7 7 \"impulse 7\"; in_bind 7 8 \"impulse 8\"; in_bind 7 9 \"impulse 9\"; in_bind 7 0 \"impulse 10\"; in_bind 7 KP_1 \"impulse 1\"; in_bind 7 KP_2 \"impulse 2\"; in_bind 7 KP_3 \"impulse 3\"; in_bind 7 KP_4 \"impulse 4\"; in_bind 7 KP_5 \"impulse 5\"; in_bind 7 KP_6 \"impulse 6\"; in_bind 7 KP_7 \"impulse 7\"; in_bind 7 KP_8 \"impulse 8\"; in_bind 7 KP_9 \"impulse 9\"; in_bind 7 KP_0 \"impulse 10\"; in_bindmap 7 0\n"); + msg_entity = other; WriteByte(MSG_ONE, SVC_FINALE); WriteString(MSG_ONE, ""); @@ -2309,7 +2318,14 @@ void MapVote_Tick() // use impulses as new vote if(other.impulse >= 1 && other.impulse <= mapvote_count) if(mapvote_maps[other.impulse - 1] != "") + { other.mapvote = other.impulse; + if(mapvote_detail) + mapvote_dirty = TRUE; + + msg_entity = other; + MapVote_TellVote(MSG_ONE, other.mapvote); + } other.impulse = 0; if(other.mapvote) @@ -2318,6 +2334,13 @@ void MapVote_Tick() MapVote_CheckRules_1(); // just count + if(!cvar("g_maplist_textonly")) + if(mapvote_dirty) // 1 if "keeptwo" or "impulse" happened before + { + MapVote_UpdateData(MSG_BROADCAST); + mapvote_dirty = FALSE; + } + if(cvar("g_maplist_textonly")) { FOR_EACH_REALCLIENT(other) -- 2.39.2