diff --git a/Release/Plugins/RenX.Core.lib b/Release/Plugins/RenX.Core.lib index 351b393..3ec45f8 100644 Binary files a/Release/Plugins/RenX.Core.lib and b/Release/Plugins/RenX.Core.lib differ diff --git a/RenX.Core/RenX.Core.vcxproj b/RenX.Core/RenX.Core.vcxproj index 18d2c1f..d0ebcb1 100644 --- a/RenX.Core/RenX.Core.vcxproj +++ b/RenX.Core/RenX.Core.vcxproj @@ -71,6 +71,7 @@ + diff --git a/RenX.Core/RenX.Core.vcxproj.filters b/RenX.Core/RenX.Core.vcxproj.filters index 1027a38..09f1e2b 100644 --- a/RenX.Core/RenX.Core.vcxproj.filters +++ b/RenX.Core/RenX.Core.vcxproj.filters @@ -50,6 +50,9 @@ Header Files + + Header Files + diff --git a/RenX.Core/RenX_BuildingInfo.h b/RenX.Core/RenX_BuildingInfo.h new file mode 100644 index 0000000..dc0433a --- /dev/null +++ b/RenX.Core/RenX_BuildingInfo.h @@ -0,0 +1,59 @@ +/** + * Copyright (C) 2015 Justin James. + * + * This license must be preserved. + * Any applications, libraries, or code which make any use of any + * component of this program must not be commercial, unless explicit + * permission is granted from the original author. The use of this + * program for non-profit purposes is permitted. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * In the event that this license restricts you from making desired use of this program, contact the original author. + * Written by Justin James + */ + +#if !defined _RENX_BUILDINGINFO_H_HEADER +#define _RENX_BUILDINGINFO_H_HEADER + +/** + * @file RenX_BuildingInfo.h + * @brief Defines the BuildingInfo structure. + */ + +#include "Jupiter/String.h" +#include "Jupiter/INIFile.h" +#include "RenX.h" + +/** DLL Linkage Nagging */ +#if defined _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4251) +#endif + +namespace RenX +{ + + /** + * @brief Includes all of the tracked information about a building. + */ + struct RENX_API BuildingInfo + { + Jupiter::StringS name; + TeamType team = TeamType::Other; + int health = 0; + int max_health = 0; + bool capturable = false; + mutable Jupiter::INIFile varData; + }; + +} + +/** Re-enable warnings */ +#if defined _MSC_VER +#pragma warning(pop) +#endif + +#endif // _RENX_BUILDINGINFO_H_HEADER \ No newline at end of file diff --git a/RenX.Core/RenX_Core.cpp b/RenX.Core/RenX_Core.cpp index 7f5fe12..9de547d 100644 --- a/RenX.Core/RenX_Core.cpp +++ b/RenX.Core/RenX_Core.cpp @@ -1,5 +1,5 @@ /** - * Copyright (C) 2014 Justin James. + * Copyright (C) 2014-2015 Justin James. * * This license must be preserved. * Any applications, libraries, or code which make any use of any @@ -34,7 +34,7 @@ RenX::Core *RenX::getCore() return &pluginInstance; } -RenX::Core::Core() +void RenX::Core::init() { const Jupiter::ReadableString &serverList = Jupiter::IRC::Client::Config->get(STRING_LITERAL_AS_REFERENCE("RenX"), STRING_LITERAL_AS_REFERENCE("Servers")); RenX::Core::translationsFile.readFile(Jupiter::IRC::Client::Config->get(STRING_LITERAL_AS_REFERENCE("RenX"), STRING_LITERAL_AS_REFERENCE("TranslationsFile"), STRING_LITERAL_AS_REFERENCE("Translations.ini"))); @@ -149,11 +149,11 @@ int RenX::Core::addCommand(RenX::GameCommand *command) int RenX::Core::think() { - 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++; + size_t index = 0; + while (index < RenX::Core::servers.size()) + if (RenX::Core::servers.get(index)->think() != 0) + delete RenX::Core::servers.remove(index); + else ++index; return Jupiter::Plugin::think(); } @@ -165,6 +165,14 @@ extern "C" __declspec(dllexport) Jupiter::Plugin *getPlugin() return &pluginInstance; } +// Load + +extern "C" __declspec(dllexport) bool load(void) +{ + pluginInstance.init(); + return true; +} + // Unload extern "C" __declspec(dllexport) void unload(void) diff --git a/RenX.Core/RenX_Core.h b/RenX.Core/RenX_Core.h index d5c504e..21be70d 100644 --- a/RenX.Core/RenX_Core.h +++ b/RenX.Core/RenX_Core.h @@ -1,5 +1,5 @@ /** - * Copyright (C) 2014 Justin James. + * Copyright (C) 2014-2015 Justin James. * * This license must be preserved. * Any applications, libraries, or code which make any use of any @@ -157,9 +157,9 @@ namespace RenX int addCommand(GameCommand *command); /** - * @brief Default constructor for the Core class. + * @brief Initializes the Core. */ - Core(); + void init(); /** * Destructor for the Core class. diff --git a/RenX.Core/RenX_Functions.cpp b/RenX.Core/RenX_Functions.cpp index 720e548..3ec861f 100644 --- a/RenX.Core/RenX_Functions.cpp +++ b/RenX.Core/RenX_Functions.cpp @@ -445,7 +445,7 @@ const Jupiter::ReferenceString RenX::translateName(const Jupiter::ReadableString return Jupiter::ReferenceString::empty; Jupiter::ReferenceString iniTranslation = RenX::getCore()->getTranslationsFile().get(STRING_LITERAL_AS_REFERENCE("Name"), obj); - if (iniTranslation.isEmpty() == false) + if (iniTranslation.isNotEmpty()) return iniTranslation; static Jupiter::ReferenceString object; @@ -778,7 +778,7 @@ Jupiter::String RenX::getFormattedPlayerName(const RenX::PlayerInfo *player) void RenX::sanitizeString(Jupiter::StringType &str) { - if (str.isEmpty() == false) + if (str.isNotEmpty()) { str.replace('|', '/'); if (str.get(str.size() - 1) == '\\') diff --git a/RenX.Core/RenX_Server.cpp b/RenX.Core/RenX_Server.cpp index 68cfa46..d35c758 100644 --- a/RenX.Core/RenX_Server.cpp +++ b/RenX.Core/RenX_Server.cpp @@ -22,6 +22,7 @@ #include "IRC_Bot.h" #include "RenX_Server.h" #include "RenX_PlayerInfo.h" +#include "RenX_BuildingInfo.h" #include "RenX_GameCommand.h" #include "RenX_Functions.h" #include "RenX_Plugin.h" @@ -82,8 +83,14 @@ int RenX::Server::think() } return 0; } - if (RenX::Server::rconVersion >= 3 && std::chrono::steady_clock::now() > RenX::Server::lastClientListUpdate + RenX::Server::clientUpdateRate) - RenX::Server::updateClientList(); + if (RenX::Server::rconVersion >= 3) + { + if (RenX::Server::clientUpdateRate != std::chrono::milliseconds::zero() && std::chrono::steady_clock::now() > RenX::Server::lastClientListUpdate + RenX::Server::clientUpdateRate) + RenX::Server::updateClientList(); + + if (RenX::Server::buildingUpdateRate != std::chrono::milliseconds::zero() && std::chrono::steady_clock::now() > RenX::Server::lastBuildingListUpdate + RenX::Server::buildingUpdateRate) + RenX::Server::updateBuildingList(); + } } return 0; } @@ -198,6 +205,14 @@ int RenX::Server::sendData(const Jupiter::ReadableString &data) return RenX::Server::sock.send(data); } +RenX::BuildingInfo *RenX::Server::getBuildingByName(const Jupiter::ReadableString &name) const +{ + for (size_t index = 0; index != RenX::Server::buildings.size(); ++index) + if (RenX::Server::buildings.get(index)->name.equalsi(name)) + return RenX::Server::buildings.get(index); + return nullptr; +} + RenX::PlayerInfo *RenX::Server::getPlayer(int id) const { if (RenX::Server::players.size() == 0) return nullptr; @@ -373,14 +388,20 @@ bool RenX::Server::updateClientList() if (RenX::Server::players.get(i)->isBot) botCount++; - bool r; + int r = 0; if (RenX::Server::players.size() != botCount) r = RenX::Server::sock.send(STRING_LITERAL_AS_REFERENCE("cclientvarlist ID\xA0""SCORE\xA0""CREDITS\xA0""PING\n")) > 0; if (botCount != 0) r |= RenX::Server::sock.send(STRING_LITERAL_AS_REFERENCE("cbotvarlist ID\xA0""SCORE\xA0""CREDITS\n")) > 0; - return r; + return r != 0; +} + +bool RenX::Server::updateBuildingList() +{ + RenX::Server::lastBuildingListUpdate = std::chrono::steady_clock::now(); + return RenX::Server::sock.send(STRING_LITERAL_AS_REFERENCE("cbinfo\n")) > 0; } bool RenX::Server::gameover() @@ -498,7 +519,7 @@ bool RenX::Server::changeTeam(RenX::PlayerInfo *player, bool resetCredits) const Jupiter::ReadableString &RenX::Server::getPrefix() const { - static Jupiter::StringS parsed; + static Jupiter::String parsed; RenX::processTags(parsed = RenX::Server::IRCPrefix, this); return parsed; } @@ -627,7 +648,7 @@ void RenX::Server::addCommand(RenX::GameCommand *command) if (RenX::Server::commandAccessLevels != nullptr) { const Jupiter::ReadableString &accessLevel = RenX::Server::commandAccessLevels->get(command->getTrigger()); - if (accessLevel.isEmpty() == false) + if (accessLevel.isNotEmpty()) command->setAccessLevel(accessLevel.asInt()); } if (RenX::Server::commandAliases != nullptr) @@ -703,7 +724,7 @@ void RenX::Server::sendPubChan(const char *fmt, ...) const va_start(args, fmt); Jupiter::StringL msg; const Jupiter::ReadableString &serverPrefix = RenX::Server::getPrefix(); - if (serverPrefix.isEmpty() == false) + if (serverPrefix.isNotEmpty()) { msg += serverPrefix; msg += ' '; @@ -718,7 +739,7 @@ void RenX::Server::sendPubChan(const char *fmt, ...) const void RenX::Server::sendPubChan(const Jupiter::ReadableString &msg) const { const Jupiter::ReadableString &prefix = this->getPrefix(); - if (prefix.isEmpty() == false) + if (prefix.isNotEmpty()) { Jupiter::String m(msg.size() + prefix.size() + 1); m.set(prefix); @@ -738,7 +759,7 @@ void RenX::Server::sendAdmChan(const char *fmt, ...) const va_start(args, fmt); Jupiter::StringL msg; const Jupiter::ReadableString &serverPrefix = RenX::Server::getPrefix(); - if (serverPrefix.isEmpty() == false) + if (serverPrefix.isNotEmpty()) { msg += serverPrefix; msg += ' '; @@ -753,7 +774,7 @@ void RenX::Server::sendAdmChan(const char *fmt, ...) const void RenX::Server::sendAdmChan(const Jupiter::ReadableString &msg) const { const Jupiter::ReadableString &prefix = this->getPrefix(); - if (prefix.isEmpty() == false) + if (prefix.isNotEmpty()) { Jupiter::String m(msg.size() + prefix.size() + 1); m.set(prefix); @@ -774,7 +795,7 @@ void RenX::Server::sendLogChan(const char *fmt, ...) const va_start(args, fmt); Jupiter::StringL msg; const Jupiter::ReadableString &serverPrefix = RenX::Server::getPrefix(); - if (serverPrefix.isEmpty() == false) + if (serverPrefix.isNotEmpty()) { msg += serverPrefix; msg += ' '; @@ -794,7 +815,7 @@ void RenX::Server::sendLogChan(const Jupiter::ReadableString &msg) const { IRC_Bot *server; const Jupiter::ReadableString &prefix = this->getPrefix(); - if (prefix.isEmpty() == false) + if (prefix.isNotEmpty()) { Jupiter::String m(msg.size() + prefix.size() + 1); m.set(prefix); @@ -937,7 +958,7 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) banDatabase->deactivate(i); else if ((this->localSteamBan && entry->steamid != 0 && entry->steamid == player->steamid) || (this->localIPBan && entry->ip != 0 && entry->ip == player->ip32) - || (this->localNameBan && entry->name.isEmpty() == false && entry->name.equalsi(player->name))) + || (this->localNameBan && entry->name.isNotEmpty() && entry->name.equalsi(player->name))) { char timeStr[256]; if (entry->length == 0) @@ -983,7 +1004,7 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) { bool recalcUUID = false; r->team = team; - if (r->ip32 == 0 && ip.isEmpty() == false) + if (r->ip32 == 0 && ip.isNotEmpty()) { r->ip = ip; r->ip32 = Jupiter::Socket::pton4(Jupiter::CStringS(r->ip).c_str()); @@ -994,7 +1015,7 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) r->steamid = steamid; recalcUUID = true; } - if (r->name.size() == 0) + if (r->name.isEmpty()) { r->name = name; recalcUUID = true; @@ -1013,7 +1034,7 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) return getPlayerOrAdd(name, id, team, isBot, 0U, Jupiter::ReferenceString::empty); }; - if (buff.size() != 0) + if (buff.isNotEmpty()) { switch (header[0]) { @@ -1022,7 +1043,7 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) { // ID | IP | Steam ID | Admin Status | Team | Name header.shiftRight(1); - if (header.isEmpty() == false) + if (header.isNotEmpty()) { bool isBot = false; int id; @@ -1304,16 +1325,69 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) } buff.shiftLeft(1); } + else if (this->lastCommand.equalsi("binfo") || this->lastCommand.equalsi("buildinginfo") || this->lastCommand.equalsi("blist") || this->lastCommand.equalsi("buildinglist")) + { + buff.shiftRight(1); + if (this->commandListFormat.isEmpty()) + this->commandListFormat = buff; + else + { + /* + lRCON Command; DevBot executed: binfo + rBuilding Health MaxHealth Team Capturable + rRx_Building_Refinery_GDI 4000 4000 GDI False + */ + Jupiter::INIFile::Section table; + size_t i = this->commandListFormat.tokenCount(RenX::DelimC); + while (i-- != 0) + table.set(this->commandListFormat.getToken(i, RenX::DelimC), buff.getToken(i, RenX::DelimC)); + + Jupiter::INIFile::Section::KeyValuePair *pair; + RenX::BuildingInfo *building; + + pair = table.getPair(STRING_LITERAL_AS_REFERENCE("Building")); + if (pair != nullptr) + { + building = this->getBuildingByName(pair->getValue()); + if (building == nullptr) + { + building = new RenX::BuildingInfo(); + RenX::Server::buildings.add(building); + building->name = pair->getValue(); + } + + pair = table.getPair(STRING_LITERAL_AS_REFERENCE("Health")); + if (pair != nullptr) + building->health = pair->getValue().asInt(10); + + pair = table.getPair(STRING_LITERAL_AS_REFERENCE("MaxHealth")); + if (pair != nullptr) + building->max_health = pair->getValue().asInt(10); + + pair = table.getPair(STRING_LITERAL_AS_REFERENCE("Team")); + if (pair != nullptr) + building->team = RenX::getTeam(pair->getValue()); + + pair = table.getPair(STRING_LITERAL_AS_REFERENCE("Capturable")); + if (pair != nullptr) + building->capturable = pair->getValue().asBool(); + } + } + buff.shiftLeft(1); + } else if (this->lastCommand.equalsi("map")) this->map = buff.substring(1); else if (this->lastCommand.equalsi("serverinfo")) { - // "Port" | Port | "Name" | Name | "Passworded" | "True"/"False" | "Level" | Level - buff.shiftRight(1); - this->port = static_cast(buff.getToken(1, RenX::DelimC).asUnsignedInt(10)); - this->serverName = buff.getToken(3, RenX::DelimC); - this->map = buff.getToken(7, RenX::DelimC); - buff.shiftLeft(1); + if (this->lastCommandParams.isEmpty()) + { + // "Port" | Port | "Name" | Name | "Passworded" | "True"/"False" | "Level" | Level + buff.shiftRight(1); + this->port = static_cast(buff.getToken(1, RenX::DelimC).asUnsignedInt(10)); + this->serverName = buff.getToken(3, RenX::DelimC); + this->map = buff.getToken(7, RenX::DelimC); + buff.shiftLeft(1); + } } else if (this->lastCommand.equalsi("changename")) { @@ -1593,7 +1667,7 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) // "player" | Player | "suicide by" | Damage Type // NOTE: Filter these out when Player.isEmpty(). Jupiter::ReferenceString playerToken = buff.getToken(3, RenX::DelimC); - if (playerToken.isEmpty() == false) + if (playerToken.isNotEmpty()) { RenX::PlayerInfo *player = parseGetPlayerOrAdd(playerToken); Jupiter::ReferenceString type = buff.getToken(4, RenX::DelimC); @@ -1937,7 +2011,10 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) for (size_t i = 0; i < xPlugins.size(); i++) xPlugins.get(i)->RenX_OnExecute(this, user, command); if (this->rconUser.equals(user)) + { this->lastCommand = cmd; + this->lastCommandParams = command.gotoWord(1, " "); + } } } else if (subHeader.equals("Subscribed;")) @@ -2269,6 +2346,7 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) xPlugins.get(i)->RenX_OnCommand(this, buff); this->commandListFormat.set(Jupiter::ReferenceString::empty); this->lastCommand = Jupiter::ReferenceString::empty; + this->lastCommandParams = Jupiter::ReferenceString::empty; buff.shiftLeft(1); break; @@ -2289,6 +2367,7 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) RenX::Server::sock.send(STRING_LITERAL_AS_REFERENCE("s\n")); RenX::Server::send(STRING_LITERAL_AS_REFERENCE("serverinfo")); RenX::Server::fetchClientList(); + RenX::Server::updateBuildingList(); this->firstGame = true; this->seamless = true; @@ -2423,6 +2502,7 @@ void RenX::Server::init() RenX::Server::steamFormat = Jupiter::IRC::Client::Config->getInt(RenX::Server::configSection, STRING_LITERAL_AS_REFERENCE("SteamFormat"), 16); RenX::Server::neverSay = Jupiter::IRC::Client::Config->getBool(RenX::Server::configSection, STRING_LITERAL_AS_REFERENCE("NeverSay"), false); RenX::Server::clientUpdateRate = std::chrono::milliseconds(Jupiter::IRC::Client::Config->getInt(RenX::Server::configSection, STRING_LITERAL_AS_REFERENCE("ClientUpdateRate"), 2500)); + RenX::Server::buildingUpdateRate = std::chrono::milliseconds(Jupiter::IRC::Client::Config->getInt(RenX::Server::configSection, STRING_LITERAL_AS_REFERENCE("BuildingUpdateRate"), 7500)); Jupiter::INIFile &commandsFile = RenX::getCore()->getCommandsFile(); RenX::Server::commandAccessLevels = commandsFile.getSection(RenX::Server::configSection); diff --git a/RenX.Core/RenX_Server.h b/RenX.Core/RenX_Server.h index 812d3ec..71abd4c 100644 --- a/RenX.Core/RenX_Server.h +++ b/RenX.Core/RenX_Server.h @@ -45,6 +45,7 @@ namespace RenX { /** Forward declarations */ struct PlayerInfo; + struct BuildingInfo; class GameCommand; class Core; @@ -82,6 +83,7 @@ namespace RenX public: // RenX::Server Jupiter::DLList players; /** A list of players in the server */ + Jupiter::ArrayList buildings; /** A list of buildings in the server */ Jupiter::INIFile varData; /** This may be replaced later with a more dedicated type. */ /** @@ -190,6 +192,14 @@ namespace RenX */ int sendData(const Jupiter::ReadableString &data); + /** + * @brief Fetches a player's data, based on their name. + * + * @param name Name of the player. + * @return A player's data on success, nullptr otherwise. + */ + RenX::BuildingInfo *getBuildingByName(const Jupiter::ReadableString &name) const; + /** * @brief Fetches a player's data based on their ID number. * @@ -314,6 +324,13 @@ namespace RenX */ bool updateClientList(); + /** + * @brief Sends a building list request. + * + * @return True on success, false otherwise. + */ + bool updateBuildingList(); + /** * @brief Forces the current game to end. * @@ -800,6 +817,7 @@ namespace RenX time_t lastAttempt = 0; int attempts = 0; std::chrono::steady_clock::time_point lastClientListUpdate = std::chrono::steady_clock::now(); + std::chrono::steady_clock::time_point lastBuildingListUpdate = std::chrono::steady_clock::now(); Jupiter::String lastLine; Jupiter::StringS commandListFormat; Jupiter::StringS gameVersion; @@ -812,6 +830,7 @@ namespace RenX time_t delay; int maxAttempts; std::chrono::milliseconds clientUpdateRate; + std::chrono::milliseconds buildingUpdateRate; int steamFormat; /** 16 = hex, 10 = base 10, 8 = octal, -2 = SteamID 2, -3 = SteamID 3 */ bool rconBan; bool localBan; @@ -831,6 +850,7 @@ namespace RenX Jupiter::StringS rconUser; Jupiter::StringS serverName; Jupiter::StringS lastCommand; + Jupiter::StringS lastCommandParams; Jupiter::StringS map; Jupiter::INIFile::Section *commandAccessLevels; Jupiter::INIFile::Section *commandAliases; diff --git a/RenX.Core/RenX_Tags.cpp b/RenX.Core/RenX_Tags.cpp index 82ed6c3..10f3553 100644 --- a/RenX.Core/RenX_Tags.cpp +++ b/RenX.Core/RenX_Tags.cpp @@ -253,101 +253,109 @@ TagsImp::TagsImp() this->loseScoreTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("LoseScoreTag"), STRING_LITERAL_AS_REFERENCE("{LOSESCORE}")); } +#define PROCESS_TAG(tag, value) \ +while(true) { \ +index = msg.find(tag); \ +if (index == Jupiter::INVALID_INDEX) break; \ +msg.replace(index, tag.size(), value); } + + void TagsImp::processTags(Jupiter::StringType &msg, const RenX::Server *server, const RenX::PlayerInfo *player, const RenX::PlayerInfo *victim) { - msg.replace(this->INTERNAL_DATE_TAG, Jupiter::ReferenceString(getTimeFormat(this->dateFmt.c_str()))); - msg.replace(this->INTERNAL_TIME_TAG, Jupiter::ReferenceString(getTimeFormat(this->timeFmt.c_str()))); + size_t index; + PROCESS_TAG(this->INTERNAL_DATE_TAG, Jupiter::ReferenceString(getTimeFormat(this->dateFmt.c_str()))); + PROCESS_TAG(this->INTERNAL_TIME_TAG, Jupiter::ReferenceString(getTimeFormat(this->timeFmt.c_str()))); if (server != nullptr) { - msg.replace(this->INTERNAL_RCON_VERSION_TAG, Jupiter::StringS::Format("%u", server->getVersion())); - msg.replace(this->INTERNAL_GAME_VERSION_TAG, server->getGameVersion()); - msg.replace(this->INTERNAL_RULES_TAG, server->getRules()); - msg.replace(this->INTERNAL_USER_TAG, server->getUser()); - msg.replace(this->INTERNAL_SERVER_NAME_TAG, server->getName()); - msg.replace(this->INTERNAL_MAP_TAG, server->getMap()); - msg.replace(this->INTERNAL_SERVER_HOSTNAME_TAG, server->getHostname()); - msg.replace(this->INTERNAL_SERVER_PORT_TAG, Jupiter::StringS::Format("%u", server->getPort())); - msg.replace(this->INTERNAL_SOCKET_HOSTNAME_TAG, server->getSocketHostname()); - msg.replace(this->INTERNAL_SOCKET_PORT_TAG, Jupiter::StringS::Format("%u", server->getSocketPort())); - msg.replace(this->INTERNAL_SERVER_PREFIX_TAG, server->getPrefix()); + PROCESS_TAG(this->INTERNAL_RCON_VERSION_TAG, Jupiter::StringS::Format("%u", server->getVersion())); + PROCESS_TAG(this->INTERNAL_GAME_VERSION_TAG, server->getGameVersion()); + PROCESS_TAG(this->INTERNAL_RULES_TAG, server->getRules()); + PROCESS_TAG(this->INTERNAL_USER_TAG, server->getUser()); + PROCESS_TAG(this->INTERNAL_SERVER_NAME_TAG, server->getName()); + PROCESS_TAG(this->INTERNAL_MAP_TAG, server->getMap()); + PROCESS_TAG(this->INTERNAL_SERVER_HOSTNAME_TAG, server->getHostname()); + PROCESS_TAG(this->INTERNAL_SERVER_PORT_TAG, Jupiter::StringS::Format("%u", server->getPort())); + PROCESS_TAG(this->INTERNAL_SOCKET_HOSTNAME_TAG, server->getSocketHostname()); + PROCESS_TAG(this->INTERNAL_SOCKET_PORT_TAG, Jupiter::StringS::Format("%u", server->getSocketPort())); + PROCESS_TAG(this->INTERNAL_SERVER_PREFIX_TAG, server->getPrefix()); if (player != nullptr) { - msg.replace(this->INTERNAL_STEAM_TAG, server->formatSteamID(player)); + PROCESS_TAG(this->INTERNAL_STEAM_TAG, server->formatSteamID(player)); } if (victim != nullptr) { - msg.replace(this->INTERNAL_VICTIM_STEAM_TAG, server->formatSteamID(victim)); + PROCESS_TAG(this->INTERNAL_VICTIM_STEAM_TAG, server->formatSteamID(victim)); } } if (player != nullptr) { - msg.replace(this->INTERNAL_NAME_TAG, RenX::getFormattedPlayerName(player)); - msg.replace(this->INTERNAL_RAW_NAME_TAG, player->name); - msg.replace(this->INTERNAL_IP_TAG, player->ip); - msg.replace(this->INTERNAL_UUID_TAG, player->uuid); - msg.replace(this->INTERNAL_ID_TAG, Jupiter::StringS::Format("%d", player->id)); - msg.replace(this->INTERNAL_CHARACTER_TAG, RenX::translateName(player->character)); - msg.replace(this->INTERNAL_VEHICLE_TAG, RenX::translateName(player->vehicle)); - msg.replace(this->INTERNAL_ADMIN_TAG, player->adminType); - msg.replace(this->INTERNAL_PREFIX_TAG, player->formatNamePrefix); - msg.replace(this->INTERNAL_GAME_PREFIX_TAG, player->gamePrefix); - msg.replace(this->INTERNAL_TEAM_COLOR_TAG, RenX::getTeamColor(player->team)); - msg.replace(this->INTERNAL_TEAM_SHORT_TAG, RenX::getTeamName(player->team)); - msg.replace(this->INTERNAL_TEAM_LONG_TAG, RenX::getFullTeamName(player->team)); - msg.replace(this->INTERNAL_PING_TAG, Jupiter::StringS::Format("%hu", player->ping)); - msg.replace(this->INTERNAL_SCORE_TAG, Jupiter::StringS::Format("%.0f", player->score)); - msg.replace(this->INTERNAL_CREDITS_TAG, Jupiter::StringS::Format("%.0f", player->credits)); - msg.replace(this->INTERNAL_KILLS_TAG, Jupiter::StringS::Format("%u", player->kills)); - msg.replace(this->INTERNAL_DEATHS_TAG, Jupiter::StringS::Format("%u", player->deaths)); - msg.replace(this->INTERNAL_KDR_TAG, Jupiter::StringS::Format("%.2f", static_cast(player->kills) / (player->deaths == 0 ? 1.0f : static_cast(player->deaths)))); - msg.replace(this->INTERNAL_SUICIDES_TAG, Jupiter::StringS::Format("%u", player->suicides)); - msg.replace(this->INTERNAL_HEADSHOTS_TAG, Jupiter::StringS::Format("%u", player->headshots)); - msg.replace(this->INTERNAL_VEHICLE_KILLS_TAG, Jupiter::StringS::Format("%u", player->vehicleKills)); - msg.replace(this->INTERNAL_BUILDING_KILLS_TAG, Jupiter::StringS::Format("%u", player->buildingKills)); - msg.replace(this->INTERNAL_DEFENCE_KILLS_TAG, Jupiter::StringS::Format("%u", player->defenceKills)); - msg.replace(this->INTERNAL_WINS_TAG, Jupiter::StringS::Format("%u", player->wins)); - msg.replace(this->INTERNAL_LOSES_TAG, Jupiter::StringS::Format("%u", player->loses)); - msg.replace(this->INTERNAL_BEACON_PLACEMENTS_TAG, Jupiter::StringS::Format("%u", player->beaconPlacements)); - msg.replace(this->INTERNAL_BEACON_DISARMS_TAG, Jupiter::StringS::Format("%u", player->beaconDisarms)); - msg.replace(this->INTERNAL_CAPTURES_TAG, Jupiter::StringS::Format("%u", player->captures)); - msg.replace(this->INTERNAL_STEALS_TAG, Jupiter::StringS::Format("%u", player->steals)); - msg.replace(this->INTERNAL_STOLEN_TAG, Jupiter::StringS::Format("%u", player->stolen)); - msg.replace(this->INTERNAL_ACCESS_TAG, Jupiter::StringS::Format("%d", player->access)); + PROCESS_TAG(this->INTERNAL_NAME_TAG, RenX::getFormattedPlayerName(player)); + PROCESS_TAG(this->INTERNAL_RAW_NAME_TAG, player->name); + PROCESS_TAG(this->INTERNAL_IP_TAG, player->ip); + PROCESS_TAG(this->INTERNAL_UUID_TAG, player->uuid); + PROCESS_TAG(this->INTERNAL_ID_TAG, Jupiter::StringS::Format("%d", player->id)); + PROCESS_TAG(this->INTERNAL_CHARACTER_TAG, RenX::translateName(player->character)); + PROCESS_TAG(this->INTERNAL_VEHICLE_TAG, RenX::translateName(player->vehicle)); + PROCESS_TAG(this->INTERNAL_ADMIN_TAG, player->adminType); + PROCESS_TAG(this->INTERNAL_PREFIX_TAG, player->formatNamePrefix); + PROCESS_TAG(this->INTERNAL_GAME_PREFIX_TAG, player->gamePrefix); + PROCESS_TAG(this->INTERNAL_TEAM_COLOR_TAG, RenX::getTeamColor(player->team)); + PROCESS_TAG(this->INTERNAL_TEAM_SHORT_TAG, RenX::getTeamName(player->team)); + PROCESS_TAG(this->INTERNAL_TEAM_LONG_TAG, RenX::getFullTeamName(player->team)); + PROCESS_TAG(this->INTERNAL_PING_TAG, Jupiter::StringS::Format("%hu", player->ping)); + PROCESS_TAG(this->INTERNAL_SCORE_TAG, Jupiter::StringS::Format("%.0f", player->score)); + PROCESS_TAG(this->INTERNAL_CREDITS_TAG, Jupiter::StringS::Format("%.0f", player->credits)); + PROCESS_TAG(this->INTERNAL_KILLS_TAG, Jupiter::StringS::Format("%u", player->kills)); + PROCESS_TAG(this->INTERNAL_DEATHS_TAG, Jupiter::StringS::Format("%u", player->deaths)); + PROCESS_TAG(this->INTERNAL_KDR_TAG, Jupiter::StringS::Format("%.2f", static_cast(player->kills) / (player->deaths == 0 ? 1.0f : static_cast(player->deaths)))); + PROCESS_TAG(this->INTERNAL_SUICIDES_TAG, Jupiter::StringS::Format("%u", player->suicides)); + PROCESS_TAG(this->INTERNAL_HEADSHOTS_TAG, Jupiter::StringS::Format("%u", player->headshots)); + PROCESS_TAG(this->INTERNAL_VEHICLE_KILLS_TAG, Jupiter::StringS::Format("%u", player->vehicleKills)); + PROCESS_TAG(this->INTERNAL_BUILDING_KILLS_TAG, Jupiter::StringS::Format("%u", player->buildingKills)); + PROCESS_TAG(this->INTERNAL_DEFENCE_KILLS_TAG, Jupiter::StringS::Format("%u", player->defenceKills)); + PROCESS_TAG(this->INTERNAL_WINS_TAG, Jupiter::StringS::Format("%u", player->wins)); + PROCESS_TAG(this->INTERNAL_LOSES_TAG, Jupiter::StringS::Format("%u", player->loses)); + PROCESS_TAG(this->INTERNAL_BEACON_PLACEMENTS_TAG, Jupiter::StringS::Format("%u", player->beaconPlacements)); + PROCESS_TAG(this->INTERNAL_BEACON_DISARMS_TAG, Jupiter::StringS::Format("%u", player->beaconDisarms)); + PROCESS_TAG(this->INTERNAL_CAPTURES_TAG, Jupiter::StringS::Format("%u", player->captures)); + PROCESS_TAG(this->INTERNAL_STEALS_TAG, Jupiter::StringS::Format("%u", player->steals)); + PROCESS_TAG(this->INTERNAL_STOLEN_TAG, Jupiter::StringS::Format("%u", player->stolen)); + PROCESS_TAG(this->INTERNAL_ACCESS_TAG, Jupiter::StringS::Format("%d", player->access)); } if (victim != nullptr) { - msg.replace(this->INTERNAL_VICTIM_NAME_TAG, RenX::getFormattedPlayerName(victim)); - msg.replace(this->INTERNAL_VICTIM_RAW_NAME_TAG, victim->name); - msg.replace(this->INTERNAL_VICTIM_IP_TAG, victim->ip); - msg.replace(this->INTERNAL_VICTIM_UUID_TAG, victim->uuid); - msg.replace(this->INTERNAL_VICTIM_ID_TAG, Jupiter::StringS::Format("%d", victim->id)); - msg.replace(this->INTERNAL_VICTIM_CHARACTER_TAG, RenX::translateName(victim->character)); - msg.replace(this->INTERNAL_VICTIM_VEHICLE_TAG, RenX::translateName(victim->vehicle)); - msg.replace(this->INTERNAL_VICTIM_ADMIN_TAG, victim->adminType); - msg.replace(this->INTERNAL_VICTIM_PREFIX_TAG, victim->formatNamePrefix); - msg.replace(this->INTERNAL_VICTIM_GAME_PREFIX_TAG, victim->gamePrefix); - msg.replace(this->INTERNAL_VICTIM_TEAM_COLOR_TAG, RenX::getTeamColor(victim->team)); - msg.replace(this->INTERNAL_VICTIM_TEAM_SHORT_TAG, RenX::getTeamName(victim->team)); - msg.replace(this->INTERNAL_VICTIM_TEAM_LONG_TAG, RenX::getFullTeamName(victim->team)); - msg.replace(this->INTERNAL_VICTIM_PING_TAG, Jupiter::StringS::Format("%hu", victim->ping)); - msg.replace(this->INTERNAL_VICTIM_SCORE_TAG, Jupiter::StringS::Format("%.0f", victim->score)); - msg.replace(this->INTERNAL_VICTIM_CREDITS_TAG, Jupiter::StringS::Format("%.0f", victim->credits)); - msg.replace(this->INTERNAL_VICTIM_KILLS_TAG, Jupiter::StringS::Format("%u", victim->kills)); - msg.replace(this->INTERNAL_VICTIM_DEATHS_TAG, Jupiter::StringS::Format("%u", victim->deaths)); - msg.replace(this->INTERNAL_VICTIM_KDR_TAG, Jupiter::StringS::Format("%.2f", static_cast(victim->kills) / (victim->deaths == 0 ? 1.0f : static_cast(victim->deaths)))); - msg.replace(this->INTERNAL_VICTIM_SUICIDES_TAG, Jupiter::StringS::Format("%u", victim->suicides)); - msg.replace(this->INTERNAL_VICTIM_HEADSHOTS_TAG, Jupiter::StringS::Format("%u", victim->headshots)); - msg.replace(this->INTERNAL_VICTIM_VEHICLE_KILLS_TAG, Jupiter::StringS::Format("%u", victim->vehicleKills)); - msg.replace(this->INTERNAL_VICTIM_BUILDING_KILLS_TAG, Jupiter::StringS::Format("%u", victim->buildingKills)); - msg.replace(this->INTERNAL_VICTIM_DEFENCE_KILLS_TAG, Jupiter::StringS::Format("%u", victim->defenceKills)); - msg.replace(this->INTERNAL_VICTIM_WINS_TAG, Jupiter::StringS::Format("%u", victim->wins)); - msg.replace(this->INTERNAL_VICTIM_LOSES_TAG, Jupiter::StringS::Format("%u", victim->loses)); - msg.replace(this->INTERNAL_VICTIM_BEACON_PLACEMENTS_TAG, Jupiter::StringS::Format("%u", victim->beaconPlacements)); - msg.replace(this->INTERNAL_VICTIM_BEACON_DISARMS_TAG, Jupiter::StringS::Format("%u", victim->beaconDisarms)); - msg.replace(this->INTERNAL_VICTIM_CAPTURES_TAG, Jupiter::StringS::Format("%u", victim->captures)); - msg.replace(this->INTERNAL_VICTIM_STEALS_TAG, Jupiter::StringS::Format("%u", victim->steals)); - msg.replace(this->INTERNAL_VICTIM_STOLEN_TAG, Jupiter::StringS::Format("%u", victim->stolen)); - msg.replace(this->INTERNAL_VICTIM_ACCESS_TAG, Jupiter::StringS::Format("%d", victim->access)); + PROCESS_TAG(this->INTERNAL_VICTIM_NAME_TAG, RenX::getFormattedPlayerName(victim)); + PROCESS_TAG(this->INTERNAL_VICTIM_RAW_NAME_TAG, victim->name); + PROCESS_TAG(this->INTERNAL_VICTIM_IP_TAG, victim->ip); + PROCESS_TAG(this->INTERNAL_VICTIM_UUID_TAG, victim->uuid); + PROCESS_TAG(this->INTERNAL_VICTIM_ID_TAG, Jupiter::StringS::Format("%d", victim->id)); + PROCESS_TAG(this->INTERNAL_VICTIM_CHARACTER_TAG, RenX::translateName(victim->character)); + PROCESS_TAG(this->INTERNAL_VICTIM_VEHICLE_TAG, RenX::translateName(victim->vehicle)); + PROCESS_TAG(this->INTERNAL_VICTIM_ADMIN_TAG, victim->adminType); + PROCESS_TAG(this->INTERNAL_VICTIM_PREFIX_TAG, victim->formatNamePrefix); + PROCESS_TAG(this->INTERNAL_VICTIM_GAME_PREFIX_TAG, victim->gamePrefix); + PROCESS_TAG(this->INTERNAL_VICTIM_TEAM_COLOR_TAG, RenX::getTeamColor(victim->team)); + PROCESS_TAG(this->INTERNAL_VICTIM_TEAM_SHORT_TAG, RenX::getTeamName(victim->team)); + PROCESS_TAG(this->INTERNAL_VICTIM_TEAM_LONG_TAG, RenX::getFullTeamName(victim->team)); + PROCESS_TAG(this->INTERNAL_VICTIM_PING_TAG, Jupiter::StringS::Format("%hu", victim->ping)); + PROCESS_TAG(this->INTERNAL_VICTIM_SCORE_TAG, Jupiter::StringS::Format("%.0f", victim->score)); + PROCESS_TAG(this->INTERNAL_VICTIM_CREDITS_TAG, Jupiter::StringS::Format("%.0f", victim->credits)); + PROCESS_TAG(this->INTERNAL_VICTIM_KILLS_TAG, Jupiter::StringS::Format("%u", victim->kills)); + PROCESS_TAG(this->INTERNAL_VICTIM_DEATHS_TAG, Jupiter::StringS::Format("%u", victim->deaths)); + PROCESS_TAG(this->INTERNAL_VICTIM_KDR_TAG, Jupiter::StringS::Format("%.2f", static_cast(victim->kills) / (victim->deaths == 0 ? 1.0f : static_cast(victim->deaths)))); + PROCESS_TAG(this->INTERNAL_VICTIM_SUICIDES_TAG, Jupiter::StringS::Format("%u", victim->suicides)); + PROCESS_TAG(this->INTERNAL_VICTIM_HEADSHOTS_TAG, Jupiter::StringS::Format("%u", victim->headshots)); + PROCESS_TAG(this->INTERNAL_VICTIM_VEHICLE_KILLS_TAG, Jupiter::StringS::Format("%u", victim->vehicleKills)); + PROCESS_TAG(this->INTERNAL_VICTIM_BUILDING_KILLS_TAG, Jupiter::StringS::Format("%u", victim->buildingKills)); + PROCESS_TAG(this->INTERNAL_VICTIM_DEFENCE_KILLS_TAG, Jupiter::StringS::Format("%u", victim->defenceKills)); + PROCESS_TAG(this->INTERNAL_VICTIM_WINS_TAG, Jupiter::StringS::Format("%u", victim->wins)); + PROCESS_TAG(this->INTERNAL_VICTIM_LOSES_TAG, Jupiter::StringS::Format("%u", victim->loses)); + PROCESS_TAG(this->INTERNAL_VICTIM_BEACON_PLACEMENTS_TAG, Jupiter::StringS::Format("%u", victim->beaconPlacements)); + PROCESS_TAG(this->INTERNAL_VICTIM_BEACON_DISARMS_TAG, Jupiter::StringS::Format("%u", victim->beaconDisarms)); + PROCESS_TAG(this->INTERNAL_VICTIM_CAPTURES_TAG, Jupiter::StringS::Format("%u", victim->captures)); + PROCESS_TAG(this->INTERNAL_VICTIM_STEALS_TAG, Jupiter::StringS::Format("%u", victim->steals)); + PROCESS_TAG(this->INTERNAL_VICTIM_STOLEN_TAG, Jupiter::StringS::Format("%u", victim->stolen)); + PROCESS_TAG(this->INTERNAL_VICTIM_ACCESS_TAG, Jupiter::StringS::Format("%d", victim->access)); } Jupiter::ArrayList &xPlugins = *RenX::getCore()->getPlugins();