From 933b9f0e0b183d6fd56f2d55c846beecdb11e7de Mon Sep 17 00:00:00 2001 From: JustinAJ Date: Tue, 2 Sep 2014 19:04:41 -0400 Subject: [PATCH] Moved data processing from RenX::Core to RenX::Server. Added line preservation. --- Release/Bot.lib | Bin 19582 -> 19582 bytes Release/Plugins/RenX.Core.lib | Bin 51654 -> 52542 bytes RenX.Core/RenX_Core.cpp | 459 +--------------------------------- RenX.Core/RenX_Core.h | 2 +- RenX.Core/RenX_Server.cpp | 459 +++++++++++++++++++++++++++++++++- RenX.Core/RenX_Server.h | 23 +- 6 files changed, 484 insertions(+), 459 deletions(-) diff --git a/Release/Bot.lib b/Release/Bot.lib index 8c360257fc1274990a7618a5731fe0f5b453cd87..1ff74ab6f4691161851bd57b1cd7aab8d941941f 100644 GIT binary patch delta 1670 zcmZuxOH30%7~VpGMIJWx#VeH30H)A|K4`lwZ5IlCEG5N=@uEoyF~+Fi0S^+4kQfgJ zq4B>EHJ&{|2zoH#;!#3Ohz@Jww^p-P5Cj9940pf{Z#PAYRwNrS zYYZ1+)Ih>(gK~oiKS#PKtK@g<#u2Yfe`2XML@IvpMk%1A>|pQ_pv`xa0$B0NXKupX z_oHI<57mwZJ_f z?`GVC6ZOy}7zJ2&w!=k$9d$I#Dba*A)W zK|Qw{DKDek&UP0Pics>JDUX}zP>4+wpPlC+lIC5ArNPciVKON(oTXMA@S+O9HO?vu zqs-U1C6gM<@&dKO#m_51bL2J!=r-O**otuBiwNn+6s_)vOlC96W{TN=qJ({EY=(N{ zGxT_j02^a@4!EcQrq~S%;5H8?NdIqQcQ~LcZqfFZM$_*W>I6_~5^x}k@L92N#E)^} za1@{C05xIJF3B`<=z(X73kp|U@H@>`UrLaG99*W0D_l>y#d34i$6bAfJ4#5v~nr5M|MPZt~7HGFxIK0~+ V3b$tNd!1uz!xvc25wqEx^bg+My=wpf delta 1670 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 diff --git a/RenX.Core/RenX_Core.cpp b/RenX.Core/RenX_Core.cpp index d47bc05..b9c6b99 100644 --- a/RenX.Core/RenX_Core.cpp +++ b/RenX.Core/RenX_Core.cpp @@ -146,463 +146,14 @@ int RenX::Core::addCommand(RenX::GameCommand *command) return RenX::Core::servers.size(); } -// This shouldn't be needed later. -/*#define PARSE_PLAYER_DATA(STRING, OFFSET) \ - char *name = nullptr; int id; char team; \ - const char *p = strstr(buff, STRING); \ - if (p - buff - OFFSET < 12) { } \ - team = *(p - 3); \ - if (*(p - 9) == '<') id = atoi(p - 8); \ - else id = atoi(p - 9); \ - name = charToChar(buff + OFFSET + 1, 0, (int)(p - 10 - (buff + OFFSET + 1)));*/ - -#define PARSE_PLAYER_DATA() \ - Jupiter::ReferenceString name; \ - TeamType team; \ - int id; \ - bool isBot = false; { \ - Jupiter::ReferenceString idToken; \ - if (playerData[0] == ',') { \ - name = playerData.gotoWord(1, ","); \ - idToken = playerData.getWord(0, ","); \ - team = Other; \ - } else { \ - name = playerData.gotoWord(2, ","); \ - idToken = playerData.getWord(1, ","); \ - team = RenX::getTeam(playerData[0]); \ - } \ - if (idToken[0] == 'b') { idToken.shiftRight(1); isBot = true; } \ - id = idToken.asInt(10); } \ - RenX::PlayerInfo *player = getPlayerOrAdd(server, name, id, team, isBot); - -inline RenX::PlayerInfo *getPlayerOrAdd(RenX::Server *server, const Jupiter::ReadableString &name, int id, RenX::TeamType team, bool isBot) -{ - RenX::PlayerInfo *r = server->getPlayer(id); - if (r == nullptr) - { - r = new RenX::PlayerInfo(); - r->id = id; - r->name = name; - r->isBot = isBot; - r->joinTime = time(nullptr); - if (id != 0) server->players.add(r); - } - else if (r->name.size() == 0) r->name = name; - r->team = team; - return r; -} - -inline void onPreGameOver(RenX::Server *server, RenX::WinType winType, RenX::TeamType team, int gScore, int nScore) -{ - RenX::PlayerInfo *player; - - if (server->players.size() != 0) - { - for (Jupiter::DLList::Node *n = server->players.getNode(0); n != nullptr; n = n->next) - { - player = n->data; - if (player != nullptr) - { - if (player->team == team) - player->wins++; - else player->loses++; - } - } - } -} - -inline void onPostGameOver(RenX::Server *server, RenX::WinType winType, RenX::TeamType team, int gScore, int nScore) -{ - RenX::PlayerInfo *player; - - if (server->players.size() != 0) - { - for (Jupiter::DLList::Node *n = server->players.getNode(0); n != nullptr; n = n->next) - { - player = n->data; - if (player != nullptr) - { - player->kills = 0; - player->deaths = 0; - player->suicides = 0; - player->headshots = 0; - player->vehicleKills = 0; - player->buildingKills = 0; - player->defenceKills = 0; - } - } - } -} - -inline void onChat(RenX::Server *server, RenX::PlayerInfo *player, const Jupiter::ReadableString &message, bool isPublic) -{ - const Jupiter::ReadableString &prefix = server->getCommandPrefix(); - if (message.find(prefix) == 0 && message.size() != prefix.size()) - { - Jupiter::ReferenceString command; - Jupiter::ReferenceString parameters; - if (containsSymbol(WHITESPACE, message.get(prefix.size()))) - { - command = Jupiter::ReferenceString::getWord(message, 1, WHITESPACE); - parameters = Jupiter::ReferenceString::gotoWord(message, 2, WHITESPACE); - } - else - { - command = Jupiter::ReferenceString::getWord(message, 0, WHITESPACE); - command.shiftRight(prefix.size()); - parameters = Jupiter::ReferenceString::gotoWord(message, 1, WHITESPACE); - } - server->triggerCommand(command, player, parameters); - } -} - int RenX::Core::think() { - // Change this later to just call server->think(). - RenX::Server *server; - for (size_t a = 0; a < RenX::Core::servers.size(); a++) - { - server = RenX::Core::servers.get(a); - if (server->isConnected() == false) - { - if (time(0) >= server->getLastAttempt() + server->getDelay()) - { - if (server->connect()) server->sendLogChan(IRCCOLOR "03[RenX]" IRCCOLOR " Socket successfully reconnected to Renegade-X server."); - else server->sendLogChan(IRCCOLOR "04[Error]" IRCCOLOR " Failed to reconnect to Renegade-X server."); - } - } - else - { - if (server->sock.recv() > 0) - { - Jupiter::ReferenceString buffer = server->sock.getBuffer(); - unsigned int totalLines = buffer.wordCount(ENDL); - for (unsigned int currentLine = 0; currentLine != totalLines; currentLine++) - { - Jupiter::ReferenceString buff = buffer.getWord(currentLine, ENDL); - Jupiter::ReferenceString header = buff.getWord(0, RenX::DelimS); - Jupiter::ReferenceString playerData = buff.getWord(1, RenX::DelimS); - Jupiter::ReferenceString action = buff.getWord(2, RenX::DelimS); - - //printf("[RenX Dump] %.*s - %.*s - %.*s" ENDL, header.size(), header.ptr(), playerData.size(), playerData.ptr(), action.size(), action.ptr()); + size_t a = 0; + while (a < RenX::Core::servers.size()) + if (RenX::Core::servers.get(a)->think() != 0) + delete RenX::Core::servers.remove(a); + else a++; - if (buff.size() != 0) - { - switch (header[0]) - { - case 'l': - if (header.equals("lGAME:")) - { - if (action.equals("deployed")) - { - PARSE_PLAYER_DATA(); - Jupiter::ReferenceString objectType = buff.getWord(3, RenX::DelimS); - if (objectType.match("*Beacon")) player->beaconPlacements++; - for (size_t i = 0; i < RenX::Core::plugins.size(); i++) - RenX::Core::plugins.get(i)->RenX_OnDeploy(server, player, objectType); - } - else if (action.equals("suicided by")) - { - PARSE_PLAYER_DATA(); - player->deaths++; - player->suicides++; - Jupiter::ReferenceString damageType = buff.getWord(3, RenX::DelimS); - for (size_t i = 0; i < RenX::Core::plugins.size(); i++) - RenX::Core::plugins.get(i)->RenX_OnSuicide(server, player, damageType); - } - else if (action.equals("killed")) - { - PARSE_PLAYER_DATA(); - Jupiter::ReferenceString victimData = buff.getWord(3, RenX::DelimS); - Jupiter::ReferenceString vname = victimData.getWord(2, ","); - Jupiter::ReferenceString vidToken = victimData.getWord(1, ","); - int vid; - bool visBot = false; - if (vidToken[0] == 'b') - { - vidToken.shiftRight(1); - visBot = true; - } - vid = vidToken.asInt(10); - TeamType vteam = RenX::getTeam(victimData.getWord(0, ",")[0]); - Jupiter::ReferenceString damageType = buff.getWord(5, RenX::DelimS); - RenX::PlayerInfo *victim = getPlayerOrAdd(server, vname, vid, vteam, visBot); - player->kills++; - if (damageType.equals("Rx_DmgType_Headshot")) player->headshots++; - victim->deaths++; - - if (server->needsCList) - { - server->sendData(STRING_LITERAL_AS_REFERENCE("clogclientlist\n")); - server->needsCList = false; - } - - for (size_t i = 0; i < RenX::Core::plugins.size(); i++) - RenX::Core::plugins.get(i)->RenX_OnKill(server, player, victim, damageType); - } - else if (action.match("died by")) - { - PARSE_PLAYER_DATA(); - player->deaths++; - Jupiter::ReferenceString damageType = buff.getWord(3, RenX::DelimS); - for (size_t i = 0; i < RenX::Core::plugins.size(); i++) - RenX::Core::plugins.get(i)->RenX_OnDie(server, player, damageType); - } - else if (action.match("destroyed*")) - { - PARSE_PLAYER_DATA(); - Jupiter::ReferenceString victim = buff.getWord(3, RenX::DelimS); - Jupiter::ReferenceString damageType = buff.getWord(5, RenX::DelimS); - ObjectType type; - if (action.equals("destroyed building")) - { - type = Building; - player->buildingKills++; - } - else if (victim.match("Rx_Defence_*")) - { - type = Defence; - player->defenceKills++; - } - else - { - type = Vehicle; - player->vehicleKills++; - } - for (size_t i = 0; i < RenX::Core::plugins.size(); i++) - RenX::Core::plugins.get(i)->RenX_OnDestroy(server, player, victim, damageType, type); - } - else if (playerData.match("??? wins (*)")) - { - TeamType team = RenX::getTeam(playerData[0]); - int gScore = buff.getWord(2, RenX::DelimS).gotoWord(1, "=").asInt(10); - int nScore = buff.getWord(3, RenX::DelimS).gotoWord(1, "=").asInt(10); - Jupiter::ReferenceString winType = Jupiter::ReferenceString::substring(playerData, 10); - winType.truncate(1); - WinType iWinType = Unknown; - if (gScore == nScore) - iWinType = Tie; - else if (winType.equals("TimeLimit")) - iWinType = Score; - else if (winType.equals("Buildings")) - iWinType = Base; - - server->needsCList = true; - onPreGameOver(server, iWinType, team, gScore, nScore); - for (size_t i = 0; i < RenX::Core::plugins.size(); i++) - RenX::Core::plugins.get(i)->RenX_OnGameOver(server, iWinType, team, gScore, nScore); - onPostGameOver(server, iWinType, team, gScore, nScore); - } - else if (playerData.equals("Tie")) - { - int gScore = action.gotoWord(1, "=").asInt(10); - int nScore = buff.getWord(3, RenX::DelimS).gotoWord(1, "=").asInt(10); - - server->needsCList = true; - if (gScore == nScore) - { - onPreGameOver(server, Tie, Other, gScore, nScore); - for (size_t i = 0; i < RenX::Core::plugins.size(); i++) - RenX::Core::plugins.get(i)->RenX_OnGameOver(server, Tie, Other, gScore, nScore); - onPostGameOver(server, Tie, Other, gScore, nScore); - } - else - { - TeamType winTeam = gScore > nScore ? RenX::getTeam('G') : RenX::getTeam('N'); - onPreGameOver(server, Shutdown, winTeam, gScore, nScore); - for (size_t i = 0; i < RenX::Core::plugins.size(); i++) - RenX::Core::plugins.get(i)->RenX_OnGameOver(server, Shutdown, winTeam, gScore, nScore); - onPostGameOver(server, Shutdown, winTeam, gScore, nScore); - } - } - else for (size_t i = 0; i < RenX::Core::plugins.size(); i++) - RenX::Core::plugins.get(i)->RenX_OnGame(server, buff.gotoWord(1, RenX::DelimS)); - } - else if (header.equals("lCHAT:")) - { - if (action.equals("teamsay:")) - { - PARSE_PLAYER_DATA(); - Jupiter::ReferenceString message = buff.getWord(3, RenX::DelimS); - onChat(server, player, message, false); - for (size_t i = 0; i < RenX::Core::plugins.size(); i++) - RenX::Core::plugins.get(i)->RenX_OnTeamChat(server, player, message); - } - else if (action.equals("say:")) - { - PARSE_PLAYER_DATA(); - Jupiter::ReferenceString message = buff.getWord(3, RenX::DelimS); - onChat(server, player, message, true); - for (size_t i = 0; i < RenX::Core::plugins.size(); i++) - RenX::Core::plugins.get(i)->RenX_OnChat(server, player, message); - } - } - else if (header.equals("lPLAYER:")) - { - PARSE_PLAYER_DATA(); - if (action.equals("disconnected")) - { - for (size_t i = 0; i < RenX::Core::plugins.size(); i++) - RenX::Core::plugins.get(i)->RenX_OnPart(server, player); - server->removePlayer(player); - player = nullptr; - } - else if (action.equals("entered from")) - { - player->ip = buff.getWord(3, RenX::DelimS); - if (buff.getWord(4, RenX::DelimS).equals("steamid")) player->steamid = buff.getWord(5, RenX::DelimS); - for (size_t i = 0; i < RenX::Core::plugins.size(); i++) - RenX::Core::plugins.get(i)->RenX_OnJoin(server, player); - } - else if (action.equals("changed name to:")) - { - Jupiter::ReferenceString newName = buff.getWord(3, RenX::DelimS); - for (size_t i = 0; i < RenX::Core::plugins.size(); i++) - RenX::Core::plugins.get(i)->RenX_OnNameChange(server, player, newName); - player->name = newName; - } - } - else if (header.equals("lRCON:")) - { - if (action.equals("executed:")) - { - Jupiter::ReferenceString command = buff.getWord(3, RenX::DelimS); - for (size_t i = 0; i < RenX::Core::plugins.size(); i++) - RenX::Core::plugins.get(i)->RenX_OnExecute(server, playerData, command); - } - else if (action.equals("subscribed")) for (size_t i = 0; i < RenX::Core::plugins.size(); i++) - RenX::Core::plugins.get(i)->RenX_OnSubscribe(server, playerData); - else for (size_t i = 0; i < RenX::Core::plugins.size(); i++) - RenX::Core::plugins.get(i)->RenX_OnRCON(server, buff.gotoWord(1, RenX::DelimS)); - } - else if (header.equals("lADMIN:")) - { - PARSE_PLAYER_DATA(); - if (action.equals("logged in as")) - { - player->adminType = buff.getWord(3, RenX::DelimS); - for (size_t i = 0; i < RenX::Core::plugins.size(); i++) - RenX::Core::plugins.get(i)->RenX_OnAdminLogin(server, player); - } - else if (action.equals("logged out of")) - { - Jupiter::ReferenceString type = buff.getWord(3, RenX::DelimS); - for (size_t i = 0; i < RenX::Core::plugins.size(); i++) - RenX::Core::plugins.get(i)->RenX_OnAdminLogout(server, player); - player->adminType = ""; - } - else for (size_t i = 0; i < RenX::Core::plugins.size(); i++) - RenX::Core::plugins.get(i)->RenX_OnAdmin(server, buff.gotoWord(1, RenX::DelimS)); - } - else if (header.equals("lC-LIST:")) - { - // ID IP SteamID Team Name - if (playerData.isEmpty()) - break; - - int id; - bool isBot = false; - if (playerData.get(0) == 'b') - { - isBot = true; - playerData.shiftRight(1); - id = playerData.asInt(10); - playerData.shiftLeft(1); - } - else id = playerData.asInt(10); - Jupiter::ReferenceString ip = playerData.getWord(1, WHITESPACE); - Jupiter::ReferenceString steamid = playerData.getWord(2, WHITESPACE); - RenX::TeamType team; - Jupiter::ReferenceString name; - if (steamid.equals("-----NO")) // RCONv2-2a - { - steamid = ""; - Jupiter::ReferenceString &teamToken = playerData.getWord(4, WHITESPACE); - if (teamToken.isEmpty()) - break; - team = getTeam(teamToken.get(0)); - name = playerData.gotoWord(5, WHITESPACE); - } - else - { - if (steamid.equals("-----NO-STEAM-----")) // RCONv2-2.5a - steamid = ""; - Jupiter::ReferenceString &teamToken = playerData.getWord(3, WHITESPACE); - if (teamToken.isEmpty()) - break; - team = getTeam(teamToken.get(0)); - name = playerData.gotoWord(4, WHITESPACE); - } - - RenX::PlayerInfo *player = getPlayerOrAdd(server, name, id, team, isBot); - if (player->ip.size() == 0) - { - player->ip = ip; - player->steamid = steamid; - } - } - else - { - buff.shiftRight(1); - for (size_t i = 0; i < RenX::Core::plugins.size(); i++) - RenX::Core::plugins.get(i)->RenX_OnLog(server, buff); - buff.shiftLeft(1); - } - break; - - case 'c': - buff.shiftRight(1); - for (size_t i = 0; i < RenX::Core::plugins.size(); i++) - RenX::Core::plugins.get(i)->RenX_OnCommand(server, buff); - buff.shiftLeft(1); - break; - - case 'e': - buff.shiftRight(1); - for (size_t i = 0; i < RenX::Core::plugins.size(); i++) - RenX::Core::plugins.get(i)->RenX_OnError(server, buff); - buff.shiftLeft(1); - break; - - case 'v': - buff.shiftRight(1); - server->rconVersion = buff.asInt(10); - server->gameVersion = buff.substring(3); - for (size_t i = 0; i < RenX::Core::plugins.size(); i++) - RenX::Core::plugins.get(i)->RenX_OnVersion(server, buff); - buff.shiftLeft(1); - break; - - case 'a': - buff.shiftRight(1); - for (size_t i = 0; i < RenX::Core::plugins.size(); i++) - RenX::Core::plugins.get(i)->RenX_OnAuthorized(server, buff); - buff.shiftLeft(1); - break; - - default: - buff.shiftRight(1); - for (size_t i = 0; i < RenX::Core::plugins.size(); i++) - RenX::Core::plugins.get(i)->RenX_OnOther(server, header[0], buff); - buff.shiftLeft(1); - break; - } - for (size_t i = 0; i < RenX::Core::plugins.size(); i++) - RenX::Core::plugins.get(i)->RenX_OnRaw(server, buff); - } - } - } - else if (Jupiter::Socket::getLastError() != 10035) // This is a serious error - { - if (server->reconnect()) server->sendLogChan(IRCCOLOR "07[Warning]" IRCCOLOR " Connection lost to Renegade-X server lost. Reconnection attempt in progress."); - else - { - server->wipeData(); - server->sendLogChan(IRCCOLOR "04[Error]" IRCCOLOR " Connection lost to Renegade-X server lost. Reconnection attempt failed."); - } - } - } - } return Jupiter::Plugin::think(); } diff --git a/RenX.Core/RenX_Core.h b/RenX.Core/RenX_Core.h index 67f481d..cdbd674 100644 --- a/RenX.Core/RenX_Core.h +++ b/RenX.Core/RenX_Core.h @@ -51,7 +51,7 @@ namespace RenX public: /** - * @brief Loops through the Renegade-X servers and parses data. + * @brief Loops through the Renegade-X servers. * This should only be called by main(). * * @return Result of Jupiter::Plugin::Think(). diff --git a/RenX.Core/RenX_Server.cpp b/RenX.Core/RenX_Server.cpp index 4ed362f..c09669b 100644 --- a/RenX.Core/RenX_Server.cpp +++ b/RenX.Core/RenX_Server.cpp @@ -24,6 +24,49 @@ #include "RenX_PlayerInfo.h" #include "RenX_GameCommand.h" #include "RenX_Functions.h" +#include "RenX_Plugin.h" + +int RenX::Server::think() +{ + if (RenX::Server::connected == false) + { + if (time(0) >= RenX::Server::lastAttempt + RenX::Server::delay) + { + if (RenX::Server::connect()) + RenX::Server::sendLogChan(IRCCOLOR "03[RenX]" IRCCOLOR " Socket successfully reconnected to Renegade-X server."); + else RenX::Server::sendLogChan(IRCCOLOR "04[Error]" IRCCOLOR " Failed to reconnect to Renegade-X server."); + } + } + else + { + if (RenX::Server::sock.recv() > 0) + { + Jupiter::ReferenceString buffer = RenX::Server::sock.getBuffer(); + unsigned int totalLines = buffer.tokenCount('\n'); + + RenX::Server::lastLine.concat(buffer.getToken(0, '\n')); + if (totalLines != 0) + { + RenX::Server::processLine(RenX::Server::lastLine); + RenX::Server::lastLine = buffer.getToken(totalLines - 1, '\n'); + + for (unsigned int currentLine = 1; currentLine != totalLines - 1; currentLine++) + RenX::Server::processLine(buffer.getToken(currentLine, '\n')); + } + } + else if (Jupiter::Socket::getLastError() != 10035) // This is a serious error + { + if (RenX::Server::reconnect()) + RenX::Server::sendLogChan(IRCCOLOR "07[Warning]" IRCCOLOR " Connection lost to Renegade-X server lost. Reconnection attempt in progress."); + else + { + RenX::Server::wipeData(); + RenX::Server::sendLogChan(IRCCOLOR "04[Error]" IRCCOLOR " Connection lost to Renegade-X server lost. Reconnection attempt failed."); + } + } + } + return 0; +} bool RenX::Server::isConnected() const { @@ -367,6 +410,419 @@ void RenX::Server::sendLogChan(const char *fmt, ...) const } } +#define PARSE_PLAYER_DATA() \ + Jupiter::ReferenceString name; \ + TeamType team; \ + int id; \ + bool isBot = false; { \ + Jupiter::ReferenceString idToken; \ + if (playerData[0] == ',') { \ + name = playerData.gotoWord(1, ","); \ + idToken = playerData.getWord(0, ","); \ + team = Other; \ + } else { \ + name = playerData.gotoWord(2, ","); \ + idToken = playerData.getWord(1, ","); \ + team = RenX::getTeam(playerData[0]); \ + } \ + if (idToken[0] == 'b') { idToken.shiftRight(1); isBot = true; } \ + id = idToken.asInt(10); } \ + RenX::PlayerInfo *player = getPlayerOrAdd(this, name, id, team, isBot); + +inline RenX::PlayerInfo *getPlayerOrAdd(RenX::Server *server, const Jupiter::ReadableString &name, int id, RenX::TeamType team, bool isBot) +{ + RenX::PlayerInfo *r = server->getPlayer(id); + if (r == nullptr) + { + r = new RenX::PlayerInfo(); + r->id = id; + r->name = name; + r->isBot = isBot; + r->joinTime = time(nullptr); + if (id != 0) server->players.add(r); + } + else if (r->name.size() == 0) r->name = name; + r->team = team; + return r; +} + +inline void onPreGameOver(RenX::Server *server, RenX::WinType winType, RenX::TeamType team, int gScore, int nScore) +{ + RenX::PlayerInfo *player; + + if (server->players.size() != 0) + { + for (Jupiter::DLList::Node *n = server->players.getNode(0); n != nullptr; n = n->next) + { + player = n->data; + if (player != nullptr) + { + if (player->team == team) + player->wins++; + else player->loses++; + } + } + } +} + +inline void onPostGameOver(RenX::Server *server, RenX::WinType winType, RenX::TeamType team, int gScore, int nScore) +{ + RenX::PlayerInfo *player; + + if (server->players.size() != 0) + { + for (Jupiter::DLList::Node *n = server->players.getNode(0); n != nullptr; n = n->next) + { + player = n->data; + if (player != nullptr) + { + player->kills = 0; + player->deaths = 0; + player->suicides = 0; + player->headshots = 0; + player->vehicleKills = 0; + player->buildingKills = 0; + player->defenceKills = 0; + } + } + } +} + +inline void onChat(RenX::Server *server, RenX::PlayerInfo *player, const Jupiter::ReadableString &message, bool isPublic) +{ + const Jupiter::ReadableString &prefix = server->getCommandPrefix(); + if (message.find(prefix) == 0 && message.size() != prefix.size()) + { + Jupiter::ReferenceString command; + Jupiter::ReferenceString parameters; + if (containsSymbol(WHITESPACE, message.get(prefix.size()))) + { + command = Jupiter::ReferenceString::getWord(message, 1, WHITESPACE); + parameters = Jupiter::ReferenceString::gotoWord(message, 2, WHITESPACE); + } + else + { + command = Jupiter::ReferenceString::getWord(message, 0, WHITESPACE); + command.shiftRight(prefix.size()); + parameters = Jupiter::ReferenceString::gotoWord(message, 1, WHITESPACE); + } + server->triggerCommand(command, player, parameters); + } +} + +void RenX::Server::processLine(const Jupiter::ReadableString &line) +{ + Jupiter::ReferenceString buff = line; + Jupiter::ArrayList &xPlugins = *RenX::getCore()->getPlugins(); + Jupiter::ReferenceString header = buff.getWord(0, RenX::DelimS); + Jupiter::ReferenceString playerData = buff.getWord(1, RenX::DelimS); + Jupiter::ReferenceString action = buff.getWord(2, RenX::DelimS); + if (buff.size() != 0) + { + switch (header[0]) + { + case 'l': + if (header.equals("lGAME:")) + { + if (action.equals("deployed")) + { + PARSE_PLAYER_DATA(); + Jupiter::ReferenceString objectType = buff.getWord(3, RenX::DelimS); + if (objectType.match("*Beacon")) player->beaconPlacements++; + for (size_t i = 0; i < xPlugins.size(); i++) + xPlugins.get(i)->RenX_OnDeploy(this, player, objectType); + } + else if (action.equals("suicided by")) + { + PARSE_PLAYER_DATA(); + player->deaths++; + player->suicides++; + Jupiter::ReferenceString damageType = buff.getWord(3, RenX::DelimS); + for (size_t i = 0; i < xPlugins.size(); i++) + xPlugins.get(i)->RenX_OnSuicide(this, player, damageType); + } + else if (action.equals("killed")) + { + PARSE_PLAYER_DATA(); + Jupiter::ReferenceString victimData = buff.getWord(3, RenX::DelimS); + Jupiter::ReferenceString vname = victimData.getWord(2, ","); + Jupiter::ReferenceString vidToken = victimData.getWord(1, ","); + int vid; + bool visBot = false; + if (vidToken[0] == 'b') + { + vidToken.shiftRight(1); + visBot = true; + } + vid = vidToken.asInt(10); + TeamType vteam = RenX::getTeam(victimData.getWord(0, ",")[0]); + Jupiter::ReferenceString damageType = buff.getWord(5, RenX::DelimS); + RenX::PlayerInfo *victim = getPlayerOrAdd(this, vname, vid, vteam, visBot); + player->kills++; + if (damageType.equals("Rx_DmgType_Headshot")) player->headshots++; + victim->deaths++; + + if (this->needsCList) + { + this->sendData(STRING_LITERAL_AS_REFERENCE("clogclientlist\n")); + this->needsCList = false; + } + + for (size_t i = 0; i < xPlugins.size(); i++) + xPlugins.get(i)->RenX_OnKill(this, player, victim, damageType); + } + else if (action.match("died by")) + { + PARSE_PLAYER_DATA(); + player->deaths++; + Jupiter::ReferenceString damageType = buff.getWord(3, RenX::DelimS); + for (size_t i = 0; i < xPlugins.size(); i++) + xPlugins.get(i)->RenX_OnDie(this, player, damageType); + } + else if (action.match("destroyed*")) + { + PARSE_PLAYER_DATA(); + Jupiter::ReferenceString victim = buff.getWord(3, RenX::DelimS); + Jupiter::ReferenceString damageType = buff.getWord(5, RenX::DelimS); + ObjectType type; + if (action.equals("destroyed building")) + { + type = Building; + player->buildingKills++; + } + else if (victim.match("Rx_Defence_*")) + { + type = Defence; + player->defenceKills++; + } + else + { + type = Vehicle; + player->vehicleKills++; + } + for (size_t i = 0; i < xPlugins.size(); i++) + xPlugins.get(i)->RenX_OnDestroy(this, player, victim, damageType, type); + } + else if (playerData.match("??? wins (*)")) + { + TeamType team = RenX::getTeam(playerData[0]); + int gScore = buff.getWord(2, RenX::DelimS).gotoWord(1, "=").asInt(10); + int nScore = buff.getWord(3, RenX::DelimS).gotoWord(1, "=").asInt(10); + Jupiter::ReferenceString winType = Jupiter::ReferenceString::substring(playerData, 10); + winType.truncate(1); + WinType iWinType = Unknown; + if (gScore == nScore) + iWinType = Tie; + else if (winType.equals("TimeLimit")) + iWinType = Score; + else if (winType.equals("Buildings")) + iWinType = Base; + + this->needsCList = true; + onPreGameOver(this, iWinType, team, gScore, nScore); + for (size_t i = 0; i < xPlugins.size(); i++) + xPlugins.get(i)->RenX_OnGameOver(this, iWinType, team, gScore, nScore); + onPostGameOver(this, iWinType, team, gScore, nScore); + } + else if (playerData.equals("Tie")) + { + int gScore = action.gotoWord(1, "=").asInt(10); + int nScore = buff.getWord(3, RenX::DelimS).gotoWord(1, "=").asInt(10); + + this->needsCList = true; + if (gScore == nScore) + { + onPreGameOver(this, Tie, Other, gScore, nScore); + for (size_t i = 0; i < xPlugins.size(); i++) + xPlugins.get(i)->RenX_OnGameOver(this, Tie, Other, gScore, nScore); + onPostGameOver(this, Tie, Other, gScore, nScore); + } + else + { + TeamType winTeam = gScore > nScore ? RenX::getTeam('G') : RenX::getTeam('N'); + onPreGameOver(this, Shutdown, winTeam, gScore, nScore); + for (size_t i = 0; i < xPlugins.size(); i++) + xPlugins.get(i)->RenX_OnGameOver(this, Shutdown, winTeam, gScore, nScore); + onPostGameOver(this, Shutdown, winTeam, gScore, nScore); + } + } + else for (size_t i = 0; i < xPlugins.size(); i++) + xPlugins.get(i)->RenX_OnGame(this, buff.gotoWord(1, RenX::DelimS)); + } + else if (header.equals("lCHAT:")) + { + if (action.equals("teamsay:")) + { + PARSE_PLAYER_DATA(); + Jupiter::ReferenceString message = buff.getWord(3, RenX::DelimS); + onChat(this, player, message, false); + for (size_t i = 0; i < xPlugins.size(); i++) + xPlugins.get(i)->RenX_OnTeamChat(this, player, message); + } + else if (action.equals("say:")) + { + PARSE_PLAYER_DATA(); + Jupiter::ReferenceString message = buff.getWord(3, RenX::DelimS); + onChat(this, player, message, true); + for (size_t i = 0; i < xPlugins.size(); i++) + xPlugins.get(i)->RenX_OnChat(this, player, message); + } + } + else if (header.equals("lPLAYER:")) + { + PARSE_PLAYER_DATA(); + if (action.equals("disconnected")) + { + for (size_t i = 0; i < xPlugins.size(); i++) + xPlugins.get(i)->RenX_OnPart(this, player); + this->removePlayer(player); + player = nullptr; + } + else if (action.equals("entered from")) + { + player->ip = buff.getWord(3, RenX::DelimS); + if (buff.getWord(4, RenX::DelimS).equals("steamid")) player->steamid = buff.getWord(5, RenX::DelimS); + for (size_t i = 0; i < xPlugins.size(); i++) + xPlugins.get(i)->RenX_OnJoin(this, player); + } + else if (action.equals("changed name to:")) + { + Jupiter::ReferenceString newName = buff.getWord(3, RenX::DelimS); + for (size_t i = 0; i < xPlugins.size(); i++) + xPlugins.get(i)->RenX_OnNameChange(this, player, newName); + player->name = newName; + } + } + else if (header.equals("lRCON:")) + { + if (action.equals("executed:")) + { + Jupiter::ReferenceString command = buff.getWord(3, RenX::DelimS); + for (size_t i = 0; i < xPlugins.size(); i++) + xPlugins.get(i)->RenX_OnExecute(this, playerData, command); + } + else if (action.equals("subscribed")) for (size_t i = 0; i < xPlugins.size(); i++) + xPlugins.get(i)->RenX_OnSubscribe(this, playerData); + else for (size_t i = 0; i < xPlugins.size(); i++) + xPlugins.get(i)->RenX_OnRCON(this, buff.gotoWord(1, RenX::DelimS)); + } + else if (header.equals("lADMIN:")) + { + PARSE_PLAYER_DATA(); + if (action.equals("logged in as")) + { + player->adminType = buff.getWord(3, RenX::DelimS); + for (size_t i = 0; i < xPlugins.size(); i++) + xPlugins.get(i)->RenX_OnAdminLogin(this, player); + } + else if (action.equals("logged out of")) + { + Jupiter::ReferenceString type = buff.getWord(3, RenX::DelimS); + for (size_t i = 0; i < xPlugins.size(); i++) + xPlugins.get(i)->RenX_OnAdminLogout(this, player); + player->adminType = ""; + } + else for (size_t i = 0; i < xPlugins.size(); i++) + xPlugins.get(i)->RenX_OnAdmin(this, buff.gotoWord(1, RenX::DelimS)); + } + else if (header.equals("lC-LIST:")) + { + // ID IP SteamID Team Name + if (playerData.isEmpty()) + break; + + int id; + bool isBot = false; + if (playerData.get(0) == 'b') + { + isBot = true; + playerData.shiftRight(1); + id = playerData.asInt(10); + playerData.shiftLeft(1); + } + else id = playerData.asInt(10); + Jupiter::ReferenceString ip = playerData.getWord(1, WHITESPACE); + Jupiter::ReferenceString steamid = playerData.getWord(2, WHITESPACE); + RenX::TeamType team; + Jupiter::ReferenceString name; + if (steamid.equals("-----NO")) // RCONv2-2a + { + steamid = ""; + Jupiter::ReferenceString &teamToken = playerData.getWord(4, WHITESPACE); + if (teamToken.isEmpty()) + break; + team = getTeam(teamToken.get(0)); + name = playerData.gotoWord(5, WHITESPACE); + } + else + { + if (steamid.equals("-----NO-STEAM-----")) // RCONv2-2.5a + steamid = ""; + Jupiter::ReferenceString &teamToken = playerData.getWord(3, WHITESPACE); + if (teamToken.isEmpty()) + break; + team = getTeam(teamToken.get(0)); + name = playerData.gotoWord(4, WHITESPACE); + } + + RenX::PlayerInfo *player = getPlayerOrAdd(this, name, id, team, isBot); + if (player->ip.size() == 0) + { + player->ip = ip; + player->steamid = steamid; + } + } + else + { + buff.shiftRight(1); + for (size_t i = 0; i < xPlugins.size(); i++) + xPlugins.get(i)->RenX_OnLog(this, buff); + buff.shiftLeft(1); + } + break; + + case 'c': + buff.shiftRight(1); + for (size_t i = 0; i < xPlugins.size(); i++) + xPlugins.get(i)->RenX_OnCommand(this, buff); + buff.shiftLeft(1); + break; + + case 'e': + buff.shiftRight(1); + for (size_t i = 0; i < xPlugins.size(); i++) + xPlugins.get(i)->RenX_OnError(this, buff); + buff.shiftLeft(1); + break; + + case 'v': + buff.shiftRight(1); + this->rconVersion = buff.asInt(10); + this->gameVersion = buff.substring(3); + for (size_t i = 0; i < xPlugins.size(); i++) + xPlugins.get(i)->RenX_OnVersion(this, buff); + buff.shiftLeft(1); + break; + + case 'a': + buff.shiftRight(1); + for (size_t i = 0; i < xPlugins.size(); i++) + xPlugins.get(i)->RenX_OnAuthorized(this, buff); + buff.shiftLeft(1); + break; + + default: + buff.shiftRight(1); + for (size_t i = 0; i < xPlugins.size(); i++) + xPlugins.get(i)->RenX_OnOther(this, header[0], buff); + buff.shiftLeft(1); + break; + } + for (size_t i = 0; i < xPlugins.size(); i++) + xPlugins.get(i)->RenX_OnRaw(this, buff); + } +} + void RenX::Server::disconnect() { RenX::Server::sock.closeSocket(); @@ -398,7 +854,8 @@ bool RenX::Server::reconnect() void RenX::Server::wipeData() { - while (RenX::Server::players.size() != 0) delete RenX::Server::players.remove(0U); + while (RenX::Server::players.size() != 0) + delete RenX::Server::players.remove(0U); RenX::Server::commands.emptyAndDelete(); } diff --git a/RenX.Core/RenX_Server.h b/RenX.Core/RenX_Server.h index b8bda77..66b604e 100644 --- a/RenX.Core/RenX_Server.h +++ b/RenX.Core/RenX_Server.h @@ -29,6 +29,7 @@ #include "Jupiter/String.h" #include "Jupiter/CString.h" #include "Jupiter/INIFile.h" +#include "Jupiter/Thinker.h" #include "RenX.h" /** DLL Linkage Nagging */ @@ -48,10 +49,18 @@ namespace RenX * @brief Represents a connection to an individiaul Renegade-X server. * There are often more than one of these, such as when communities run multiple servers. */ - class RENX_API Server + class RENX_API Server : public Jupiter::Thinker { - friend class RenX::Core; - public: + public: // Jupiter::Thinker + + /** + * @brief Checks and processes raw socket data. + * + * @return Zero if no error occurs, a non-zero value otherwise. + */ + int think(); + + public: // RenX::Server Jupiter::DLList players; /** A list of players in the server */ Jupiter::INIFile varData; /** This may be replaced later with a more dedicated type. */ @@ -352,6 +361,13 @@ namespace RenX */ void sendLogChan(const char *fmt, ...) const; + /** + * @brief Processes a line of RCON input data. Input data SHOULD NOT include a new-line ('\n') terminator. + * + * @param line Line to process + */ + void processLine(const Jupiter::ReadableString &line); + /** * @brief Disconnects from a server's RCON interface. */ @@ -418,6 +434,7 @@ namespace RenX Jupiter::StringS IRCPrefix; Jupiter::StringS CommandPrefix; Jupiter::StringS gameVersion; + Jupiter::String lastLine; Jupiter::ArrayList commands; };