// // IntQryBuildInformation() // // Protocol building routine, the passed parameter is the enquirer version static void IntQryBuildInformation(const DWORD &EqProtocolVersion, const DWORD &EqTime) { std::vector<CvarField_t> Cvars; // bond - time MSG_WriteLong(&ml_message, EqTime); // The servers real protocol version // bond - real protocol MSG_WriteLong(&ml_message, PROTOCOL_VERSION); // Built revision of server MSG_WriteLong(&ml_message, last_revision); cvar_t *var = GetFirstCvar(); // Count our cvars and add them while (var) { if (var->flags() & CVAR_SERVERINFO) { CvarField.Name = var->name(); CvarField.Value = var->cstring(); Cvars.push_back(CvarField); } var = var->GetNext(); } // Cvar count MSG_WriteByte(&ml_message, (BYTE)Cvars.size()); // Write cvars for (size_t i = 0; i < Cvars.size(); ++i) { MSG_WriteString(&ml_message, Cvars[i].Name.c_str()); MSG_WriteString(&ml_message, Cvars[i].Value.c_str()); } MSG_WriteString(&ml_message, (strlen(join_password.cstring()) ? MD5SUM(join_password.cstring()).c_str() : "")); MSG_WriteString(&ml_message, level.mapname); int timeleft = (int)(sv_timelimit - level.time/(TICRATE*60)); if (timeleft < 0) timeleft = 0; MSG_WriteShort(&ml_message, timeleft); // Team data MSG_WriteByte(&ml_message, 2); // Blue MSG_WriteString(&ml_message, "Blue"); MSG_WriteLong(&ml_message, 0x000000FF); MSG_WriteShort(&ml_message, (short)TEAMpoints[it_blueflag]); MSG_WriteString(&ml_message, "Red"); MSG_WriteLong(&ml_message, 0x00FF0000); MSG_WriteShort(&ml_message, (short)TEAMpoints[it_redflag]); // TODO: When real dynamic teams are implemented //byte TeamCount = (byte)sv_teamsinplay; //MSG_WriteByte(&ml_message, TeamCount); //for (byte i = 0; i < TeamCount; ++i) //{ // TODO - Figure out where the info resides //MSG_WriteString(&ml_message, ""); //MSG_WriteLong(&ml_message, 0); //MSG_WriteShort(&ml_message, TEAMpoints[i]); //} // Patch files MSG_WriteByte(&ml_message, patchfiles.size()); for (size_t i = 0; i < patchfiles.size(); ++i) { MSG_WriteString(&ml_message, patchfiles[i].c_str()); } // Wad files MSG_WriteByte(&ml_message, wadnames.size()); for (size_t i = 0; i < wadnames.size(); ++i) { MSG_WriteString(&ml_message, wadnames[i].c_str()); MSG_WriteString(&ml_message, wadhashes[i].c_str()); } MSG_WriteByte(&ml_message, players.size()); // Player info for (size_t i = 0; i < players.size(); ++i) { MSG_WriteString(&ml_message, players[i].userinfo.netname); MSG_WriteByte(&ml_message, players[i].userinfo.team); MSG_WriteShort(&ml_message, players[i].ping); int timeingame = (time(NULL) - players[i].JoinTime)/60; if (timeingame < 0) timeingame = 0; MSG_WriteShort(&ml_message, timeingame); // FIXME - Treat non-players (downloaders/others) as spectators too for // now bool spectator; spectator = (players[i].spectator || ((players[i].playerstate != PST_LIVE) && (players[i].playerstate != PST_DEAD) && (players[i].playerstate != PST_REBORN))); MSG_WriteBool(&ml_message, spectator); MSG_WriteShort(&ml_message, players[i].fragcount); MSG_WriteShort(&ml_message, players[i].killcount); MSG_WriteShort(&ml_message, players[i].deathcount); } }
void NetDemo::writeLauncherSequence(buf_t *netbuffer) { cvar_t *var = NULL, *prev_cvar = NULL; // Server sends launcher info MSG_WriteLong (netbuffer, CHALLENGE); MSG_WriteLong (netbuffer, 0); // server_token // get sv_hostname and write it var = cvar_t::FindCVar("sv_hostname", &prev_cvar); MSG_WriteString (netbuffer, server_host.c_str()); int playersingame = 0; for (size_t i = 0; i < players.size(); i++) { if (players[i].ingame()) playersingame++; } MSG_WriteByte (netbuffer, playersingame); MSG_WriteByte (netbuffer, 0); // sv_maxclients MSG_WriteString (netbuffer, level.mapname); // names of all the wadfiles on the server size_t numwads = wadfiles.size(); if (numwads > 0xff) numwads = 0xff; MSG_WriteByte (netbuffer, numwads - 1); for (size_t n = 1; n < numwads; n++) { std::string tmpname = wadfiles[n]; // strip absolute paths, as they present a security risk FixPathSeparator(tmpname); size_t slash = tmpname.find_last_of(PATHSEPCHAR); if (slash != std::string::npos) tmpname = tmpname.substr(slash + 1, tmpname.length() - slash); MSG_WriteString (netbuffer, tmpname.c_str()); } MSG_WriteBool (netbuffer, 0); // deathmatch? MSG_WriteByte (netbuffer, 0); // sv_skill MSG_WriteBool (netbuffer, (sv_gametype == GM_TEAMDM)); MSG_WriteBool (netbuffer, (sv_gametype == GM_CTF)); for (size_t i = 0; i < players.size(); i++) { // Notes: client just ignores this data but still expects to parse it if (players[i].ingame()) { MSG_WriteString (netbuffer, ""); // player's netname MSG_WriteShort (netbuffer, 0); // player's fragcount MSG_WriteLong (netbuffer, 0); // player's ping MSG_WriteByte (netbuffer, 0); // player's team } } // MD5 hash sums for all the wadfiles on the server for (size_t n = 1; n < numwads; n++) MSG_WriteString (netbuffer, wadhashes[n].c_str()); MSG_WriteString (netbuffer, ""); // sv_website.cstring() if (sv_gametype == GM_TEAMDM || sv_gametype == GM_CTF) { MSG_WriteLong (netbuffer, 0); // sv_scorelimit for (size_t n = 0; n < NUMTEAMS; n++) { MSG_WriteBool (netbuffer, false); } } MSG_WriteShort (netbuffer, VERSION); // Note: these are ignored by clients when the client connects anyway // so they don't need real data MSG_WriteString (netbuffer, ""); // sv_email.cstring() MSG_WriteShort (netbuffer, 0); // sv_timelimit MSG_WriteShort (netbuffer, 0); // timeleft before end of level MSG_WriteShort (netbuffer, 0); // sv_fraglimit MSG_WriteBool (netbuffer, false); // sv_itemrespawn MSG_WriteBool (netbuffer, false); // sv_weaponstay MSG_WriteBool (netbuffer, false); // sv_friendlyfire MSG_WriteBool (netbuffer, false); // sv_allowexit MSG_WriteBool (netbuffer, false); // sv_infiniteammo MSG_WriteBool (netbuffer, false); // sv_nomonsters MSG_WriteBool (netbuffer, false); // sv_monstersrespawn MSG_WriteBool (netbuffer, false); // sv_fastmonsters MSG_WriteBool (netbuffer, false); // sv_allowjump MSG_WriteBool (netbuffer, false); // sv_freelook MSG_WriteBool (netbuffer, false); // sv_waddownload MSG_WriteBool (netbuffer, false); // sv_emptyreset MSG_WriteBool (netbuffer, false); // sv_cleanmaps MSG_WriteBool (netbuffer, false); // sv_fragexitswitch for (size_t i = 0; i < players.size(); i++) { if (players[i].ingame()) { MSG_WriteShort (netbuffer, players[i].killcount); MSG_WriteShort (netbuffer, players[i].deathcount); int timeingame = (time(NULL) - players[i].JoinTime)/60; if (timeingame < 0) timeingame = 0; MSG_WriteShort (netbuffer, timeingame); } } MSG_WriteLong(netbuffer, (DWORD)0x01020304); MSG_WriteShort(netbuffer, sv_maxplayers); for (size_t i = 0; i < players.size(); i++) { if (players[i].ingame()) MSG_WriteBool (netbuffer, players[i].spectator); } MSG_WriteLong (netbuffer, (DWORD)0x01020305); MSG_WriteShort (netbuffer, 0); // join_passowrd MSG_WriteLong (netbuffer, GAMEVER); // TODO: handle patch files MSG_WriteByte (netbuffer, 0); // patchfiles.size() // MSG_WriteByte (netbuffer, patchfiles.size()); // for (size_t n = 0; n < patchfiles.size(); n++) // MSG_WriteString(netbuffer, patchfiles[n].c_str()); }
// // SV_SendServerInfo // // Sends server info to a launcher // TODO: Clean up and reinvent. void SV_SendServerInfo() { size_t i; SZ_Clear(&ml_message); MSG_WriteLong(&ml_message, CHALLENGE); MSG_WriteLong(&ml_message, SV_NewToken()); // if master wants a key to be presented, present it we will if(MSG_BytesLeft() == 4) MSG_WriteLong(&ml_message, MSG_ReadLong()); MSG_WriteString(&ml_message, (char *)sv_hostname.cstring()); byte playersingame = 0; for (Players::iterator it = players.begin();it != players.end();++it) { if (it->ingame()) playersingame++; } MSG_WriteByte(&ml_message, playersingame); MSG_WriteByte(&ml_message, sv_maxclients.asInt()); MSG_WriteString(&ml_message, level.mapname); size_t numwads = wadfiles.size(); if(numwads > 0xff)numwads = 0xff; MSG_WriteByte(&ml_message, numwads - 1); for (i = 1; i < numwads; ++i) MSG_WriteString(&ml_message, D_CleanseFileName(wadfiles[i], "wad").c_str()); MSG_WriteBool(&ml_message, (sv_gametype == GM_DM || sv_gametype == GM_TEAMDM)); MSG_WriteByte(&ml_message, sv_skill.asInt()); MSG_WriteBool(&ml_message, (sv_gametype == GM_TEAMDM)); MSG_WriteBool(&ml_message, (sv_gametype == GM_CTF)); for (Players::iterator it = players.begin();it != players.end();++it) { if (it->ingame()) { MSG_WriteString(&ml_message, it->userinfo.netname.c_str()); MSG_WriteShort(&ml_message, it->fragcount); MSG_WriteLong(&ml_message, it->ping); if (sv_gametype == GM_TEAMDM || sv_gametype == GM_CTF) MSG_WriteByte(&ml_message, it->userinfo.team); else MSG_WriteByte(&ml_message, TEAM_NONE); } } for (i = 1; i < numwads; ++i) MSG_WriteString(&ml_message, wadhashes[i].c_str()); MSG_WriteString(&ml_message, sv_website.cstring()); if (sv_gametype == GM_TEAMDM || sv_gametype == GM_CTF) { MSG_WriteLong(&ml_message, sv_scorelimit.asInt()); for(size_t i = 0; i < NUMTEAMS; i++) { if ((sv_gametype == GM_CTF && i < 2) || (sv_gametype != GM_CTF && i < sv_teamsinplay)) { MSG_WriteByte(&ml_message, 1); MSG_WriteLong(&ml_message, TEAMpoints[i]); } else { MSG_WriteByte(&ml_message, 0); } } } MSG_WriteShort(&ml_message, VERSION); //bond=========================== MSG_WriteString(&ml_message, (char *)sv_email.cstring()); int timeleft = (int)(sv_timelimit - level.time/(TICRATE*60)); if (timeleft<0) timeleft=0; MSG_WriteShort(&ml_message,sv_timelimit.asInt()); MSG_WriteShort(&ml_message,timeleft); MSG_WriteShort(&ml_message,sv_fraglimit.asInt()); MSG_WriteBool(&ml_message, (sv_itemsrespawn ? true : false)); MSG_WriteBool(&ml_message, (sv_weaponstay ? true : false)); MSG_WriteBool(&ml_message, (sv_friendlyfire ? true : false)); MSG_WriteBool(&ml_message, (sv_allowexit ? true : false)); MSG_WriteBool(&ml_message, (sv_infiniteammo ? true : false)); MSG_WriteBool(&ml_message, (sv_nomonsters ? true : false)); MSG_WriteBool(&ml_message, (sv_monstersrespawn ? true : false)); MSG_WriteBool(&ml_message, (sv_fastmonsters ? true : false)); MSG_WriteBool(&ml_message, (sv_allowjump ? true : false)); MSG_WriteBool(&ml_message, (sv_freelook ? true : false)); MSG_WriteBool(&ml_message, (sv_waddownload ? true : false)); MSG_WriteBool(&ml_message, (sv_emptyreset ? true : false)); MSG_WriteBool(&ml_message, false); // used to be sv_cleanmaps MSG_WriteBool(&ml_message, (sv_fragexitswitch ? true : false)); for (Players::iterator it = players.begin();it != players.end();++it) { if (it->ingame()) { MSG_WriteShort(&ml_message, it->killcount); MSG_WriteShort(&ml_message, it->deathcount); int timeingame = (time(NULL) - it->JoinTime)/60; if (timeingame<0) timeingame=0; MSG_WriteShort(&ml_message, timeingame); } } //bond=========================== MSG_WriteLong(&ml_message, (DWORD)0x01020304); MSG_WriteShort(&ml_message, sv_maxplayers.asInt()); for (Players::iterator it = players.begin();it != players.end();++it) { if (it->ingame()) { MSG_WriteBool(&ml_message, (it->spectator ? true : false)); } } MSG_WriteLong(&ml_message, (DWORD)0x01020305); MSG_WriteShort(&ml_message, strlen(join_password.cstring()) ? 1 : 0); // GhostlyDeath -- Send Game Version info MSG_WriteLong(&ml_message, GAMEVER); MSG_WriteByte(&ml_message, patchfiles.size()); for (size_t i = 0; i < patchfiles.size(); ++i) MSG_WriteString(&ml_message, D_CleanseFileName(patchfiles[i]).c_str()); NET_SendPacket(ml_message, net_from); }