diff --git a/Release/Plugins/RenX.Core.lib b/Release/Plugins/RenX.Core.lib index 1d8d80e..c94365f 100644 Binary files a/Release/Plugins/RenX.Core.lib and b/Release/Plugins/RenX.Core.lib differ diff --git a/RenX.Commands/RenX_Commands.cpp b/RenX.Commands/RenX_Commands.cpp index bce56cf..44fdd35 100644 --- a/RenX.Commands/RenX_Commands.cpp +++ b/RenX.Commands/RenX_Commands.cpp @@ -781,7 +781,7 @@ void RotationIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString Jupiter::IRC::Client::Channel *chan = source->getChannel(channel); if (chan != nullptr) { - const Jupiter::ReadableString *map; + const RenX::Map *map; int type = chan->getType(); Jupiter::String list; size_t index = 0; @@ -794,10 +794,10 @@ void RotationIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString for (index = 0; index != server->maps.size(); ++index) { map = server->maps.get(index); - if (server->getMap().equalsi(*map)) - list += STRING_LITERAL_AS_REFERENCE(" " IRCBOLD "[") + *server->maps.get(index) + STRING_LITERAL_AS_REFERENCE("]" IRCBOLD); + if (server->getMap().name.equalsi(map->name)) + list += STRING_LITERAL_AS_REFERENCE(" " IRCBOLD "[") + server->maps.get(index)->name + STRING_LITERAL_AS_REFERENCE("]" IRCBOLD); else - list += " "_jrs + *server->maps.get(index); + list += " "_jrs + server->maps.get(index)->name; } if (index == 0) source->sendMessage(channel, "No maps in rotation"_jrs); @@ -838,7 +838,8 @@ void MapIRCCommand::trigger(IRC_Bot *source, const Jupiter::ReadableString &chan if (server->isLogChanType(type)) { match = true; - source->sendMessage(channel, "Current Map: "_jrs + server->getMap()); + const RenX::Map &map = server->getMap(); + source->sendMessage(channel, "Current Map: "_jrs + map.name + "; GUID: "_jrs + RenX::formatGUID(map)); } } if (match == false) diff --git a/RenX.Core/RenX.Core.vcxproj b/RenX.Core/RenX.Core.vcxproj index d0ebcb1..db0db01 100644 --- a/RenX.Core/RenX.Core.vcxproj +++ b/RenX.Core/RenX.Core.vcxproj @@ -76,6 +76,7 @@ + @@ -86,6 +87,7 @@ + diff --git a/RenX.Core/RenX.Core.vcxproj.filters b/RenX.Core/RenX.Core.vcxproj.filters index 09f1e2b..1c2ec70 100644 --- a/RenX.Core/RenX.Core.vcxproj.filters +++ b/RenX.Core/RenX.Core.vcxproj.filters @@ -53,6 +53,9 @@ Header Files + + Header Files + @@ -76,5 +79,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/RenX.Core/RenX_Functions.cpp b/RenX.Core/RenX_Functions.cpp index af09fde..2ae9db5 100644 --- a/RenX.Core/RenX_Functions.cpp +++ b/RenX.Core/RenX_Functions.cpp @@ -862,6 +862,11 @@ Jupiter::String RenX::getFormattedPlayerName(const RenX::PlayerInfo *player) return r; } +Jupiter::StringS RenX::formatGUID(const RenX::Map &map) +{ + return Jupiter::StringS::Format("%.8llX%.8llX", map.guid[0], map.guid[1]); +} + void RenX::sanitizeString(Jupiter::StringType &str) { if (str.isNotEmpty()) diff --git a/RenX.Core/RenX_Functions.h b/RenX.Core/RenX_Functions.h index 9a4954d..24b807c 100644 --- a/RenX.Core/RenX_Functions.h +++ b/RenX.Core/RenX_Functions.h @@ -28,6 +28,7 @@ #include "Jupiter/INIFile.h" #include "Jupiter/String.h" #include "RenX.h" +#include "RenX_Map.h" namespace RenX { @@ -136,6 +137,14 @@ namespace RenX */ RENX_API Jupiter::String getFormattedPlayerName(const RenX::PlayerInfo *player); + /** + * @brief Creates a string containing a human-readable version of a map's GUID + * + * @param map Map containing the GUID to interpret + * @return Human-readable map GUID + */ + RENX_API Jupiter::StringS formatGUID(const RenX::Map &map); + /** * @brief Sanitizes a string into a RCON-ready state by replacing special * characters with HTML-style character codes. diff --git a/RenX.Core/RenX_Map.cpp b/RenX.Core/RenX_Map.cpp new file mode 100644 index 0000000..67bc89a --- /dev/null +++ b/RenX.Core/RenX_Map.cpp @@ -0,0 +1,41 @@ +/** + * Copyright (C) 2016 Jessica James. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Written by Jessica James + */ + +#include "RenX_Map.h" + +RenX::Map::Map() +{ + RenX::Map::Map::guid[0] = 0ULL; + RenX::Map::Map::guid[1] = 0ULL; +} + +RenX::Map::Map(const Jupiter::ReadableString &in_name) : Map() +{ + name = in_name; +} + +RenX::Map::Map(const Jupiter::ReadableString &in_name, uint64_t in_guid[2]) : Map(in_name) +{ + RenX::Map::Map::guid[0] = in_guid[0]; + RenX::Map::Map::guid[1] = in_guid[1]; +} + +bool RenX::Map::equals(const RenX::Map &map) const +{ + return RenX::Map::Map::guid[0] == map.guid[0] && RenX::Map::Map::guid[1] == map.guid[1]; +} \ No newline at end of file diff --git a/RenX.Core/RenX_Map.h b/RenX.Core/RenX_Map.h new file mode 100644 index 0000000..1d80f12 --- /dev/null +++ b/RenX.Core/RenX_Map.h @@ -0,0 +1,57 @@ +/** + * Copyright (C) 2016 Jessica James. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Written by Jessica James + */ + +#if !defined _RENX_MAP_H_HEADER +#define _RENX_MAP_H_HEADER + +/** + * @file RenX_Map.h + * @brief Defines the RenX Map class + */ + +#include "Jupiter/String.h" +#include "RenX.h" + +/** DLL Linkage Nagging */ +#if defined _MSC_VER +#pragma warning(push) +#pragma warning(disable: 4251) +#endif + +namespace RenX +{ + struct RENX_API Map + { + uint64_t guid[2]; + Jupiter::StringS name; + + bool equals(const RenX::Map &map) const; + + Map(); + Map(const Jupiter::ReadableString &in_name); + Map(const Jupiter::ReadableString &in_name, uint64_t in_guid[2]); + }; +} + + +/** Re-enable warnings */ +#if defined _MSC_VER +#pragma warning(pop) +#endif + +#endif // _RENX_MAP_H_HEADER \ No newline at end of file diff --git a/RenX.Core/RenX_Server.cpp b/RenX.Core/RenX_Server.cpp index ae074e7..5da41b2 100644 --- a/RenX.Core/RenX_Server.cpp +++ b/RenX.Core/RenX_Server.cpp @@ -238,7 +238,7 @@ bool RenX::Server::hasMapInRotation(const Jupiter::ReadableString &name) const { size_t index = RenX::Server::maps.size(); while (index != 0) - if (RenX::Server::maps.get(--index)->equalsi(name)) + if (RenX::Server::maps.get(--index)->name.equalsi(name)) return true; return false; } @@ -249,7 +249,7 @@ const Jupiter::ReadableString *RenX::Server::getMapName(const Jupiter::ReadableS const Jupiter::ReadableString *map_name; while (index != 0) { - map_name = RenX::Server::maps.get(--index); + map_name = &RenX::Server::maps.get(--index)->name; if (map_name->findi(name) != Jupiter::INVALID_INDEX) return map_name; } @@ -837,7 +837,7 @@ const Jupiter::ReadableString &RenX::Server::getName() const return RenX::Server::serverName; } -const Jupiter::ReadableString &RenX::Server::getMap() const +const RenX::Map &RenX::Server::getMap() const { return RenX::Server::map; } @@ -1599,15 +1599,32 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) else if (this->lastCommand.equalsi("ping")) RenX::Server::awaitingPong = false; else if (this->lastCommand.equalsi("map")) - this->map = std::move(Jupiter::StringS::substring(line, 1)); + { + // Map | Guid + this->map.name = tokens.getToken(0); + const Jupiter::ReferenceString guid_token = tokens.getToken(1); + + if (guid_token.size() == 32U) + { + this->map.guid[0] = guid_token.substring(0U, 16U).asUnsignedLongLong(16); + this->map.guid[1] = guid_token.substring(16U).asUnsignedLongLong(16); + } + } else if (this->lastCommand.equalsi("serverinfo")) { if (this->lastCommandParams.isEmpty()) { - // "Port" | Port | "Name" | Name | "Level" | Level | "Players" | Players | "Bots" | Bots + // "Port" | Port | "Name" | Name | "Level" | Level | "Players" | Players | "Bots" | Bots | "LevelGUID" | Level GUID this->port = static_cast(tokens.getToken(1).asUnsignedInt(10)); this->serverName = tokens.getToken(3); - this->map = tokens.getToken(5); + this->map.name = tokens.getToken(5); + + const Jupiter::ReferenceString guid_token = tokens.getToken(11); + if (guid_token.size() == 32U) + { + this->map.guid[0] = guid_token.substring(0U, 16U).asUnsignedLongLong(16); + this->map.guid[1] = guid_token.substring(16U).asUnsignedLongLong(16); + } } } else if (this->lastCommand.equalsi("gameinfo"_jrs)) @@ -1647,10 +1664,22 @@ void RenX::Server::processLine(const Jupiter::ReadableString &line) } else if (this->lastCommand.equalsi("rotation"_jrs)) { - // Map - Jupiter::ReferenceString in_map = Jupiter::ReferenceString::substring(line, 1); + // Map | Guid + const Jupiter::ReadableString &in_map = tokens.getToken(0); if (this->hasMapInRotation(in_map) == false) - this->maps.add(new Jupiter::StringS(in_map)); + { + const Jupiter::ReferenceString guid_token = tokens.getToken(1); + + if (guid_token.size() == 32U) + { + RenX::Map *map = new RenX::Map(in_map); + map->guid[0] = guid_token.substring(0U, 16U).asUnsignedLongLong(16); + map->guid[1] = guid_token.substring(16U).asUnsignedLongLong(16); + this->maps.add(map); + } + else + this->maps.add(new RenX::Map(in_map)); + } } else if (this->lastCommand.equalsi("changename")) { diff --git a/RenX.Core/RenX_Server.h b/RenX.Core/RenX_Server.h index 4fa2ebc..10519fd 100644 --- a/RenX.Core/RenX_Server.h +++ b/RenX.Core/RenX_Server.h @@ -35,6 +35,7 @@ #include "Jupiter/Thinker.h" #include "Jupiter/Rehash.h" #include "RenX.h" +#include "RenX_Map.h" /** DLL Linkage Nagging */ #if defined _MSC_VER @@ -86,7 +87,7 @@ namespace RenX Jupiter::DLList players; /** A list of players in the server */ Jupiter::ArrayList buildings; /** A list of buildings in the server */ Jupiter::ArrayList mutators; /** A list of buildings the server is running */ - Jupiter::ArrayList maps; /** A list of maps in the server's rotation */ + Jupiter::ArrayList maps; /** A list of maps in the server's rotation */ Jupiter::INIFile varData; /** This may be replaced later with a more dedicated type. */ /** @@ -705,7 +706,7 @@ namespace RenX * * @return String containing the current map. */ - const Jupiter::ReadableString &getMap() const; + const RenX::Map &getMap() const; /** * @brief Fetches a command from the list. @@ -949,9 +950,9 @@ namespace RenX Jupiter::StringS rconUser; Jupiter::StringS gameVersion; Jupiter::StringS serverName; - Jupiter::StringS map; Jupiter::StringS lastCommand; Jupiter::StringS lastCommandParams; + RenX::Map map; Jupiter::TCPSocket sock; Jupiter::ReadableString::TokenizeResult commandListFormat; Jupiter::ArrayList commands; diff --git a/RenX.Core/RenX_Tags.cpp b/RenX.Core/RenX_Tags.cpp index e6c4c7e..d0a3e88 100644 --- a/RenX.Core/RenX_Tags.cpp +++ b/RenX.Core/RenX_Tags.cpp @@ -76,6 +76,7 @@ TagsImp::TagsImp() this->INTERNAL_USER_TAG = this->getUniqueInternalTag(); this->INTERNAL_SERVER_NAME_TAG = this->getUniqueInternalTag(); this->INTERNAL_MAP_TAG = this->getUniqueInternalTag(); + this->INTERNAL_MAP_GUID_TAG = this->getUniqueInternalTag(); this->INTERNAL_SERVER_HOSTNAME_TAG = this->getUniqueInternalTag(); this->INTERNAL_SERVER_PORT_TAG = this->getUniqueInternalTag(); this->INTERNAL_SOCKET_HOSTNAME_TAG = this->getUniqueInternalTag(); @@ -186,6 +187,7 @@ TagsImp::TagsImp() this->userTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("UserTag"), STRING_LITERAL_AS_REFERENCE("{USER}")); this->serverNameTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("ServerNameTag"), STRING_LITERAL_AS_REFERENCE("{SERVERNAME}")); this->mapTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("MapTag"), STRING_LITERAL_AS_REFERENCE("{MAP}")); + this->mapGUIDTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("MapGUIDTag"), STRING_LITERAL_AS_REFERENCE("{MGUID}")); this->serverHostnameTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("ServerHostnameTag"), STRING_LITERAL_AS_REFERENCE("{SERVERHOST}")); this->serverPortTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("ServerPortTag"), STRING_LITERAL_AS_REFERENCE("{SERVERPORT}")); this->socketHostnameTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("SocketHostnameTag"), STRING_LITERAL_AS_REFERENCE("{SOCKHOST}")); @@ -336,7 +338,8 @@ void TagsImp::processTags(Jupiter::StringType &msg, const RenX::Server *server, 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_MAP_TAG, server->getMap().name); + PROCESS_TAG(this->INTERNAL_MAP_GUID_TAG, RenX::formatGUID(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()); @@ -454,6 +457,7 @@ void TagsImp::sanitizeTags(Jupiter::StringType &fmt) fmt.replace(this->userTag, this->INTERNAL_USER_TAG); fmt.replace(this->serverNameTag, this->INTERNAL_SERVER_NAME_TAG); fmt.replace(this->mapTag, this->INTERNAL_MAP_TAG); + fmt.replace(this->mapGUIDTag, this->INTERNAL_MAP_GUID_TAG); fmt.replace(this->serverHostnameTag, this->INTERNAL_SERVER_HOSTNAME_TAG); fmt.replace(this->serverPortTag, this->INTERNAL_SERVER_PORT_TAG); fmt.replace(this->socketHostnameTag, this->INTERNAL_SOCKET_HOSTNAME_TAG); diff --git a/RenX.Core/RenX_Tags.h b/RenX.Core/RenX_Tags.h index 9c56377..37bcded 100644 --- a/RenX.Core/RenX_Tags.h +++ b/RenX.Core/RenX_Tags.h @@ -61,6 +61,7 @@ namespace RenX Jupiter::StringS INTERNAL_USER_TAG; Jupiter::StringS INTERNAL_SERVER_NAME_TAG; Jupiter::StringS INTERNAL_MAP_TAG; + Jupiter::StringS INTERNAL_MAP_GUID_TAG; Jupiter::StringS INTERNAL_SERVER_HOSTNAME_TAG; Jupiter::StringS INTERNAL_SERVER_PORT_TAG; Jupiter::StringS INTERNAL_SOCKET_HOSTNAME_TAG; @@ -171,6 +172,7 @@ namespace RenX Jupiter::StringS userTag; Jupiter::StringS serverNameTag; Jupiter::StringS mapTag; + Jupiter::StringS mapGUIDTag; Jupiter::StringS serverHostnameTag; Jupiter::StringS serverPortTag; Jupiter::StringS socketHostnameTag;