Browse Source

Moved 'RenX_LadderDatabase' from 'RenX.Ladder' to 'RenX::LadderDatabase' in 'RenX.Core'

Added HTTPServer plugin
Added RenX.Ladder.Web plugin
Adder tag parsing for Ladder entries
Updated Jupiter
pull/3/head
Jessica James 9 years ago
parent
commit
d0bdc387b5
  1. 51
      HTTPServer/HTTPServer.cpp
  2. 75
      HTTPServer/HTTPServer.h
  3. 84
      HTTPServer/HTTPServer.vcxproj
  4. 35
      HTTPServer/HTTPServer.vcxproj.filters
  5. 2
      Jupiter
  6. BIN
      Release/Bot.lib
  7. BIN
      Release/Plugins/RenX.Core.lib
  8. 2
      RenX.Core/RenX.Core.vcxproj
  9. 6
      RenX.Core/RenX.Core.vcxproj.filters
  10. 469
      RenX.Core/RenX_LadderDatabase.cpp
  11. 201
      RenX.Core/RenX_LadderDatabase.h
  12. 4
      RenX.Core/RenX_Server.cpp
  13. 396
      RenX.Core/RenX_Tags.cpp
  14. 82
      RenX.Core/RenX_Tags.h
  15. 86
      RenX.Ladder.Web/RenX.Ladder.Web.vcxproj
  16. 41
      RenX.Ladder.Web/RenX.Ladder.Web.vcxproj.filters
  17. 339
      RenX.Ladder.Web/RenX_Ladder_Web.cpp
  18. 66
      RenX.Ladder.Web/RenX_Ladder_Web.h
  19. 4
      RenX.Ladder/RenX.Ladder.vcxproj
  20. 6
      RenX.Ladder/RenX.Ladder.vcxproj.filters
  21. 113
      RenX.Ladder/RenX_Ladder.cpp
  22. 15
      RenX.Ladder/RenX_Ladder.h
  23. 347
      RenX.Ladder/RenX_LadderDatabase.cpp
  24. 158
      RenX.Ladder/RenX_LadderDatabase.h
  25. 4
      RenX.Listen/RenX_Listen.cpp

51
HTTPServer/HTTPServer.cpp

@ -0,0 +1,51 @@
/**
* Copyright (C) 2015-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 <jessica.aj@outlook.com>
*/
#include "Jupiter/INIFile.h"
#include "Jupiter/IRC_Client.h"
#include "HTTPServer.h"
using namespace Jupiter::literals;
HTTPServerPlugin::HTTPServerPlugin()
{
HTTPServerPlugin::server.bind(Jupiter::IRC::Client::Config->get(HTTPServerPlugin::name, "BindAddress"_jrs, "0.0.0.0"_jrs), Jupiter::IRC::Client::Config->getInt(HTTPServerPlugin::name, "BindPort"_jrs, 80));
}
int HTTPServerPlugin::think()
{
return HTTPServerPlugin::server.think();
}
// Plugin instantiation and entry point.
HTTPServerPlugin pluginInstance;
HTTPServerPlugin &getHTTPServerPlugin()
{
return pluginInstance;
}
Jupiter::HTTP::Server &getHTTPServer()
{
return pluginInstance.server;
}
extern "C" __declspec(dllexport) Jupiter::Plugin *getPlugin()
{
return &pluginInstance;
}

75
HTTPServer/HTTPServer.h

@ -0,0 +1,75 @@
/**
* Copyright (C) 2015 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 <jessica.aj@outlook.com>
*/
#if !defined _HTTPSERVER_H_HEADER
#define _HTTPSERVER_H_HEADER
/**
* @file HTTPServer.h
* @brief Provides an interface to push HTTP data to HTTP clients.
*/
#if defined _WIN32
#include "Jupiter/Plugin.h"
#include "Jupiter/Reference_String.h"
#include "Jupiter/String.h"
#include "Jupiter/HTTP_Server.h"
#if defined HTTPSERVER_EXPORTS
#define HTTPSERVER_API __declspec(dllexport)
#else // HTTPSERVER_EXPORTS
#define HTTPSERVER_API __declspec(dllimport)
#endif // HTTPSERVER_EXPORTS
#else // _WIN32
#define HTTPSERVER_API
#endif // _WIN32
/** DLL Linkage Nagging */
#if defined _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4251)
#endif
/**
* @brief Instantiates an instance of Jupiter::HTTP::Server to permit declaration of HTTP pages.
*/
class HTTPSERVER_API HTTPServerPlugin : public Jupiter::Plugin
{
public:
HTTPServerPlugin();
Jupiter::HTTP::Server server;
public: // Jupiter::Plugin
const Jupiter::ReadableString &getName() override { return name; }
int think() override;
private:
STRING_LITERAL_AS_NAMED_REFERENCE(name, "HTTPServer");
};
HTTPSERVER_API HTTPServerPlugin &getHTTPServerPlugin();
HTTPSERVER_API Jupiter::HTTP::Server &getHTTPServer();
/** Re-enable warnings */
#if defined _MSC_VER
#pragma warning(pop)
#endif
#endif // _HTTPSERVER_H_HEADER

84
HTTPServer/HTTPServer.vcxproj

@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{BB048D6F-F001-4E9B-95F4-886081E0807A}</ProjectGuid>
<RootNamespace>HTTPServer</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(SolutionDir)$(Configuration)\Plugins\</OutDir>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>../Bot;../Jupiter</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;HTTPSERVER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="HTTPServer.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="HTTPServer.cpp" />
</ItemGroup>
<ItemGroup>
<Library Include="..\Jupiter\Release\Jupiter.lib" />
<Library Include="..\Release\Bot.lib" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

35
HTTPServer/HTTPServer.vcxproj.filters

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<Library Include="..\Release\Bot.lib">
<Filter>Resource Files</Filter>
</Library>
<Library Include="..\Jupiter\Release\Jupiter.lib">
<Filter>Resource Files</Filter>
</Library>
</ItemGroup>
<ItemGroup>
<ClInclude Include="HTTPServer.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="HTTPServer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

2
Jupiter

@ -1 +1 @@
Subproject commit 993a313b81c7fa061d0101bdc2ac101b8b5e2114
Subproject commit 0fba343102afa3d397e613c85ca451d0085522f8

BIN
Release/Bot.lib

Binary file not shown.

BIN
Release/Plugins/RenX.Core.lib

Binary file not shown.

2
RenX.Core/RenX.Core.vcxproj

@ -77,6 +77,7 @@
<ClInclude Include="RenX_ExemptionDatabase.h" />
<ClInclude Include="RenX_Functions.h" />
<ClInclude Include="RenX_GameCommand.h" />
<ClInclude Include="RenX_LadderDatabase.h" />
<ClInclude Include="RenX_Map.h" />
<ClInclude Include="RenX_PlayerInfo.h" />
<ClInclude Include="RenX_Plugin.h" />
@ -89,6 +90,7 @@
<ClCompile Include="RenX_ExemptionDatabase.cpp" />
<ClCompile Include="RenX_Functions.cpp" />
<ClCompile Include="RenX_GameCommand.cpp" />
<ClCompile Include="RenX_LadderDatabase.cpp" />
<ClCompile Include="RenX_Map.cpp" />
<ClCompile Include="RenX_Plugin.cpp" />
<ClCompile Include="RenX_Server.cpp" />

6
RenX.Core/RenX.Core.vcxproj.filters

@ -59,6 +59,9 @@
<ClInclude Include="RenX_ExemptionDatabase.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="RenX_LadderDatabase.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="RenX_Plugin.cpp">
@ -88,5 +91,8 @@
<ClCompile Include="RenX_ExemptionDatabase.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="RenX_LadderDatabase.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

469
RenX.Core/RenX_LadderDatabase.cpp

@ -0,0 +1,469 @@
/**
* Copyright (C) 2015-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 <jessica.aj@outlook.com>
*/
#include "RenX_LadderDatabase.h"
#include "RenX_Server.h"
#include "RenX_PlayerInfo.h"
#include "RenX_BanDatabase.h"
Jupiter::ArrayList<RenX::LadderDatabase> _ladder_databases;
Jupiter::ArrayList<RenX::LadderDatabase> &RenX::ladder_databases = _ladder_databases;
RenX::LadderDatabase::LadderDatabase()
{
_ladder_databases.add(this);
}
RenX::LadderDatabase::~LadderDatabase()
{
while (RenX::LadderDatabase::head != nullptr)
{
RenX::LadderDatabase::end = RenX::LadderDatabase::head;
RenX::LadderDatabase::head = RenX::LadderDatabase::head->next;
delete RenX::LadderDatabase::end;
}
}
void RenX::LadderDatabase::process_data(Jupiter::DataBuffer &buffer, FILE *file, fpos_t pos)
{
RenX::LadderDatabase::Entry *entry = new RenX::LadderDatabase::Entry();
// read data from buffer to entry
entry->steam_id = buffer.pop<uint64_t>();
entry->total_score = buffer.pop<uint64_t>();
entry->total_kills = buffer.pop<uint32_t>();
entry->total_deaths = buffer.pop<uint32_t>();
entry->total_headshot_kills = buffer.pop<uint32_t>();
entry->total_vehicle_kills = buffer.pop<uint32_t>();
entry->total_building_kills = buffer.pop<uint32_t>();
entry->total_defence_kills = buffer.pop<uint32_t>();
entry->total_captures = buffer.pop<uint32_t>();
entry->total_game_time = buffer.pop<uint32_t>();
entry->total_games = buffer.pop<uint32_t>();
entry->total_gdi_games = buffer.pop<uint32_t>();
entry->total_nod_games = buffer.pop<uint32_t>();
entry->total_wins = buffer.pop<uint32_t>();
entry->total_gdi_wins = buffer.pop<uint32_t>();
entry->total_nod_wins = buffer.pop<uint32_t>();
entry->total_beacon_placements = buffer.pop<uint32_t>();
entry->total_beacon_disarms = buffer.pop<uint32_t>();
entry->total_proxy_placements = buffer.pop<uint32_t>();
entry->total_proxy_disarms = buffer.pop<uint32_t>();
entry->top_score = buffer.pop<uint32_t>();
entry->top_kills = buffer.pop<uint32_t>();
entry->most_deaths = buffer.pop<uint32_t>();
entry->top_headshot_kills = buffer.pop<uint32_t>();
entry->top_vehicle_kills = buffer.pop<uint32_t>();
entry->top_building_kills = buffer.pop<uint32_t>();
entry->top_defence_kills = buffer.pop<uint32_t>();
entry->top_captures = buffer.pop<uint32_t>();
entry->top_game_time = buffer.pop<uint32_t>();
entry->top_beacon_placements = buffer.pop<uint32_t>();
entry->top_beacon_disarms = buffer.pop<uint32_t>();
entry->top_proxy_placements = buffer.pop<uint32_t>();
entry->top_proxy_disarms = buffer.pop<uint32_t>();
entry->most_recent_ip = buffer.pop<uint32_t>();
entry->last_game = buffer.pop<time_t>();
entry->most_recent_name = buffer.pop<Jupiter::String_Strict, char>();
// push data to list
if (RenX::LadderDatabase::head == nullptr)
{
RenX::LadderDatabase::head = entry;
RenX::LadderDatabase::end = RenX::LadderDatabase::head;
}
else
{
RenX::LadderDatabase::end->next = entry;
entry->prev = end;
end = entry;
}
entry->rank = ++RenX::LadderDatabase::entries;
}
void RenX::LadderDatabase::process_header(FILE *file)
{
int chr = fgetc(file);
if (chr != EOF)
RenX::LadderDatabase::read_version = chr;
}
void RenX::LadderDatabase::create_header(FILE *file)
{
fputc(RenX::LadderDatabase::write_version, file);
}
RenX::LadderDatabase::Entry *RenX::LadderDatabase::getHead() const
{
return RenX::LadderDatabase::head;
}
RenX::LadderDatabase::Entry *RenX::LadderDatabase::getPlayerEntry(uint64_t steamid) const
{
for (RenX::LadderDatabase::Entry *itr = RenX::LadderDatabase::head; itr != nullptr; itr = itr->next)
if (itr->steam_id == steamid)
return itr;
return nullptr;
}
std::pair<RenX::LadderDatabase::Entry *, size_t> RenX::LadderDatabase::getPlayerEntryAndIndex(uint64_t steamid) const
{
size_t index = 0;
for (RenX::LadderDatabase::Entry *itr = RenX::LadderDatabase::head; itr != nullptr; itr = itr->next, ++index)
if (itr->steam_id == steamid)
return std::pair<RenX::LadderDatabase::Entry *, size_t>(itr, index);
return std::pair<RenX::LadderDatabase::Entry *, size_t>(nullptr, Jupiter::INVALID_INDEX);
}
RenX::LadderDatabase::Entry *RenX::LadderDatabase::getPlayerEntryByName(const Jupiter::ReadableString &name) const
{
for (RenX::LadderDatabase::Entry *itr = RenX::LadderDatabase::head; itr != nullptr; itr = itr->next)
if (itr->most_recent_name.equalsi(name))
return itr;
return nullptr;
}
std::pair<RenX::LadderDatabase::Entry *, size_t> RenX::LadderDatabase::getPlayerEntryAndIndexByName(const Jupiter::ReadableString &name) const
{
size_t index = 0;
for (RenX::LadderDatabase::Entry *itr = RenX::LadderDatabase::head; itr != nullptr; itr = itr->next, ++index)
if (itr->most_recent_name.equalsi(name))
return std::pair<RenX::LadderDatabase::Entry *, size_t>(itr, index);
return std::pair<RenX::LadderDatabase::Entry *, size_t>(nullptr, Jupiter::INVALID_INDEX);
}
RenX::LadderDatabase::Entry *RenX::LadderDatabase::getPlayerEntryByPartName(const Jupiter::ReadableString &name) const
{
for (RenX::LadderDatabase::Entry *itr = RenX::LadderDatabase::head; itr != nullptr; itr = itr->next)
if (itr->most_recent_name.findi(name) != Jupiter::INVALID_INDEX)
return itr;
return nullptr;
}
std::pair<RenX::LadderDatabase::Entry *, size_t> RenX::LadderDatabase::getPlayerEntryAndIndexByPartName(const Jupiter::ReadableString &name) const
{
size_t index = 0;
for (RenX::LadderDatabase::Entry *itr = RenX::LadderDatabase::head; itr != nullptr; itr = itr->next, ++index)
if (itr->most_recent_name.findi(name) != Jupiter::INVALID_INDEX)
return std::pair<RenX::LadderDatabase::Entry *, size_t>(itr, index);
return std::pair<RenX::LadderDatabase::Entry *, size_t>(nullptr, Jupiter::INVALID_INDEX);
}
Jupiter::SLList<RenX::LadderDatabase::Entry> RenX::LadderDatabase::getPlayerEntriesByPartName(const Jupiter::ReadableString &name, size_t max) const
{
Jupiter::SLList<RenX::LadderDatabase::Entry> list;
if (max == 0)
{
for (RenX::LadderDatabase::Entry *itr = RenX::LadderDatabase::head; itr != nullptr; itr = itr->next)
if (itr->most_recent_name.findi(name) != Jupiter::INVALID_INDEX)
list.add(new RenX::LadderDatabase::Entry(*itr));
}
else
for (RenX::LadderDatabase::Entry *itr = RenX::LadderDatabase::head; itr != nullptr; itr = itr->next)
if (itr->most_recent_name.findi(name) != Jupiter::INVALID_INDEX)
{
list.add(new RenX::LadderDatabase::Entry(*itr));
if (--max == 0)
return list;
}
return list;
}
Jupiter::SLList<std::pair<RenX::LadderDatabase::Entry, size_t>> RenX::LadderDatabase::getPlayerEntriesAndIndexByPartName(const Jupiter::ReadableString &name, size_t max) const
{
Jupiter::SLList<std::pair<RenX::LadderDatabase::Entry, size_t>> list;
size_t index = 0;
if (max == 0)
{
for (RenX::LadderDatabase::Entry *itr = RenX::LadderDatabase::head; itr != nullptr; itr = itr->next, ++index)
if (itr->most_recent_name.findi(name) != Jupiter::INVALID_INDEX)
list.add(new std::pair<RenX::LadderDatabase::Entry, size_t>(*itr, index));
}
else
for (RenX::LadderDatabase::Entry *itr = RenX::LadderDatabase::head; itr != nullptr; itr = itr->next, ++index)
if (itr->most_recent_name.findi(name) != Jupiter::INVALID_INDEX)
{
list.add(new std::pair<RenX::LadderDatabase::Entry, size_t>(*itr, index));
if (--max)
return list;
}
return list;
}
RenX::LadderDatabase::Entry *RenX::LadderDatabase::getPlayerEntryByIndex(size_t index) const
{
for (RenX::LadderDatabase::Entry *itr = RenX::LadderDatabase::head; itr != nullptr; itr = itr->next, --index)
if (index == 0)
return itr;
return nullptr;
}
size_t RenX::LadderDatabase::getEntries() const
{
return RenX::LadderDatabase::entries;
}
std::chrono::steady_clock::time_point RenX::LadderDatabase::getLastSortTime() const
{
return RenX::LadderDatabase::last_sort;
}
void RenX::LadderDatabase::append(RenX::LadderDatabase::Entry *entry)
{
++RenX::LadderDatabase::entries;
if (RenX::LadderDatabase::head == nullptr)
{
RenX::LadderDatabase::head = entry;
RenX::LadderDatabase::end = RenX::LadderDatabase::head;
return;
}
RenX::LadderDatabase::end->next = entry;
entry->prev = RenX::LadderDatabase::end;
RenX::LadderDatabase::end = entry;
}
void RenX::LadderDatabase::write(const Jupiter::CStringType &filename)
{
return RenX::LadderDatabase::write(filename.c_str());
}
void RenX::LadderDatabase::write(const char *filename)
{
if (RenX::LadderDatabase::entries != 0)
{
FILE *file = fopen(filename, "wb");
if (file != nullptr)
{
size_t rank = 0;
Jupiter::DataBuffer buffer;
RenX::LadderDatabase::create_header(file);
RenX::LadderDatabase::Entry *entry = RenX::LadderDatabase::head;
while (entry != nullptr)
{
// update rank
entry->rank = ++rank;
// push data from entry to buffer
buffer.push(entry->steam_id);
buffer.push(entry->total_score);
buffer.push(entry->total_kills);
buffer.push(entry->total_deaths);
buffer.push(entry->total_headshot_kills);
buffer.push(entry->total_vehicle_kills);
buffer.push(entry->total_building_kills);
buffer.push(entry->total_defence_kills);
buffer.push(entry->total_captures);
buffer.push(entry->total_game_time);
buffer.push(entry->total_games);
buffer.push(entry->total_gdi_games);
buffer.push(entry->total_nod_games);
buffer.push(entry->total_wins);
buffer.push(entry->total_gdi_wins);
buffer.push(entry->total_nod_wins);
buffer.push(entry->total_beacon_placements);
buffer.push(entry->total_beacon_disarms);
buffer.push(entry->total_proxy_placements);
buffer.push(entry->total_proxy_disarms);
buffer.push(entry->top_score);
buffer.push(entry->top_kills);
buffer.push(entry->most_deaths);
buffer.push(entry->top_headshot_kills);
buffer.push(entry->top_vehicle_kills);
buffer.push(entry->top_building_kills);
buffer.push(entry->top_defence_kills);
buffer.push(entry->top_captures);
buffer.push(entry->top_game_time);
buffer.push(entry->top_beacon_placements);
buffer.push(entry->top_beacon_disarms);
buffer.push(entry->top_proxy_placements);
buffer.push(entry->top_proxy_disarms);
buffer.push(entry->most_recent_ip);
buffer.push(entry->last_game);
buffer.push(entry->most_recent_name);
// push buffer to file
buffer.push_to(file);
// iterate
entry = entry->next;
}
fclose(file);
}
}
}
void RenX::LadderDatabase::sort_entries()
{
if (RenX::LadderDatabase::entries <= 1)
return;
RenX::LadderDatabase::Entry *itr = RenX::LadderDatabase::head;
RenX::LadderDatabase::Entry *itr2, *ptr;
// iterate forward (search for out-of-order content)
while (itr->next != nullptr)
{
// out-of-order content found
if (itr->next->total_score > itr->total_score)
{
// pull content out
ptr = itr->next;
itr->next = ptr->next;
if (itr->next != nullptr)
itr->next->prev = itr;
// iterate backwards from our iterator, and insert
itr2 = itr;
while (true)
{
if (itr2->prev == nullptr)
{
// push ptr to head
ptr->next = itr2;
ptr->prev = nullptr;
itr2->prev = ptr;
RenX::LadderDatabase::head = ptr;
break;
}
itr2 = itr2->prev;
if (itr2->total_score > ptr->total_score)
{
// insert ptr after itr2
ptr->next = itr2->next;
ptr->next->prev = ptr;
ptr->prev = itr2;
itr2->next = ptr;
break;
}
}
}
else // continue iterating
itr = itr->next;
}
RenX::LadderDatabase::end = itr;
RenX::LadderDatabase::last_sort = std::chrono::steady_clock::now();
}
void RenX::LadderDatabase::updateLadder(RenX::Server *server, const RenX::TeamType &team, bool output_times)
{
if (server->players.size() != 0)
{
// update player stats in memory
RenX::PlayerInfo *player;
RenX::LadderDatabase::Entry *entry;
for (Jupiter::DLList<RenX::PlayerInfo>::Node *node = server->players.getNode(0); node != nullptr; node = node->next)
{
player = node->data;
if (player->steamid != 0 && (player->ban_flags & RenX::BanDatabase::Entry::FLAG_TYPE_LADDER) == 0)
{
entry = RenX::LadderDatabase::getPlayerEntry(player->steamid);
if (entry == nullptr)
{
entry = new RenX::LadderDatabase::Entry();
RenX::LadderDatabase::append(entry);
entry->steam_id = player->steamid;
}
entry->total_score += static_cast<uint64_t>(player->score);
entry->total_kills += player->kills;
entry->total_deaths += player->deaths;
entry->total_headshot_kills += player->headshots;
entry->total_vehicle_kills += player->vehicleKills;
entry->total_building_kills += player->buildingKills;
entry->total_defence_kills += player->defenceKills;
entry->total_captures += player->captures;
entry->total_game_time += static_cast<uint32_t>(std::chrono::duration_cast<std::chrono::seconds>(server->getGameTime(player)).count());
++entry->total_games;
switch (player->team)
{
case RenX::TeamType::GDI:
++entry->total_gdi_games;
if (player->team == team)
++entry->total_wins, ++entry->total_gdi_wins;
break;
case RenX::TeamType::Nod:
++entry->total_nod_games;
if (player->team == team)
++entry->total_wins, ++entry->total_nod_wins;
break;
default:
if (player->team == team)
++entry->total_wins;
break;
}
entry->total_beacon_placements += player->beaconPlacements;
entry->total_beacon_disarms += player->beaconDisarms;
entry->total_proxy_placements += player->proxy_placements;
entry->total_proxy_disarms += player->proxy_disarms;
auto set_if_greater = [](uint32_t &src, const uint32_t &cmp)
{
if (cmp > src)
src = cmp;
};
set_if_greater(entry->top_score, static_cast<uint32_t>(player->score));
set_if_greater(entry->top_kills, player->kills);
set_if_greater(entry->most_deaths, player->deaths);
set_if_greater(entry->top_headshot_kills, player->headshots);
set_if_greater(entry->top_vehicle_kills, player->vehicleKills);
set_if_greater(entry->top_building_kills, player->buildingKills);
set_if_greater(entry->top_defence_kills, player->defenceKills);
set_if_greater(entry->top_captures, player->captures);
set_if_greater(entry->top_game_time, static_cast<uint32_t>(std::chrono::duration_cast<std::chrono::seconds>(server->getGameTime(player)).count()));
set_if_greater(entry->top_beacon_placements, player->beaconPlacements);
set_if_greater(entry->top_beacon_disarms, player->beaconDisarms);
set_if_greater(entry->top_proxy_placements, player->proxy_placements);
set_if_greater(entry->top_proxy_disarms, player->proxy_disarms);
entry->most_recent_ip = player->ip32;
entry->last_game = time(nullptr);
entry->most_recent_name = player->name;
}
}
// sort new stats
std::chrono::steady_clock::time_point start_time = std::chrono::steady_clock::now();
RenX::LadderDatabase::sort_entries();
std::chrono::steady_clock::duration sort_duration = std::chrono::steady_clock::now() - start_time;
// write new stats
start_time = std::chrono::steady_clock::now();
RenX::LadderDatabase::write(this->getFilename());
std::chrono::steady_clock::duration write_duration = std::chrono::steady_clock::now() - start_time;
if (output_times)
{
Jupiter::StringS str = Jupiter::StringS::Format("Ladder: %u entries sorted in %f seconds; Database written in %f seconds." ENDL,
RenX::LadderDatabase::getEntries(),
static_cast<double>(sort_duration.count()) * (static_cast<double>(std::chrono::steady_clock::duration::period::num / static_cast<double>(std::chrono::steady_clock::duration::period::den) * static_cast<double>(std::chrono::seconds::duration::period::den / std::chrono::seconds::duration::period::num))),
static_cast<double>(write_duration.count()) * (static_cast<double>(std::chrono::steady_clock::duration::period::num) / static_cast<double>(std::chrono::steady_clock::duration::period::den) * static_cast<double>(std::chrono::seconds::duration::period::den / std::chrono::seconds::duration::period::num)));
str.println(stdout);
server->sendLogChan(str);
}
}
}

201
RenX.Core/RenX_LadderDatabase.h

@ -0,0 +1,201 @@
/**
* Copyright (C) 2015-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 <jessica.aj@outlook.com>
*/
#if !defined _RENX_LADDERDATABASE_H_HEADER
#define _RENX_LADDERDATABASE_H_HEADER
#include <chrono>
#include "Jupiter/Database.h"
#include "Jupiter/String.h"
#include "Jupiter/SLList.h"
#include "Jupiter/ArrayList.h"
#include "RenX.h"
/** DLL Linkage Nagging */
#if defined _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4251)
#endif
namespace RenX
{
class Server;
class RENX_API LadderDatabase : public Jupiter::Database
{
public: // Jupiter::Database
/**
* @brief Processes a chunk of data in a database.
*
* @param buffer Buffer to process
* @param file File being processed
* @param pos position that the buffer starts at in the file
*/
void process_data(Jupiter::DataBuffer &buffer, FILE *file, fpos_t pos) override;
/**
* @brief Processes the header for a database.
*
* @param file File being processed
*/
void process_header(FILE *file) override;
/**
* @brief Generates a header for a database.
*
* @param file File being created
*/
void create_header(FILE *file) override;
public: // LadderDatabase
struct RENX_API Entry
{
size_t rank;
uint64_t steam_id, total_score;
uint32_t total_kills, total_deaths, total_headshot_kills, total_vehicle_kills, total_building_kills, total_defence_kills, total_captures, total_game_time, total_games, total_gdi_games, total_nod_games, total_wins, total_gdi_wins, total_nod_wins, total_beacon_placements, total_beacon_disarms, total_proxy_placements, total_proxy_disarms, // totals (15)
top_score, top_kills, most_deaths, top_headshot_kills, top_vehicle_kills, top_building_kills, top_defence_kills, top_captures, top_game_time, top_beacon_placements, top_beacon_disarms, top_proxy_placements, top_proxy_disarms, // tops (12)
most_recent_ip; // other (1)
time_t last_game;
Jupiter::StringS most_recent_name;
Entry *next = nullptr;
Entry *prev = nullptr;
};
/**
* @brief Fetches the head of the entry list.
*
* @return Head of the ladder entry list.
*/
Entry *getHead() const;
/**
* @brief Fetches a ladder entry by Steam ID.
*
* @param steamid Steam ID to search ladder for
* @return Ladder entry with a matching steamid if one exists, nullptr otherwise.
*/
Entry *getPlayerEntry(uint64_t steamid) const;
std::pair<Entry *, size_t> getPlayerEntryAndIndex(uint64_t steamid) const;
/**
* @brief Searches for a ladder entry by name
*
* @param name Name to search ladder for
* @return Ladder entry with a matching name if one exists, nullptr otherwise.
*/
Entry *getPlayerEntryByName(const Jupiter::ReadableString &name) const;
std::pair<Entry *, size_t> getPlayerEntryAndIndexByName(const Jupiter::ReadableString &name) const;
/**
* @brief Searches for a ladder entry by part name
*
* @param name Part of name to search ladder for
* @return Ladder entry with a matching name if one exists, nullptr otherwise.
*/
Entry *getPlayerEntryByPartName(const Jupiter::ReadableString &name) const;
std::pair<Entry *, size_t> getPlayerEntryAndIndexByPartName(const Jupiter::ReadableString &name) const;
/**
* @brief Fetches all entries matching a part name.
*
* @param name Part of name to search for
* @param max Maximum number of entries to return
* @return List containing entries with matching names.
*/
Jupiter::SLList<Entry> getPlayerEntriesByPartName(const Jupiter::ReadableString &name, size_t max) const;
Jupiter::SLList<std::pair<Entry, size_t>> getPlayerEntriesAndIndexByPartName(const Jupiter::ReadableString &name, size_t max) const;
/**
* @brief Fetches a ladder entry at a specified index
*
* @param index Index of the element to fetch
* @return Ladder entry with a matching name if one exists, nullptr otherwise.
*/
Entry *getPlayerEntryByIndex(size_t index) const;
/**
* @brief Fetches the total number of ladder entries in the list.
*
* @return Total number of entries.
*/
size_t getEntries() const;
/**
* @brief Returns the last time that the contents of this database object were modified (i.e: initialized or written).
*/
std::chrono::steady_clock::time_point getLastSortTime() const;
/**
* @brief Places a ladder entry at the end of the list, regardless of order
* Note: This does not copy data from the pointer -- the pointer is added to the list.
*
* @param entry Ladder entry to add
*/
void append(Entry *entry);
/**
* @brief Writes the current ladder data to the disk.
*/
void write(const Jupiter::CStringType &filename);
void write(const char *filename);
/**
* @brief Sorts the ladder data in memory.
*/
void sort_entries();
/**
* @brief Pushes the player data from the server into the ladder, sorts the data, and writes it to file storage.
*
* @param server Renegade-X server to pull player data from
* @param team Team which just won
* @param output_times True if the sort/write times should be output, false otherwise.
*/
void updateLadder(RenX::Server *server, const RenX::TeamType &team, bool output_times);
/**
* @brief Constructor for the LadderDatabase class
*/
LadderDatabase();
/**
* @brief Deconstructor for the LadderDatabase class
*/
~LadderDatabase();
private:
/** Database version */
const uint8_t write_version = 0;
uint8_t read_version = write_version;
std::chrono::steady_clock::time_point last_sort = std::chrono::steady_clock::now();
size_t entries = 0;
Entry *head = nullptr;
Entry *end;
};
RENX_API extern Jupiter::ArrayList<RenX::LadderDatabase> &ladder_databases;
}
/** Re-enable warnings */
#if defined _MSC_VER
#pragma warning(pop)
#endif
#endif //_RENX_LADDERDATABASE_H_HEADER

4
RenX.Core/RenX_Server.cpp

@ -2762,7 +2762,7 @@ void RenX::Server::disconnect(RenX::DisconnectReason reason)
for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnServerDisconnect(this, reason);
RenX::Server::sock.closeSocket();
RenX::Server::sock.close();
RenX::Server::wipeData();
RenX::Server::connected = false;
}
@ -2916,7 +2916,7 @@ void RenX::Server::init()
RenX::Server::~Server()
{
sock.closeSocket();
sock.close();
RenX::Server::wipeData();
RenX::Server::commands.emptyAndDelete();
}

396
RenX.Core/RenX_Tags.cpp

@ -1,5 +1,5 @@
/**
* Copyright (C) 2015 Jessica James.
* Copyright (C) 2015-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
@ -27,10 +27,13 @@
#include "RenX_Plugin.h"
#include "RenX_Tags.h"
using namespace Jupiter::literals;
struct TagsImp : RenX::Tags
{
TagsImp();
void processTags(Jupiter::StringType &msg, const RenX::Server *server, const RenX::PlayerInfo *player, const RenX::PlayerInfo *victim, const RenX::BuildingInfo *building);
void processTags(Jupiter::StringType &msg, const RenX::LadderDatabase::Entry &entry);
void sanitizeTags(Jupiter::StringType &fmt);
const Jupiter::ReadableString &getUniqueInternalTag();
Jupiter::StringS get_building_health_bar(const RenX::BuildingInfo *building);
@ -54,14 +57,14 @@ RenX::Tags *RenX::tags = &_tags;
TagsImp::TagsImp()
{
this->tagItr = 0;
this->uniqueTag = STRING_LITERAL_AS_REFERENCE("\0\0\0\0\0\0");
this->uniqueTag = "\0\0\0\0\0\0"_jrs;
const Jupiter::ReadableString &configSection = Jupiter::IRC::Client::Config->get(STRING_LITERAL_AS_REFERENCE("RenX"), STRING_LITERAL_AS_REFERENCE("TagDefinitions"), STRING_LITERAL_AS_REFERENCE("RenX.Tags"));
TagsImp::bar_width = Jupiter::IRC::Client::Config->getInt(configSection, STRING_LITERAL_AS_REFERENCE("BarWidth"), 19);
const Jupiter::ReadableString &configSection = Jupiter::IRC::Client::Config->get("RenX"_jrs, "TagDefinitions"_jrs, "RenX.Tags"_jrs);
TagsImp::bar_width = Jupiter::IRC::Client::Config->getInt(configSection, "BarWidth"_jrs, 19);
/** Global formats */
this->dateFmt = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("DateFormat"), STRING_LITERAL_AS_REFERENCE("%A, %B %d, %Y"));
this->timeFmt = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("TimeFormat"), STRING_LITERAL_AS_REFERENCE("%H:%M:%S"));;
this->dateFmt = Jupiter::IRC::Client::Config->get(configSection, "DateFormat"_jrs, "%A, %B %d, %Y"_jrs);
this->timeFmt = Jupiter::IRC::Client::Config->get(configSection, "TimeFormat"_jrs, "%H:%M:%S"_jrs);;
/** Internal message tags */
@ -101,6 +104,7 @@ TagsImp::TagsImp()
this->INTERNAL_TEAM_LONG_TAG = this->getUniqueInternalTag();
this->INTERNAL_PING_TAG = this->getUniqueInternalTag();
this->INTERNAL_SCORE_TAG = this->getUniqueInternalTag();
this->INTERNAL_SCORE_PER_MINUTE_TAG = this->getUniqueInternalTag();
this->INTERNAL_CREDITS_TAG = this->getUniqueInternalTag();
this->INTERNAL_KILLS_TAG = this->getUniqueInternalTag();
this->INTERNAL_DEATHS_TAG = this->getUniqueInternalTag();
@ -110,10 +114,24 @@ TagsImp::TagsImp()
this->INTERNAL_VEHICLE_KILLS_TAG = this->getUniqueInternalTag();
this->INTERNAL_BUILDING_KILLS_TAG = this->getUniqueInternalTag();
this->INTERNAL_DEFENCE_KILLS_TAG = this->getUniqueInternalTag();
this->INTERNAL_GAME_TIME_TAG = this->getUniqueInternalTag();
this->INTERNAL_GAMES_TAG = this->getUniqueInternalTag();
this->INTERNAL_GDI_GAMES_TAG = this->getUniqueInternalTag();
this->INTERNAL_NOD_GAMES_TAG = this->getUniqueInternalTag();
this->INTERNAL_WINS_TAG = this->getUniqueInternalTag();
this->INTERNAL_LOSES_TAG = this->getUniqueInternalTag();
this->INTERNAL_GDI_WINS_TAG = this->getUniqueInternalTag();
this->INTERNAL_NOD_WINS_TAG = this->getUniqueInternalTag();
this->INTERNAL_TIES_TAG = this->getUniqueInternalTag();
this->INTERNAL_LOSSES_TAG = this->getUniqueInternalTag();
this->INTERNAL_GDI_LOSSES_TAG = this->getUniqueInternalTag();
this->INTERNAL_NOD_LOSSES_TAG = this->getUniqueInternalTag();
this->INTERNAL_WIN_LOSS_RATIO_TAG = this->getUniqueInternalTag();
this->INTERNAL_GDI_WIN_LOSS_RATIO_TAG = this->getUniqueInternalTag();
this->INTERNAL_NOD_WIN_LOSS_RATIO_TAG = this->getUniqueInternalTag();
this->INTERNAL_BEACON_PLACEMENTS_TAG = this->getUniqueInternalTag();
this->INTERNAL_BEACON_DISARMS_TAG = this->getUniqueInternalTag();
this->INTERNAL_PROXY_PLACEMENTS_TAG = this->getUniqueInternalTag();
this->INTERNAL_PROXY_DISARMS_TAG = this->getUniqueInternalTag();
this->INTERNAL_CAPTURES_TAG = this->getUniqueInternalTag();
this->INTERNAL_STEALS_TAG = this->getUniqueInternalTag();
this->INTERNAL_STOLEN_TAG = this->getUniqueInternalTag();
@ -146,10 +164,24 @@ TagsImp::TagsImp()
this->INTERNAL_VICTIM_VEHICLE_KILLS_TAG = this->getUniqueInternalTag();
this->INTERNAL_VICTIM_BUILDING_KILLS_TAG = this->getUniqueInternalTag();
this->INTERNAL_VICTIM_DEFENCE_KILLS_TAG = this->getUniqueInternalTag();
this->INTERNAL_VICTIM_GAME_TIME_TAG = this->getUniqueInternalTag();
this->INTERNAL_VICTIM_GAMES_TAG = this->getUniqueInternalTag();
this->INTERNAL_VICTIM_GDI_GAMES_TAG = this->getUniqueInternalTag();
this->INTERNAL_VICTIM_NOD_GAMES_TAG = this->getUniqueInternalTag();
this->INTERNAL_VICTIM_WINS_TAG = this->getUniqueInternalTag();
this->INTERNAL_VICTIM_LOSES_TAG = this->getUniqueInternalTag();
this->INTERNAL_VICTIM_GDI_WINS_TAG = this->getUniqueInternalTag();
this->INTERNAL_VICTIM_NOD_WINS_TAG = this->getUniqueInternalTag();
this->INTERNAL_VICTIM_TIES_TAG = this->getUniqueInternalTag();
this->INTERNAL_VICTIM_LOSSES_TAG = this->getUniqueInternalTag();
this->INTERNAL_VICTIM_GDI_LOSSES_TAG = this->getUniqueInternalTag();
this->INTERNAL_VICTIM_NOD_LOSSES_TAG = this->getUniqueInternalTag();
this->INTERNAL_VICTIM_WIN_LOSS_RATIO_TAG = this->getUniqueInternalTag();
this->INTERNAL_VICTIM_GDI_WIN_LOSS_RATIO_TAG = this->getUniqueInternalTag();
this->INTERNAL_VICTIM_NOD_WIN_LOSS_RATIO_TAG = this->getUniqueInternalTag();
this->INTERNAL_VICTIM_BEACON_PLACEMENTS_TAG = this->getUniqueInternalTag();
this->INTERNAL_VICTIM_BEACON_DISARMS_TAG = this->getUniqueInternalTag();
this->INTERNAL_VICTIM_PROXY_PLACEMENTS_TAG = this->getUniqueInternalTag();
this->INTERNAL_VICTIM_PROXY_DISARMS_TAG = this->getUniqueInternalTag();
this->INTERNAL_VICTIM_CAPTURES_TAG = this->getUniqueInternalTag();
this->INTERNAL_VICTIM_STEALS_TAG = this->getUniqueInternalTag();
this->INTERNAL_VICTIM_STOLEN_TAG = this->getUniqueInternalTag();
@ -173,117 +205,151 @@ TagsImp::TagsImp()
this->INTERNAL_NEW_NAME_TAG = this->getUniqueInternalTag();
this->INTERNAL_WIN_SCORE_TAG = this->getUniqueInternalTag();
this->INTERNAL_LOSE_SCORE_TAG = this->getUniqueInternalTag();
this->INTERNAL_LAST_GAME_TAG = this->getUniqueInternalTag();
this->INTERNAL_RANK_TAG = this->getUniqueInternalTag();
/** External (config) tags */
/** Global tags */
this->dateTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("DateTag"), STRING_LITERAL_AS_REFERENCE("{DATE}"));
this->timeTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("TimeTag"), STRING_LITERAL_AS_REFERENCE("{TIME}"));
this->dateTag = Jupiter::IRC::Client::Config->get(configSection, "DateTag"_jrs, "{DATE}"_jrs);
this->timeTag = Jupiter::IRC::Client::Config->get(configSection, "TimeTag"_jrs, "{TIME}"_jrs);
/** Server tags */
this->rconVersionTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("RCONVersionTag"), STRING_LITERAL_AS_REFERENCE("{RVER}"));
this->gameVersionTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("GameVersionTag"), STRING_LITERAL_AS_REFERENCE("{GVER}"));
this->rulesTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("RulesTag"), STRING_LITERAL_AS_REFERENCE("{RULES}"));
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}"));
this->socketPortTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("SocketPortTag"), STRING_LITERAL_AS_REFERENCE("{SOCKPORT}"));
this->serverPrefixTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("ServerPrefixTag"), STRING_LITERAL_AS_REFERENCE("{SERVERPREFIX}"));
this->rconVersionTag = Jupiter::IRC::Client::Config->get(configSection, "RCONVersionTag"_jrs, "{RVER}"_jrs);
this->gameVersionTag = Jupiter::IRC::Client::Config->get(configSection, "GameVersionTag"_jrs, "{GVER}"_jrs);
this->rulesTag = Jupiter::IRC::Client::Config->get(configSection, "RulesTag"_jrs, "{RULES}"_jrs);
this->userTag = Jupiter::IRC::Client::Config->get(configSection, "UserTag"_jrs, "{USER}"_jrs);
this->serverNameTag = Jupiter::IRC::Client::Config->get(configSection, "ServerNameTag"_jrs, "{SERVERNAME}"_jrs);
this->mapTag = Jupiter::IRC::Client::Config->get(configSection, "MapTag"_jrs, "{MAP}"_jrs);
this->mapGUIDTag = Jupiter::IRC::Client::Config->get(configSection, "MapGUIDTag"_jrs, "{MGUID}"_jrs);
this->serverHostnameTag = Jupiter::IRC::Client::Config->get(configSection, "ServerHostnameTag"_jrs, "{SERVERHOST}"_jrs);
this->serverPortTag = Jupiter::IRC::Client::Config->get(configSection, "ServerPortTag"_jrs, "{SERVERPORT}"_jrs);
this->socketHostnameTag = Jupiter::IRC::Client::Config->get(configSection, "SocketHostnameTag"_jrs, "{SOCKHOST}"_jrs);
this->socketPortTag = Jupiter::IRC::Client::Config->get(configSection, "SocketPortTag"_jrs, "{SOCKPORT}"_jrs);
this->serverPrefixTag = Jupiter::IRC::Client::Config->get(configSection, "ServerPrefixTag"_jrs, "{SERVERPREFIX}"_jrs);
/** Player tags */
this->nameTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("NameTag"), STRING_LITERAL_AS_REFERENCE("{NAME}"));
this->rawNameTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("RawNameTag"), STRING_LITERAL_AS_REFERENCE("{RNAME}"));
this->ipTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("IPTag"), STRING_LITERAL_AS_REFERENCE("{IP}"));
this->rdnsTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("RDNSTag"), STRING_LITERAL_AS_REFERENCE("{RDNS}"));
this->steamTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("SteamTag"), STRING_LITERAL_AS_REFERENCE("{STEAM}"));
this->uuidTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("UUIDTag"), STRING_LITERAL_AS_REFERENCE("{UUID}"));
this->idTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("IDTag"), STRING_LITERAL_AS_REFERENCE("{ID}"));
this->characterTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("CharacterTag"), STRING_LITERAL_AS_REFERENCE("{CHAR}"));
this->vehicleTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VehicleTag"), STRING_LITERAL_AS_REFERENCE("{VEH}"));
this->adminTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("AdminTag"), STRING_LITERAL_AS_REFERENCE("{ADMIN}"));
this->prefixTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("PrefixTag"), STRING_LITERAL_AS_REFERENCE("{PREFIX}"));
this->gamePrefixTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("GamePrefixTag"), STRING_LITERAL_AS_REFERENCE("{GPREFIX}"));
this->teamColorTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("TeamColorTag"), STRING_LITERAL_AS_REFERENCE("{TCOLOR}"));
this->teamShortTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("ShortTeamTag"), STRING_LITERAL_AS_REFERENCE("{TEAMS}"));
this->teamLongTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("LongTeamTag"), STRING_LITERAL_AS_REFERENCE("{TEAML}"));
this->pingTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("PingTag"), STRING_LITERAL_AS_REFERENCE("{PING}"));
this->scoreTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("ScoreTag"), STRING_LITERAL_AS_REFERENCE("{SCORE}"));
this->creditsTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("CreditsTag"), STRING_LITERAL_AS_REFERENCE("{CREDITS}"));
this->killsTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("KillsTag"), STRING_LITERAL_AS_REFERENCE("{KILLS}"));
this->deathsTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("DeathsTag"), STRING_LITERAL_AS_REFERENCE("{DEATHS}"));
this->kdrTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("KDRTag"), STRING_LITERAL_AS_REFERENCE("{KDR}"));
this->suicidesTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("SuicidesTag"), STRING_LITERAL_AS_REFERENCE("{SUICIDES}"));
this->headshotsTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("HeadshotsTag"), STRING_LITERAL_AS_REFERENCE("{HEADSHOTS}"));
this->vehicleKillsTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VehicleKillsTag"), STRING_LITERAL_AS_REFERENCE("{VEHICLEKILLS}"));
this->buildingKillsTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("BuildingKillsTag"), STRING_LITERAL_AS_REFERENCE("{BUILDINGKILLS}"));
this->defenceKillsTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("DefenceKillsTag"), STRING_LITERAL_AS_REFERENCE("{DEFENCEKILLS}"));
this->winsTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("WinsTag"), STRING_LITERAL_AS_REFERENCE("{WINS}"));
this->losesTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("LosesTag"), STRING_LITERAL_AS_REFERENCE("{LOSES}"));
this->beaconPlacementsTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("BeaconPlacementsTag"), STRING_LITERAL_AS_REFERENCE("{BEACONPLACEMENTS}"));
this->beaconDisarmsTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("BeaconDisarmsTag"), STRING_LITERAL_AS_REFERENCE("{BEACONDISARMS}"));
this->capturesTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("CapturesTag"), STRING_LITERAL_AS_REFERENCE("{CAPTURES}"));
this->stealsTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("StealsTag"), STRING_LITERAL_AS_REFERENCE("{STEALS}"));
this->stolenTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("StolenTag"), STRING_LITERAL_AS_REFERENCE("{STOLEN}"));
this->accessTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("AccessTag"), STRING_LITERAL_AS_REFERENCE("{ACCESS}"));
this->nameTag = Jupiter::IRC::Client::Config->get(configSection, "NameTag"_jrs, "{NAME}"_jrs);
this->rawNameTag = Jupiter::IRC::Client::Config->get(configSection, "RawNameTag"_jrs, "{RNAME}"_jrs);
this->ipTag = Jupiter::IRC::Client::Config->get(configSection, "IPTag"_jrs, "{IP}"_jrs);
this->rdnsTag = Jupiter::IRC::Client::Config->get(configSection, "RDNSTag"_jrs, "{RDNS}"_jrs);
this->steamTag = Jupiter::IRC::Client::Config->get(configSection, "SteamTag"_jrs, "{STEAM}"_jrs);
this->uuidTag = Jupiter::IRC::Client::Config->get(configSection, "UUIDTag"_jrs, "{UUID}"_jrs);
this->idTag = Jupiter::IRC::Client::Config->get(configSection, "IDTag"_jrs, "{ID}"_jrs);
this->characterTag = Jupiter::IRC::Client::Config->get(configSection, "CharacterTag"_jrs, "{CHAR}"_jrs);
this->vehicleTag = Jupiter::IRC::Client::Config->get(configSection, "VehicleTag"_jrs, "{VEH}"_jrs);
this->adminTag = Jupiter::IRC::Client::Config->get(configSection, "AdminTag"_jrs, "{ADMIN}"_jrs);
this->prefixTag = Jupiter::IRC::Client::Config->get(configSection, "PrefixTag"_jrs, "{PREFIX}"_jrs);
this->gamePrefixTag = Jupiter::IRC::Client::Config->get(configSection, "GamePrefixTag"_jrs, "{GPREFIX}"_jrs);
this->teamColorTag = Jupiter::IRC::Client::Config->get(configSection, "TeamColorTag"_jrs, "{TCOLOR}"_jrs);
this->teamShortTag = Jupiter::IRC::Client::Config->get(configSection, "ShortTeamTag"_jrs, "{TEAMS}"_jrs);
this->teamLongTag = Jupiter::IRC::Client::Config->get(configSection, "LongTeamTag"_jrs, "{TEAML}"_jrs);
this->pingTag = Jupiter::IRC::Client::Config->get(configSection, "PingTag"_jrs, "{PING}"_jrs);
this->scoreTag = Jupiter::IRC::Client::Config->get(configSection, "ScoreTag"_jrs, "{SCORE}"_jrs);
this->scorePerMinuteTag = Jupiter::IRC::Client::Config->get(configSection, "ScorePerMinuteTag"_jrs, "{SPM}"_jrs);
this->creditsTag = Jupiter::IRC::Client::Config->get(configSection, "CreditsTag"_jrs, "{CREDITS}"_jrs);
this->killsTag = Jupiter::IRC::Client::Config->get(configSection, "KillsTag"_jrs, "{KILLS}"_jrs);
this->deathsTag = Jupiter::IRC::Client::Config->get(configSection, "DeathsTag"_jrs, "{DEATHS}"_jrs);
this->kdrTag = Jupiter::IRC::Client::Config->get(configSection, "KDRTag"_jrs, "{KDR}"_jrs);
this->suicidesTag = Jupiter::IRC::Client::Config->get(configSection, "SuicidesTag"_jrs, "{SUICIDES}"_jrs);
this->headshotsTag = Jupiter::IRC::Client::Config->get(configSection, "HeadshotsTag"_jrs, "{HEADSHOTS}"_jrs);
this->vehicleKillsTag = Jupiter::IRC::Client::Config->get(configSection, "VehicleKillsTag"_jrs, "{VEHICLEKILLS}"_jrs);
this->buildingKillsTag = Jupiter::IRC::Client::Config->get(configSection, "BuildingKillsTag"_jrs, "{BUILDINGKILLS}"_jrs);
this->defenceKillsTag = Jupiter::IRC::Client::Config->get(configSection, "DefenceKillsTag"_jrs, "{DEFENCEKILLS}"_jrs);
this->gameTimeTag = Jupiter::IRC::Client::Config->get(configSection, "GameTimeTag"_jrs, "{GAMETIME}"_jrs);
this->gamesTag = Jupiter::IRC::Client::Config->get(configSection, "GamesTag"_jrs, "{GAMES}"_jrs);
this->GDIGamesTag = Jupiter::IRC::Client::Config->get(configSection, "GDIGamesTag"_jrs, "{GDIGAMES}"_jrs);
this->NodGamesTag = Jupiter::IRC::Client::Config->get(configSection, "NodGamesTag"_jrs, "{NODGAMES}"_jrs);
this->winsTag = Jupiter::IRC::Client::Config->get(configSection, "WinsTag"_jrs, "{WINS}"_jrs);
this->GDIWinsTag = Jupiter::IRC::Client::Config->get(configSection, "GDIWinsTag"_jrs, "{GDIWINS}"_jrs);
this->NodWinsTag = Jupiter::IRC::Client::Config->get(configSection, "NodWinsTag"_jrs, "{NODWINS}"_jrs);
this->tiesTag = Jupiter::IRC::Client::Config->get(configSection, "TiesTag"_jrs, "{TIES}"_jrs);
this->lossesTag = Jupiter::IRC::Client::Config->get(configSection, "LossesTag"_jrs, "{LOSSES}"_jrs);
this->GDILossesTag = Jupiter::IRC::Client::Config->get(configSection, "GDILossesTag"_jrs, "{GDILOSSES}"_jrs);
this->NodLossesTag = Jupiter::IRC::Client::Config->get(configSection, "NodLossesTag"_jrs, "{NODLOSSES}"_jrs);
this->winLossRatioTag = Jupiter::IRC::Client::Config->get(configSection, "WinLossRatioTag"_jrs, "{WLR}"_jrs);
this->GDIWinLossRatioTag = Jupiter::IRC::Client::Config->get(configSection, "GDIWinLossRatioTag"_jrs, "{GWLR}"_jrs);
this->NodWinLossRatioTag = Jupiter::IRC::Client::Config->get(configSection, "NodWinLossRatioTag"_jrs, "{NWLR}"_jrs);
this->beaconPlacementsTag = Jupiter::IRC::Client::Config->get(configSection, "BeaconPlacementsTag"_jrs, "{BEACONPLACEMENTS}"_jrs);
this->beaconDisarmsTag = Jupiter::IRC::Client::Config->get(configSection, "BeaconDisarmsTag"_jrs, "{BEACONDISARMS}"_jrs);
this->proxyPlacementsTag = Jupiter::IRC::Client::Config->get(configSection, "ProxyPlacementsTag"_jrs, "{PROXYPLACEMENTS}"_jrs);
this->proxyDisarmsTag = Jupiter::IRC::Client::Config->get(configSection, "ProxyDisarmsTag"_jrs, "{PROXYDISARMS}"_jrs);
this->capturesTag = Jupiter::IRC::Client::Config->get(configSection, "CapturesTag"_jrs, "{CAPTURES}"_jrs);
this->stealsTag = Jupiter::IRC::Client::Config->get(configSection, "StealsTag"_jrs, "{STEALS}"_jrs);
this->stolenTag = Jupiter::IRC::Client::Config->get(configSection, "StolenTag"_jrs, "{STOLEN}"_jrs);
this->accessTag = Jupiter::IRC::Client::Config->get(configSection, "AccessTag"_jrs, "{ACCESS}"_jrs);
/** Victim player tags */
this->victimNameTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimNameTag"), STRING_LITERAL_AS_REFERENCE("{VNAME}"));
this->victimRawNameTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimRawNameTag"), STRING_LITERAL_AS_REFERENCE("{VRNAME}"));
this->victimIPTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimIPTag"), STRING_LITERAL_AS_REFERENCE("{VIP}"));
this->victimRDNSTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimRDNSTag"), STRING_LITERAL_AS_REFERENCE("{VRDNS}"));
this->victimSteamTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimSteamTag"), STRING_LITERAL_AS_REFERENCE("{VSTEAM}"));
this->victimUUIDTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimUUIDTag"), STRING_LITERAL_AS_REFERENCE("{VUUID}"));
this->victimIDTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimIDTag"), STRING_LITERAL_AS_REFERENCE("{VID}"));
this->victimCharacterTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimCharacterTag"), STRING_LITERAL_AS_REFERENCE("{VCHAR}"));
this->victimVehicleTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimVehicleTag"), STRING_LITERAL_AS_REFERENCE("{VVEH}"));
this->victimAdminTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimAdminTag"), STRING_LITERAL_AS_REFERENCE("{VADMIN}"));
this->victimPrefixTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimPrefixTag"), STRING_LITERAL_AS_REFERENCE("{VPREFIX}"));
this->victimGamePrefixTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimGamePrefixTag"), STRING_LITERAL_AS_REFERENCE("{VGPREFIX}"));
this->victimTeamColorTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimTeamColorTag"), STRING_LITERAL_AS_REFERENCE("{VTCOLOR}"));
this->victimTeamShortTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimShortTeamTag"), STRING_LITERAL_AS_REFERENCE("{VTEAMS}"));
this->victimTeamLongTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimLongTeamTag"), STRING_LITERAL_AS_REFERENCE("{VTEAML}"));
this->victimPingTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimPingTag"), STRING_LITERAL_AS_REFERENCE("{VPING}"));
this->victimScoreTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimScoreTag"), STRING_LITERAL_AS_REFERENCE("{VSCORE}"));
this->victimCreditsTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimCreditsTag"), STRING_LITERAL_AS_REFERENCE("{VCREDITS}"));
this->victimKillsTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimKillsTag"), STRING_LITERAL_AS_REFERENCE("{VKILLS}"));
this->victimDeathsTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimDeathsTag"), STRING_LITERAL_AS_REFERENCE("{VDEATHS}"));
this->victimKDRTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimKDRTag"), STRING_LITERAL_AS_REFERENCE("{VKDR}"));
this->victimSuicidesTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimSuicidesTag"), STRING_LITERAL_AS_REFERENCE("{VSUICIDES}"));
this->victimHeadshotsTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimHeadshotsTag"), STRING_LITERAL_AS_REFERENCE("{VHEADSHOTS}"));
this->victimVehicleKillsTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimVehicleKillsTag"), STRING_LITERAL_AS_REFERENCE("{VVEHICLEKILLS}"));
this->victimBuildingKillsTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimBuildingKillsTag"), STRING_LITERAL_AS_REFERENCE("{VBUILDINGKILLS}"));
this->victimDefenceKillsTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimDefenceKillsTag"), STRING_LITERAL_AS_REFERENCE("{VDEFENCEKILLS}"));
this->victimWinsTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimWinsTag"), STRING_LITERAL_AS_REFERENCE("{VWINS}"));
this->victimLosesTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimLosesTag"), STRING_LITERAL_AS_REFERENCE("{VLOSES}"));
this->victimBeaconPlacementsTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimBeaconPlacementsTag"), STRING_LITERAL_AS_REFERENCE("{VBEACONPLACEMENTS}"));
this->victimBeaconDisarmsTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimBeaconDisarmsTag"), STRING_LITERAL_AS_REFERENCE("{VBEACONDISARMS}"));
this->victimCapturesTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimCapturesTag"), STRING_LITERAL_AS_REFERENCE("{VCAPTURES}"));
this->victimStealsTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimStealsTag"), STRING_LITERAL_AS_REFERENCE("{VSTEALS}"));
this->victimStolenTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimStolenTag"), STRING_LITERAL_AS_REFERENCE("{VSTOLEN}"));
this->victimAccessTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("VictimAccessTag"), STRING_LITERAL_AS_REFERENCE("{VACCESS}"));
this->victimNameTag = Jupiter::IRC::Client::Config->get(configSection, "VictimNameTag"_jrs, "{VNAME}"_jrs);
this->victimRawNameTag = Jupiter::IRC::Client::Config->get(configSection, "VictimRawNameTag"_jrs, "{VRNAME}"_jrs);
this->victimIPTag = Jupiter::IRC::Client::Config->get(configSection, "VictimIPTag"_jrs, "{VIP}"_jrs);
this->victimRDNSTag = Jupiter::IRC::Client::Config->get(configSection, "VictimRDNSTag"_jrs, "{VRDNS}"_jrs);
this->victimSteamTag = Jupiter::IRC::Client::Config->get(configSection, "VictimSteamTag"_jrs, "{VSTEAM}"_jrs);
this->victimUUIDTag = Jupiter::IRC::Client::Config->get(configSection, "VictimUUIDTag"_jrs, "{VUUID}"_jrs);
this->victimIDTag = Jupiter::IRC::Client::Config->get(configSection, "VictimIDTag"_jrs, "{VID}"_jrs);
this->victimCharacterTag = Jupiter::IRC::Client::Config->get(configSection, "VictimCharacterTag"_jrs, "{VCHAR}"_jrs);
this->victimVehicleTag = Jupiter::IRC::Client::Config->get(configSection, "VictimVehicleTag"_jrs, "{VVEH}"_jrs);
this->victimAdminTag = Jupiter::IRC::Client::Config->get(configSection, "VictimAdminTag"_jrs, "{VADMIN}"_jrs);
this->victimPrefixTag = Jupiter::IRC::Client::Config->get(configSection, "VictimPrefixTag"_jrs, "{VPREFIX}"_jrs);
this->victimGamePrefixTag = Jupiter::IRC::Client::Config->get(configSection, "VictimGamePrefixTag"_jrs, "{VGPREFIX}"_jrs);
this->victimTeamColorTag = Jupiter::IRC::Client::Config->get(configSection, "VictimTeamColorTag"_jrs, "{VTCOLOR}"_jrs);
this->victimTeamShortTag = Jupiter::IRC::Client::Config->get(configSection, "VictimShortTeamTag"_jrs, "{VTEAMS}"_jrs);
this->victimTeamLongTag = Jupiter::IRC::Client::Config->get(configSection, "VictimLongTeamTag"_jrs, "{VTEAML}"_jrs);
this->victimPingTag = Jupiter::IRC::Client::Config->get(configSection, "VictimPingTag"_jrs, "{VPING}"_jrs);
this->victimScoreTag = Jupiter::IRC::Client::Config->get(configSection, "VictimScoreTag"_jrs, "{VSCORE}"_jrs);
this->victimScorePerMinuteTag = Jupiter::IRC::Client::Config->get(configSection, "VictimScorePerMinuteTag"_jrs, "{VSPM}"_jrs);
this->victimCreditsTag = Jupiter::IRC::Client::Config->get(configSection, "VictimCreditsTag"_jrs, "{VCREDITS}"_jrs);
this->victimKillsTag = Jupiter::IRC::Client::Config->get(configSection, "VictimKillsTag"_jrs, "{VKILLS}"_jrs);
this->victimDeathsTag = Jupiter::IRC::Client::Config->get(configSection, "VictimDeathsTag"_jrs, "{VDEATHS}"_jrs);
this->victimKDRTag = Jupiter::IRC::Client::Config->get(configSection, "VictimKDRTag"_jrs, "{VKDR}"_jrs);
this->victimSuicidesTag = Jupiter::IRC::Client::Config->get(configSection, "VictimSuicidesTag"_jrs, "{VSUICIDES}"_jrs);
this->victimHeadshotsTag = Jupiter::IRC::Client::Config->get(configSection, "VictimHeadshotsTag"_jrs, "{VHEADSHOTS}"_jrs);
this->victimVehicleKillsTag = Jupiter::IRC::Client::Config->get(configSection, "VictimVehicleKillsTag"_jrs, "{VVEHICLEKILLS}"_jrs);
this->victimBuildingKillsTag = Jupiter::IRC::Client::Config->get(configSection, "VictimBuildingKillsTag"_jrs, "{VBUILDINGKILLS}"_jrs);
this->victimDefenceKillsTag = Jupiter::IRC::Client::Config->get(configSection, "VictimDefenceKillsTag"_jrs, "{VDEFENCEKILLS}"_jrs);
this->victimGameTimeTag = Jupiter::IRC::Client::Config->get(configSection, "VictimGameTimeTag"_jrs, "{VGAMETIME}"_jrs);
this->victimGamesTag = Jupiter::IRC::Client::Config->get(configSection, "VictimGamesTag"_jrs, "{VGAMES}"_jrs);
this->victimGDIGamesTag = Jupiter::IRC::Client::Config->get(configSection, "VictimGDIGamesTag"_jrs, "{VGDIGAMES}"_jrs);
this->victimNodGamesTag = Jupiter::IRC::Client::Config->get(configSection, "VictimNodGamesTag"_jrs, "{VNODGAMES}"_jrs);
this->victimWinsTag = Jupiter::IRC::Client::Config->get(configSection, "VictimWinsTag"_jrs, "{VWINS}"_jrs);
this->victimGDIWinsTag = Jupiter::IRC::Client::Config->get(configSection, "VictimGDIWinsTag"_jrs, "{VGDIWINS}"_jrs);
this->victimNodWinsTag = Jupiter::IRC::Client::Config->get(configSection, "VictimNodWinsTag"_jrs, "{VNODWINS}"_jrs);
this->victimTiesTag = Jupiter::IRC::Client::Config->get(configSection, "VictimTiesTag"_jrs, "{VTIES}"_jrs);
this->victimLossesTag = Jupiter::IRC::Client::Config->get(configSection, "VictimLossesTag"_jrs, "{VLOSSES}"_jrs);
this->victimGDILossesTag = Jupiter::IRC::Client::Config->get(configSection, "VictimGDILossesTag"_jrs, "{VGDILOSSES}"_jrs);
this->victimNodLossesTag = Jupiter::IRC::Client::Config->get(configSection, "VictimNodLossesTag"_jrs, "{VNODLOSSES}"_jrs);
this->victimWinLossRatioTag = Jupiter::IRC::Client::Config->get(configSection, "WinLossRatioTag"_jrs, "{WLR}"_jrs);
this->victimGDIWinLossRatioTag = Jupiter::IRC::Client::Config->get(configSection, "GDIWinLossRatioTag"_jrs, "{VGWLR}"_jrs);
this->victimNodWinLossRatioTag = Jupiter::IRC::Client::Config->get(configSection, "NodWinLossRatioTag"_jrs, "{VNWLR}"_jrs);
this->victimBeaconPlacementsTag = Jupiter::IRC::Client::Config->get(configSection, "VictimBeaconPlacementsTag"_jrs, "{VBEACONPLACEMENTS}"_jrs);
this->victimBeaconDisarmsTag = Jupiter::IRC::Client::Config->get(configSection, "VictimBeaconDisarmsTag"_jrs, "{VBEACONDISARMS}"_jrs);
this->victimProxyPlacementsTag = Jupiter::IRC::Client::Config->get(configSection, "VictimProxyPlacementsTag"_jrs, "{VPROXYPLACEMENTS}"_jrs);
this->victimProxyDisarmsTag = Jupiter::IRC::Client::Config->get(configSection, "VictimProxyDisarmsTag"_jrs, "{VPROXYDISARMS}"_jrs);
this->victimCapturesTag = Jupiter::IRC::Client::Config->get(configSection, "VictimCapturesTag"_jrs, "{VCAPTURES}"_jrs);
this->victimStealsTag = Jupiter::IRC::Client::Config->get(configSection, "VictimStealsTag"_jrs, "{VSTEALS}"_jrs);
this->victimStolenTag = Jupiter::IRC::Client::Config->get(configSection, "VictimStolenTag"_jrs, "{VSTOLEN}"_jrs);
this->victimAccessTag = Jupiter::IRC::Client::Config->get(configSection, "VictimAccessTag"_jrs, "{VACCESS}"_jrs);
/** Building tags */
this->buildingNameTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("BuildingNameTag"), STRING_LITERAL_AS_REFERENCE("{BNAME}"));
this->buildingRawNameTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("BuildingRawNameTag"), STRING_LITERAL_AS_REFERENCE("{BRNAME}"));
this->buildingHealthTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("BuildingHealthTag"), STRING_LITERAL_AS_REFERENCE("{BHEALTH}"));
this->buildingMaxHealthTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("BuildingMaxHealthTag"), STRING_LITERAL_AS_REFERENCE("{BMHEALTH}"));
this->buildingHealthPercentageTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("BuildingHealthPercentageTag"), STRING_LITERAL_AS_REFERENCE("{BHP}"));
this->buildingHealthBarTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("BuildingHealthBarTag"), STRING_LITERAL_AS_REFERENCE("{BHBAR}"));
this->buildingTeamColorTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("BuildingTeamColorTag"), STRING_LITERAL_AS_REFERENCE("{BCOLOR}"));
this->buildingTeamShortTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("BuildingShortTeamTag"), STRING_LITERAL_AS_REFERENCE("{BTEAMS}"));
this->buildingTeamLongTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("BuildingLongTeamTag"), STRING_LITERAL_AS_REFERENCE("{BTEAML}"));
this->buildingNameTag = Jupiter::IRC::Client::Config->get(configSection, "BuildingNameTag"_jrs, "{BNAME}"_jrs);
this->buildingRawNameTag = Jupiter::IRC::Client::Config->get(configSection, "BuildingRawNameTag"_jrs, "{BRNAME}"_jrs);
this->buildingHealthTag = Jupiter::IRC::Client::Config->get(configSection, "BuildingHealthTag"_jrs, "{BHEALTH}"_jrs);
this->buildingMaxHealthTag = Jupiter::IRC::Client::Config->get(configSection, "BuildingMaxHealthTag"_jrs, "{BMHEALTH}"_jrs);
this->buildingHealthPercentageTag = Jupiter::IRC::Client::Config->get(configSection, "BuildingHealthPercentageTag"_jrs, "{BHP}"_jrs);
this->buildingHealthBarTag = Jupiter::IRC::Client::Config->get(configSection, "BuildingHealthBarTag"_jrs, "{BHBAR}"_jrs);
this->buildingTeamColorTag = Jupiter::IRC::Client::Config->get(configSection, "BuildingTeamColorTag"_jrs, "{BCOLOR}"_jrs);
this->buildingTeamShortTag = Jupiter::IRC::Client::Config->get(configSection, "BuildingShortTeamTag"_jrs, "{BTEAMS}"_jrs);
this->buildingTeamLongTag = Jupiter::IRC::Client::Config->get(configSection, "BuildingLongTeamTag"_jrs, "{BTEAML}"_jrs);
/** Other tags */
this->weaponTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("WeaponTag"), STRING_LITERAL_AS_REFERENCE("{WEAPON}"));
this->objectTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("ObjectTag"), STRING_LITERAL_AS_REFERENCE("{OBJECT}"));
this->messageTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("MessageTag"), STRING_LITERAL_AS_REFERENCE("{MESSAGE}"));
this->newNameTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("NewNameTag"), STRING_LITERAL_AS_REFERENCE("{NNAME}"));
this->winScoreTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("WinScoreTag"), STRING_LITERAL_AS_REFERENCE("{WINSCORE}"));
this->loseScoreTag = Jupiter::IRC::Client::Config->get(configSection, STRING_LITERAL_AS_REFERENCE("LoseScoreTag"), STRING_LITERAL_AS_REFERENCE("{LOSESCORE}"));
this->weaponTag = Jupiter::IRC::Client::Config->get(configSection, "WeaponTag"_jrs, "{WEAPON}"_jrs);
this->objectTag = Jupiter::IRC::Client::Config->get(configSection, "ObjectTag"_jrs, "{OBJECT}"_jrs);
this->messageTag = Jupiter::IRC::Client::Config->get(configSection, "MessageTag"_jrs, "{MESSAGE}"_jrs);
this->newNameTag = Jupiter::IRC::Client::Config->get(configSection, "NewNameTag"_jrs, "{NNAME}"_jrs);
this->winScoreTag = Jupiter::IRC::Client::Config->get(configSection, "WinScoreTag"_jrs, "{WINSCORE}"_jrs);
this->loseScoreTag = Jupiter::IRC::Client::Config->get(configSection, "LoseScoreTag"_jrs, "{LOSESCORE}"_jrs);
this->lastGameTag = Jupiter::IRC::Client::Config->get(configSection, "LastScoreTag"_jrs, "{LOSESCORE}"_jrs);
this->rankTag = Jupiter::IRC::Client::Config->get(configSection, "RankTag"_jrs, "{RANK}"_jrs);
}
Jupiter::StringS TagsImp::get_building_health_bar(const RenX::BuildingInfo *building)
@ -320,11 +386,12 @@ Jupiter::StringS TagsImp::get_building_health_bar(const RenX::BuildingInfo *buil
return r += IRCNORMAL;
}
#define PROCESS_TAG(tag, value) \
while(true) { \
index = msg.find(tag); \
if (index == Jupiter::INVALID_INDEX) break; \
msg.replace(index, tag.size(), value); }
double get_ratio(double num, double denom)
{
if (denom == 0.0f)
return num;
return num / denom;
}
void TagsImp::processTags(Jupiter::StringType &msg, const RenX::Server *server, const RenX::PlayerInfo *player, const RenX::PlayerInfo *victim, const RenX::BuildingInfo *building)
{
@ -372,6 +439,7 @@ void TagsImp::processTags(Jupiter::StringType &msg, const RenX::Server *server,
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_SCORE_PER_MINUTE_TAG, Jupiter::StringS::Format("%.2f", get_ratio(static_cast<double>(player->score), static_cast<double>((std::chrono::steady_clock::now() - player->joinTime).count()) / 60.0)));
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));
@ -382,7 +450,7 @@ void TagsImp::processTags(Jupiter::StringType &msg, const RenX::Server *server,
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_LOSSES_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));
@ -408,6 +476,7 @@ void TagsImp::processTags(Jupiter::StringType &msg, const RenX::Server *server,
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_SCORE_PER_MINUTE_TAG, Jupiter::StringS::Format("%.2f", get_ratio(static_cast<double>(victim->score), static_cast<double>((std::chrono::steady_clock::now() - victim->joinTime).count()) / 60.0)));
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));
@ -418,7 +487,7 @@ void TagsImp::processTags(Jupiter::StringType &msg, const RenX::Server *server,
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_LOSSES_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));
@ -440,8 +509,66 @@ void TagsImp::processTags(Jupiter::StringType &msg, const RenX::Server *server,
}
Jupiter::ArrayList<RenX::Plugin> &xPlugins = *RenX::getCore()->getPlugins();
for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_ProcessTags(msg, server, player, victim, building);
for (index = 0; index < xPlugins.size(); ++index)
xPlugins.get(index)->RenX_ProcessTags(msg, server, player, victim, building);
}
void TagsImp::processTags(Jupiter::StringType &msg, const RenX::LadderDatabase::Entry &entry)
{
size_t index;
uint32_t total_tied_games = entry.total_wins - entry.total_gdi_wins - entry.total_nod_wins;
uint32_t total_nontied_games = entry.total_games - total_tied_games;
PROCESS_TAG(this->INTERNAL_NAME_TAG, entry.most_recent_name);
PROCESS_TAG(this->INTERNAL_STEAM_TAG, Jupiter::StringS::Format("%llu", entry.steam_id));
PROCESS_TAG(this->INTERNAL_LAST_GAME_TAG, Jupiter::StringS::Format("XX Xuary 20XX at 00:00:00")); // TODO: format this!
PROCESS_TAG(this->INTERNAL_RANK_TAG, Jupiter::StringS::Format("%u", entry.rank));
/** Totals */
PROCESS_TAG(this->INTERNAL_SCORE_TAG, Jupiter::StringS::Format("%llu", entry.total_score));
PROCESS_TAG(this->INTERNAL_KILLS_TAG, Jupiter::StringS::Format("%u", entry.total_kills));
PROCESS_TAG(this->INTERNAL_DEATHS_TAG, Jupiter::StringS::Format("%u", entry.total_deaths));
PROCESS_TAG(this->INTERNAL_KDR_TAG, Jupiter::StringS::Format("%.2f", get_ratio(static_cast<double>(entry.total_kills), static_cast<double>(entry.total_deaths))));
PROCESS_TAG(this->INTERNAL_SCORE_PER_MINUTE_TAG, Jupiter::StringS::Format("%.2f", get_ratio(static_cast<double>(entry.total_score), static_cast<double>(entry.total_game_time) / 60.0)));
PROCESS_TAG(this->INTERNAL_HEADSHOTS_TAG, Jupiter::StringS::Format("%u", entry.total_headshot_kills));
PROCESS_TAG(this->INTERNAL_VEHICLE_KILLS_TAG, Jupiter::StringS::Format("%u", entry.total_vehicle_kills));
PROCESS_TAG(this->INTERNAL_BUILDING_KILLS_TAG, Jupiter::StringS::Format("%u", entry.total_building_kills));
PROCESS_TAG(this->INTERNAL_DEFENCE_KILLS_TAG, Jupiter::StringS::Format("%u", entry.total_defence_kills));
PROCESS_TAG(this->INTERNAL_CAPTURES_TAG, Jupiter::StringS::Format("%u", entry.total_captures));
PROCESS_TAG(this->INTERNAL_GAME_TIME_TAG, Jupiter::StringS::Format("%u", entry.total_game_time));
PROCESS_TAG(this->INTERNAL_GAMES_TAG, Jupiter::StringS::Format("%u", entry.total_games));
PROCESS_TAG(this->INTERNAL_GDI_GAMES_TAG, Jupiter::StringS::Format("%u", entry.total_gdi_games));
PROCESS_TAG(this->INTERNAL_NOD_GAMES_TAG, Jupiter::StringS::Format("%u", entry.total_nod_games));
PROCESS_TAG(this->INTERNAL_WINS_TAG, Jupiter::StringS::Format("%u", entry.total_wins));
PROCESS_TAG(this->INTERNAL_GDI_WINS_TAG, Jupiter::StringS::Format("%u", entry.total_gdi_wins));
PROCESS_TAG(this->INTERNAL_NOD_WINS_TAG, Jupiter::StringS::Format("%u", entry.total_nod_wins));
PROCESS_TAG(this->INTERNAL_TIES_TAG, Jupiter::StringS::Format("%u", total_tied_games));
PROCESS_TAG(this->INTERNAL_LOSSES_TAG, Jupiter::StringS::Format("%u", total_nontied_games - entry.total_wins));
PROCESS_TAG(this->INTERNAL_GDI_LOSSES_TAG, Jupiter::StringS::Format("%u", total_nontied_games - entry.total_gdi_wins));
PROCESS_TAG(this->INTERNAL_NOD_LOSSES_TAG, Jupiter::StringS::Format("%u", total_nontied_games - entry.total_nod_wins));
PROCESS_TAG(this->INTERNAL_WIN_LOSS_RATIO_TAG, Jupiter::StringS::Format("%.2f", get_ratio(static_cast<double>(entry.total_wins), static_cast<double>(total_nontied_games - entry.total_wins))));
PROCESS_TAG(this->INTERNAL_GDI_WIN_LOSS_RATIO_TAG, Jupiter::StringS::Format("%.2f", get_ratio(static_cast<double>(entry.total_gdi_wins), static_cast<double>(total_nontied_games - entry.total_gdi_wins))));
PROCESS_TAG(this->INTERNAL_NOD_WIN_LOSS_RATIO_TAG, Jupiter::StringS::Format("%.2f", get_ratio(static_cast<double>(entry.total_nod_wins), static_cast<double>(total_nontied_games - entry.total_nod_wins))));
PROCESS_TAG(this->INTERNAL_BEACON_PLACEMENTS_TAG, Jupiter::StringS::Format("%u", entry.total_beacon_placements));
PROCESS_TAG(this->INTERNAL_BEACON_DISARMS_TAG, Jupiter::StringS::Format("%u", entry.total_beacon_disarms));
PROCESS_TAG(this->INTERNAL_PROXY_PLACEMENTS_TAG, Jupiter::StringS::Format("%u", entry.total_proxy_placements));
PROCESS_TAG(this->INTERNAL_PROXY_DISARMS_TAG, Jupiter::StringS::Format("%u", entry.total_proxy_disarms));
/** Tops */
PROCESS_TAG(this->INTERNAL_VICTIM_SCORE_TAG, Jupiter::StringS::Format("%llu", entry.top_score));
PROCESS_TAG(this->INTERNAL_VICTIM_KILLS_TAG, Jupiter::StringS::Format("%u", entry.top_kills));
PROCESS_TAG(this->INTERNAL_VICTIM_DEATHS_TAG, Jupiter::StringS::Format("%u", entry.most_deaths));
PROCESS_TAG(this->INTERNAL_VICTIM_HEADSHOTS_TAG, Jupiter::StringS::Format("%u", entry.top_headshot_kills));
PROCESS_TAG(this->INTERNAL_VICTIM_VEHICLE_KILLS_TAG, Jupiter::StringS::Format("%u", entry.top_vehicle_kills));
PROCESS_TAG(this->INTERNAL_VICTIM_BUILDING_KILLS_TAG, Jupiter::StringS::Format("%u", entry.top_building_kills));
PROCESS_TAG(this->INTERNAL_VICTIM_DEFENCE_KILLS_TAG, Jupiter::StringS::Format("%u", entry.top_defence_kills));
PROCESS_TAG(this->INTERNAL_VICTIM_CAPTURES_TAG, Jupiter::StringS::Format("%u", entry.top_captures));
PROCESS_TAG(this->INTERNAL_VICTIM_GAME_TIME_TAG, Jupiter::StringS::Format("%u", entry.top_game_time));
PROCESS_TAG(this->INTERNAL_VICTIM_BEACON_PLACEMENTS_TAG, Jupiter::StringS::Format("%u", entry.top_beacon_placements));
PROCESS_TAG(this->INTERNAL_VICTIM_BEACON_DISARMS_TAG, Jupiter::StringS::Format("%u", entry.top_beacon_disarms));
PROCESS_TAG(this->INTERNAL_VICTIM_PROXY_PLACEMENTS_TAG, Jupiter::StringS::Format("%u", entry.top_proxy_placements));
PROCESS_TAG(this->INTERNAL_VICTIM_PROXY_DISARMS_TAG, Jupiter::StringS::Format("%u", entry.top_proxy_disarms));
}
void TagsImp::sanitizeTags(Jupiter::StringType &fmt)
@ -482,6 +609,7 @@ void TagsImp::sanitizeTags(Jupiter::StringType &fmt)
fmt.replace(this->teamLongTag, this->INTERNAL_TEAM_LONG_TAG);
fmt.replace(this->pingTag, this->INTERNAL_PING_TAG);
fmt.replace(this->scoreTag, this->INTERNAL_SCORE_TAG);
fmt.replace(this->scorePerMinuteTag, this->INTERNAL_SCORE_PER_MINUTE_TAG);
fmt.replace(this->creditsTag, this->INTERNAL_CREDITS_TAG);
fmt.replace(this->killsTag, this->INTERNAL_KILLS_TAG);
fmt.replace(this->deathsTag, this->INTERNAL_DEATHS_TAG);
@ -491,10 +619,24 @@ void TagsImp::sanitizeTags(Jupiter::StringType &fmt)
fmt.replace(this->vehicleKillsTag, this->INTERNAL_VEHICLE_KILLS_TAG);
fmt.replace(this->buildingKillsTag, this->INTERNAL_BUILDING_KILLS_TAG);
fmt.replace(this->defenceKillsTag, this->INTERNAL_DEFENCE_KILLS_TAG);
fmt.replace(this->gameTimeTag, this->INTERNAL_GAME_TIME_TAG);
fmt.replace(this->gamesTag, this->INTERNAL_GAMES_TAG);
fmt.replace(this->GDIGamesTag, this->INTERNAL_GDI_GAMES_TAG);
fmt.replace(this->NodGamesTag, this->INTERNAL_NOD_GAMES_TAG);
fmt.replace(this->winsTag, this->INTERNAL_WINS_TAG);
fmt.replace(this->losesTag, this->INTERNAL_LOSES_TAG);
fmt.replace(this->GDIWinsTag, this->INTERNAL_GDI_WINS_TAG);
fmt.replace(this->NodWinsTag, this->INTERNAL_NOD_WINS_TAG);
fmt.replace(this->tiesTag, this->INTERNAL_TIES_TAG);
fmt.replace(this->lossesTag, this->INTERNAL_LOSSES_TAG);
fmt.replace(this->GDILossesTag, this->INTERNAL_GDI_LOSSES_TAG);
fmt.replace(this->NodLossesTag, this->INTERNAL_NOD_LOSSES_TAG);
fmt.replace(this->winLossRatioTag, this->INTERNAL_WIN_LOSS_RATIO_TAG);
fmt.replace(this->GDIWinLossRatioTag, this->INTERNAL_GDI_WIN_LOSS_RATIO_TAG);
fmt.replace(this->NodWinLossRatioTag, this->INTERNAL_NOD_WIN_LOSS_RATIO_TAG);
fmt.replace(this->beaconPlacementsTag, this->INTERNAL_BEACON_PLACEMENTS_TAG);
fmt.replace(this->beaconDisarmsTag, this->INTERNAL_BEACON_DISARMS_TAG);
fmt.replace(this->proxyPlacementsTag, this->INTERNAL_PROXY_PLACEMENTS_TAG);
fmt.replace(this->proxyDisarmsTag, this->INTERNAL_PROXY_DISARMS_TAG);
fmt.replace(this->capturesTag, this->INTERNAL_CAPTURES_TAG);
fmt.replace(this->stealsTag, this->INTERNAL_STEALS_TAG);
fmt.replace(this->stolenTag, this->INTERNAL_STOLEN_TAG);
@ -518,6 +660,7 @@ void TagsImp::sanitizeTags(Jupiter::StringType &fmt)
fmt.replace(this->victimTeamLongTag, this->INTERNAL_VICTIM_TEAM_LONG_TAG);
fmt.replace(this->victimPingTag, this->INTERNAL_VICTIM_PING_TAG);
fmt.replace(this->victimScoreTag, this->INTERNAL_VICTIM_SCORE_TAG);
fmt.replace(this->victimScorePerMinuteTag, this->INTERNAL_SCORE_PER_MINUTE_TAG);
fmt.replace(this->victimCreditsTag, this->INTERNAL_VICTIM_CREDITS_TAG);
fmt.replace(this->victimKillsTag, this->INTERNAL_VICTIM_KILLS_TAG);
fmt.replace(this->victimDeathsTag, this->INTERNAL_VICTIM_DEATHS_TAG);
@ -527,10 +670,24 @@ void TagsImp::sanitizeTags(Jupiter::StringType &fmt)
fmt.replace(this->victimVehicleKillsTag, this->INTERNAL_VICTIM_VEHICLE_KILLS_TAG);
fmt.replace(this->victimBuildingKillsTag, this->INTERNAL_VICTIM_BUILDING_KILLS_TAG);
fmt.replace(this->victimDefenceKillsTag, this->INTERNAL_VICTIM_DEFENCE_KILLS_TAG);
fmt.replace(this->victimGameTimeTag, this->INTERNAL_VICTIM_GAME_TIME_TAG);
fmt.replace(this->victimGamesTag, this->INTERNAL_VICTIM_GAMES_TAG);
fmt.replace(this->victimGDIGamesTag, this->INTERNAL_VICTIM_GDI_GAMES_TAG);
fmt.replace(this->victimNodGamesTag, this->INTERNAL_VICTIM_NOD_GAMES_TAG);
fmt.replace(this->victimWinsTag, this->INTERNAL_VICTIM_WINS_TAG);
fmt.replace(this->victimLosesTag, this->INTERNAL_VICTIM_LOSES_TAG);
fmt.replace(this->victimGDIWinsTag, this->INTERNAL_VICTIM_GDI_WINS_TAG);
fmt.replace(this->victimNodWinsTag, this->INTERNAL_VICTIM_NOD_WINS_TAG);
fmt.replace(this->victimTiesTag, this->INTERNAL_VICTIM_TIES_TAG);
fmt.replace(this->victimLossesTag, this->INTERNAL_VICTIM_LOSSES_TAG);
fmt.replace(this->victimGDILossesTag, this->INTERNAL_VICTIM_GDI_LOSSES_TAG);
fmt.replace(this->victimNodLossesTag, this->INTERNAL_VICTIM_NOD_LOSSES_TAG);
fmt.replace(this->victimWinLossRatioTag, this->INTERNAL_VICTIM_WIN_LOSS_RATIO_TAG);
fmt.replace(this->victimGDIWinLossRatioTag, this->INTERNAL_VICTIM_GDI_WIN_LOSS_RATIO_TAG);
fmt.replace(this->victimNodWinLossRatioTag, this->INTERNAL_VICTIM_NOD_WIN_LOSS_RATIO_TAG);
fmt.replace(this->victimBeaconPlacementsTag, this->INTERNAL_VICTIM_BEACON_PLACEMENTS_TAG);
fmt.replace(this->victimBeaconDisarmsTag, this->INTERNAL_VICTIM_BEACON_DISARMS_TAG);
fmt.replace(this->victimProxyPlacementsTag, this->INTERNAL_VICTIM_PROXY_PLACEMENTS_TAG);
fmt.replace(this->victimProxyDisarmsTag, this->INTERNAL_VICTIM_PROXY_DISARMS_TAG);
fmt.replace(this->victimCapturesTag, this->INTERNAL_VICTIM_CAPTURES_TAG);
fmt.replace(this->victimStealsTag, this->INTERNAL_VICTIM_STEALS_TAG);
fmt.replace(this->victimStolenTag, this->INTERNAL_VICTIM_STOLEN_TAG);
@ -554,6 +711,8 @@ void TagsImp::sanitizeTags(Jupiter::StringType &fmt)
fmt.replace(this->newNameTag, this->INTERNAL_NEW_NAME_TAG);
fmt.replace(this->winScoreTag, this->INTERNAL_WIN_SCORE_TAG);
fmt.replace(this->loseScoreTag, this->INTERNAL_LOSE_SCORE_TAG);
fmt.replace(this->lastGameTag, this->INTERNAL_LAST_GAME_TAG);
fmt.replace(this->rankTag, this->INTERNAL_RANK_TAG);
Jupiter::ArrayList<RenX::Plugin> &xPlugins = *RenX::getCore()->getPlugins();
for (size_t i = 0; i < xPlugins.size(); i++)
@ -582,6 +741,11 @@ void RenX::processTags(Jupiter::StringType &msg, const RenX::Server *server, con
_tags.processTags(msg, server, player, victim, building);
}
void RenX::processTags(Jupiter::StringType &msg, const RenX::LadderDatabase::Entry &entry)
{
_tags.processTags(msg, entry);
}
void RenX::sanitizeTags(Jupiter::StringType &fmt)
{
_tags.sanitizeTags(fmt);

82
RenX.Core/RenX_Tags.h

@ -27,6 +27,7 @@
#include "Jupiter/String.h"
#include "Jupiter/CString.h"
#include "RenX.h"
#include "RenX_LadderDatabase.h"
/** DLL Linkage Nagging */
#if defined _MSC_VER
@ -39,8 +40,10 @@ namespace RenX
/** Forward declarations */
struct PlayerInfo;
class Server;
struct BuildingInfo;
RENX_API void processTags(Jupiter::StringType &msg, const RenX::Server *server = nullptr, const RenX::PlayerInfo *player = nullptr, const RenX::PlayerInfo *victim = nullptr, const RenX::BuildingInfo *building = nullptr);
RENX_API void processTags(Jupiter::StringType &msg, const RenX::LadderDatabase::Entry &entry);
RENX_API void sanitizeTags(Jupiter::StringType &fmt);
RENX_API const Jupiter::ReadableString &getUniqueInternalTag();
@ -86,6 +89,7 @@ namespace RenX
Jupiter::StringS INTERNAL_TEAM_LONG_TAG;
Jupiter::StringS INTERNAL_PING_TAG;
Jupiter::StringS INTERNAL_SCORE_TAG;
Jupiter::StringS INTERNAL_SCORE_PER_MINUTE_TAG;
Jupiter::StringS INTERNAL_CREDITS_TAG;
Jupiter::StringS INTERNAL_KILLS_TAG;
Jupiter::StringS INTERNAL_DEATHS_TAG;
@ -95,10 +99,24 @@ namespace RenX
Jupiter::StringS INTERNAL_VEHICLE_KILLS_TAG;
Jupiter::StringS INTERNAL_BUILDING_KILLS_TAG;
Jupiter::StringS INTERNAL_DEFENCE_KILLS_TAG;
Jupiter::StringS INTERNAL_GAME_TIME_TAG;
Jupiter::StringS INTERNAL_GAMES_TAG;
Jupiter::StringS INTERNAL_GDI_GAMES_TAG;
Jupiter::StringS INTERNAL_NOD_GAMES_TAG;
Jupiter::StringS INTERNAL_WINS_TAG;
Jupiter::StringS INTERNAL_LOSES_TAG;
Jupiter::StringS INTERNAL_GDI_WINS_TAG;
Jupiter::StringS INTERNAL_NOD_WINS_TAG;
Jupiter::StringS INTERNAL_TIES_TAG;
Jupiter::StringS INTERNAL_LOSSES_TAG;
Jupiter::StringS INTERNAL_GDI_LOSSES_TAG;
Jupiter::StringS INTERNAL_NOD_LOSSES_TAG;
Jupiter::StringS INTERNAL_WIN_LOSS_RATIO_TAG;
Jupiter::StringS INTERNAL_GDI_WIN_LOSS_RATIO_TAG;
Jupiter::StringS INTERNAL_NOD_WIN_LOSS_RATIO_TAG;
Jupiter::StringS INTERNAL_BEACON_PLACEMENTS_TAG;
Jupiter::StringS INTERNAL_BEACON_DISARMS_TAG;
Jupiter::StringS INTERNAL_PROXY_PLACEMENTS_TAG;
Jupiter::StringS INTERNAL_PROXY_DISARMS_TAG;
Jupiter::StringS INTERNAL_CAPTURES_TAG;
Jupiter::StringS INTERNAL_STEALS_TAG;
Jupiter::StringS INTERNAL_STOLEN_TAG;
@ -122,6 +140,7 @@ namespace RenX
Jupiter::StringS INTERNAL_VICTIM_TEAM_LONG_TAG;
Jupiter::StringS INTERNAL_VICTIM_PING_TAG;
Jupiter::StringS INTERNAL_VICTIM_SCORE_TAG;
Jupiter::StringS INTERNAL_VICTIM_SCORE_PER_MINUTE_TAG;
Jupiter::StringS INTERNAL_VICTIM_CREDITS_TAG;
Jupiter::StringS INTERNAL_VICTIM_KILLS_TAG;
Jupiter::StringS INTERNAL_VICTIM_DEATHS_TAG;
@ -131,10 +150,24 @@ namespace RenX
Jupiter::StringS INTERNAL_VICTIM_VEHICLE_KILLS_TAG;
Jupiter::StringS INTERNAL_VICTIM_BUILDING_KILLS_TAG;
Jupiter::StringS INTERNAL_VICTIM_DEFENCE_KILLS_TAG;
Jupiter::StringS INTERNAL_VICTIM_GAME_TIME_TAG;
Jupiter::StringS INTERNAL_VICTIM_GAMES_TAG;
Jupiter::StringS INTERNAL_VICTIM_GDI_GAMES_TAG;
Jupiter::StringS INTERNAL_VICTIM_NOD_GAMES_TAG;
Jupiter::StringS INTERNAL_VICTIM_WINS_TAG;
Jupiter::StringS INTERNAL_VICTIM_LOSES_TAG;
Jupiter::StringS INTERNAL_VICTIM_GDI_WINS_TAG;
Jupiter::StringS INTERNAL_VICTIM_NOD_WINS_TAG;
Jupiter::StringS INTERNAL_VICTIM_TIES_TAG;
Jupiter::StringS INTERNAL_VICTIM_LOSSES_TAG;
Jupiter::StringS INTERNAL_VICTIM_GDI_LOSSES_TAG;
Jupiter::StringS INTERNAL_VICTIM_NOD_LOSSES_TAG;
Jupiter::StringS INTERNAL_VICTIM_WIN_LOSS_RATIO_TAG;
Jupiter::StringS INTERNAL_VICTIM_GDI_WIN_LOSS_RATIO_TAG;
Jupiter::StringS INTERNAL_VICTIM_NOD_WIN_LOSS_RATIO_TAG;
Jupiter::StringS INTERNAL_VICTIM_BEACON_PLACEMENTS_TAG;
Jupiter::StringS INTERNAL_VICTIM_BEACON_DISARMS_TAG;
Jupiter::StringS INTERNAL_VICTIM_PROXY_PLACEMENTS_TAG;
Jupiter::StringS INTERNAL_VICTIM_PROXY_DISARMS_TAG;
Jupiter::StringS INTERNAL_VICTIM_CAPTURES_TAG;
Jupiter::StringS INTERNAL_VICTIM_STEALS_TAG;
Jupiter::StringS INTERNAL_VICTIM_STOLEN_TAG;
@ -158,6 +191,8 @@ namespace RenX
Jupiter::StringS INTERNAL_NEW_NAME_TAG;
Jupiter::StringS INTERNAL_WIN_SCORE_TAG;
Jupiter::StringS INTERNAL_LOSE_SCORE_TAG;
Jupiter::StringS INTERNAL_LAST_GAME_TAG;
Jupiter::StringS INTERNAL_RANK_TAG;
/** External message tags */
@ -197,6 +232,7 @@ namespace RenX
Jupiter::StringS teamLongTag;
Jupiter::StringS pingTag;
Jupiter::StringS scoreTag;
Jupiter::StringS scorePerMinuteTag;
Jupiter::StringS creditsTag;
Jupiter::StringS killsTag;
Jupiter::StringS deathsTag;
@ -206,10 +242,24 @@ namespace RenX
Jupiter::StringS vehicleKillsTag;
Jupiter::StringS buildingKillsTag;
Jupiter::StringS defenceKillsTag;
Jupiter::StringS gameTimeTag;
Jupiter::StringS gamesTag;
Jupiter::StringS GDIGamesTag;
Jupiter::StringS NodGamesTag;
Jupiter::StringS winsTag;
Jupiter::StringS losesTag;
Jupiter::StringS GDIWinsTag;
Jupiter::StringS NodWinsTag;
Jupiter::StringS tiesTag;
Jupiter::StringS lossesTag;
Jupiter::StringS GDILossesTag;
Jupiter::StringS NodLossesTag;
Jupiter::StringS winLossRatioTag;
Jupiter::StringS GDIWinLossRatioTag;
Jupiter::StringS NodWinLossRatioTag;
Jupiter::StringS beaconPlacementsTag;
Jupiter::StringS beaconDisarmsTag;
Jupiter::StringS proxyPlacementsTag;
Jupiter::StringS proxyDisarmsTag;
Jupiter::StringS capturesTag;
Jupiter::StringS stealsTag;
Jupiter::StringS stolenTag;
@ -233,6 +283,7 @@ namespace RenX
Jupiter::StringS victimTeamLongTag;
Jupiter::StringS victimPingTag;
Jupiter::StringS victimScoreTag;
Jupiter::StringS victimScorePerMinuteTag;
Jupiter::StringS victimCreditsTag;
Jupiter::StringS victimKillsTag;
Jupiter::StringS victimDeathsTag;
@ -242,10 +293,24 @@ namespace RenX
Jupiter::StringS victimVehicleKillsTag;
Jupiter::StringS victimBuildingKillsTag;
Jupiter::StringS victimDefenceKillsTag;
Jupiter::StringS victimGameTimeTag;
Jupiter::StringS victimGamesTag;
Jupiter::StringS victimGDIGamesTag;
Jupiter::StringS victimNodGamesTag;
Jupiter::StringS victimWinsTag;
Jupiter::StringS victimLosesTag;
Jupiter::StringS victimGDIWinsTag;
Jupiter::StringS victimNodWinsTag;
Jupiter::StringS victimTiesTag;
Jupiter::StringS victimLossesTag;
Jupiter::StringS victimGDILossesTag;
Jupiter::StringS victimNodLossesTag;
Jupiter::StringS victimWinLossRatioTag;
Jupiter::StringS victimGDIWinLossRatioTag;
Jupiter::StringS victimNodWinLossRatioTag;
Jupiter::StringS victimBeaconPlacementsTag;
Jupiter::StringS victimBeaconDisarmsTag;
Jupiter::StringS victimProxyPlacementsTag;
Jupiter::StringS victimProxyDisarmsTag;
Jupiter::StringS victimCapturesTag;
Jupiter::StringS victimStealsTag;
Jupiter::StringS victimStolenTag;
@ -269,11 +334,20 @@ namespace RenX
Jupiter::StringS newNameTag;
Jupiter::StringS winScoreTag;
Jupiter::StringS loseScoreTag;
Jupiter::StringS lastGameTag;
Jupiter::StringS rankTag;
};
RENX_API extern Tags *tags;
}
/** Helper macro for processing tags */
#define PROCESS_TAG(tag, value) \
while(true) { \
index = msg.find(tag); \
if (index == Jupiter::INVALID_INDEX) break; \
msg.replace(index, tag.size(), value); }
/** Re-enable warnings */
#if defined _MSC_VER
#pragma warning(pop)

86
RenX.Ladder.Web/RenX.Ladder.Web.vcxproj

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{57661A2A-EE94-4E9C-B792-AB756533DEFA}</ProjectGuid>
<RootNamespace>RenX.Ladder.Web</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(SolutionDir)$(Configuration)\Plugins\</OutDir>
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>../Bot;../Jupiter;../RenX.Core;../HTTPServer</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="RenX_Ladder_Web.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="RenX_Ladder_Web.cpp" />
</ItemGroup>
<ItemGroup>
<Library Include="..\Jupiter\Release\Jupiter.lib" />
<Library Include="..\Release\Bot.lib" />
<Library Include="..\Release\Plugins\HTTPServer.lib" />
<Library Include="..\Release\Plugins\RenX.Core.lib" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

41
RenX.Ladder.Web/RenX.Ladder.Web.vcxproj.filters

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="RenX_Ladder_Web.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="RenX_Ladder_Web.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Library Include="..\Release\Plugins\RenX.Core.lib">
<Filter>Resource Files</Filter>
</Library>
<Library Include="..\Release\Bot.lib">
<Filter>Resource Files</Filter>
</Library>
<Library Include="..\Jupiter\Release\Jupiter.lib">
<Filter>Resource Files</Filter>
</Library>
<Library Include="..\Release\Plugins\HTTPServer.lib">
<Filter>Resource Files</Filter>
</Library>
</ItemGroup>
</Project>

339
RenX.Ladder.Web/RenX_Ladder_Web.cpp

@ -0,0 +1,339 @@
/**
* 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 <jessica.aj@outlook.com>
*/
#include "Jupiter/IRC_Client.h"
#include "Jupiter/INIFile.h"
#include "Jupiter/HTTP.h"
#include "Jupiter/HTTP_QueryString.h"
#include "HTTPServer.h"
#include "RenX_Tags.h"
#include "RenX_Ladder_Web.h"
using namespace Jupiter::literals;
RenX_Ladder_WebPlugin::RenX_Ladder_WebPlugin()
{
RenX_Ladder_WebPlugin::ladder_page_name = Jupiter::IRC::Client::Config->get(RenX_Ladder_WebPlugin::name, "LadderPageName"_jrs, ""_jrs);
RenX_Ladder_WebPlugin::search_page_name = Jupiter::IRC::Client::Config->get(RenX_Ladder_WebPlugin::name, "SearchPageName"_jrs, "search"_jrs);
RenX_Ladder_WebPlugin::profile_page_name = Jupiter::IRC::Client::Config->get(RenX_Ladder_WebPlugin::name, "ProfilePageName"_jrs, "profile"_jrs);
RenX_Ladder_WebPlugin::web_hostname = Jupiter::IRC::Client::Config->get(RenX_Ladder_WebPlugin::name, "Hostname"_jrs, ""_jrs);
RenX_Ladder_WebPlugin::web_path = Jupiter::IRC::Client::Config->get(RenX_Ladder_WebPlugin::name, "Path"_jrs, "/"_jrs);
this->OnRehash();
/** Initialize content */
Jupiter::HTTP::Server &server = getHTTPServer();
Jupiter::HTTP::Server::Content *content = new Jupiter::HTTP::Server::Content(RenX_Ladder_WebPlugin::ladder_page_name, handle_ladder_page);
content->language = &Jupiter::HTTP::Content::Language::ENGLISH;
content->type = &Jupiter::HTTP::Content::Type::Text::HTML;
content->charset = &Jupiter::HTTP::Content::Type::Text::Charset::UTF8;
server.hook(RenX_Ladder_WebPlugin::web_hostname, RenX_Ladder_WebPlugin::web_path, content);
content = new Jupiter::HTTP::Server::Content(RenX_Ladder_WebPlugin::search_page_name, handle_search_page);
content->language = &Jupiter::HTTP::Content::Language::ENGLISH;
content->type = &Jupiter::HTTP::Content::Type::Text::HTML;
content->charset = &Jupiter::HTTP::Content::Type::Text::Charset::UTF8;
server.hook(RenX_Ladder_WebPlugin::web_hostname, RenX_Ladder_WebPlugin::web_path, content);
content = new Jupiter::HTTP::Server::Content(RenX_Ladder_WebPlugin::profile_page_name, handle_profile_page);
content->language = &Jupiter::HTTP::Content::Language::ENGLISH;
content->type = &Jupiter::HTTP::Content::Type::Text::HTML;
content->charset = &Jupiter::HTTP::Content::Type::Text::Charset::UTF8;
server.hook(RenX_Ladder_WebPlugin::web_hostname, RenX_Ladder_WebPlugin::web_path, content);
}
RenX_Ladder_WebPlugin::~RenX_Ladder_WebPlugin()
{
Jupiter::HTTP::Server &server = getHTTPServer();
server.remove(RenX_Ladder_WebPlugin::web_hostname, RenX_Ladder_WebPlugin::web_path, RenX_Ladder_WebPlugin::ladder_page_name);
server.remove(RenX_Ladder_WebPlugin::web_hostname, RenX_Ladder_WebPlugin::web_path, RenX_Ladder_WebPlugin::search_page_name);
server.remove(RenX_Ladder_WebPlugin::web_hostname, RenX_Ladder_WebPlugin::web_path, RenX_Ladder_WebPlugin::profile_page_name);
}
int RenX_Ladder_WebPlugin::OnRehash()
{
FILE *file;
int chr;
RenX_Ladder_WebPlugin::web_header_filename = Jupiter::IRC::Client::Config->get(RenX_Ladder_WebPlugin::name, "HeaderFilename"_jrs, "RenX.Ladder.Web.Header.html"_jrs);
RenX_Ladder_WebPlugin::web_footer_filename = Jupiter::IRC::Client::Config->get(RenX_Ladder_WebPlugin::name, "FooterFilename"_jrs, "RenX.Ladder.Web.Footer.html"_jrs);
RenX_Ladder_WebPlugin::web_profile_filename = Jupiter::IRC::Client::Config->get(RenX_Ladder_WebPlugin::name, "ProfileFilename"_jrs, "RenX.Ladder.Web.Profile.html"_jrs);
RenX_Ladder_WebPlugin::web_ladder_table_header_filename = Jupiter::IRC::Client::Config->get(RenX_Ladder_WebPlugin::name, "LadderTableHeaderFilename"_jrs, "RenX.Ladder.Web.Ladder.Table.Header.html"_jrs);
RenX_Ladder_WebPlugin::web_ladder_table_footer_filename = Jupiter::IRC::Client::Config->get(RenX_Ladder_WebPlugin::name, "LadderTableFooterFilename"_jrs, "RenX.Ladder.Web.Ladder.Table.Footer.html"_jrs);
RenX_Ladder_WebPlugin::entry_table_row = Jupiter::IRC::Client::Config->get(RenX_Ladder_WebPlugin::name, "EntryTableRow"_jrs, "<tr><td>{RANK}</td><td><a href=\"profile?id={STEAM}\">{NAME}</a></td><td>{SCORE}</td><td>{SPM}</td><td>{KILLS}</td><td>{DEATHS}</td><td>{KDR}</td><td>{NODGAMES}</td><td>{NODWINS}</td><td>{NODLOSSES}</td><td>{NWLR}</td><td>{GDIGAMES}</td><td>{GDIWINS}</td><td>{GDILOSSES}</td><td>{GWLR}</td></tr>"_jrs);
RenX::sanitizeTags(RenX_Ladder_WebPlugin::entry_table_row);
RenX_Ladder_WebPlugin::header.erase();
RenX_Ladder_WebPlugin::footer.erase();
RenX_Ladder_WebPlugin::entry_profile.erase();
RenX_Ladder_WebPlugin::ladder_table_header.erase();
RenX_Ladder_WebPlugin::ladder_table_footer.erase();
/** Load header */
if (RenX_Ladder_WebPlugin::web_header_filename.isNotEmpty())
{
file = fopen(RenX_Ladder_WebPlugin::web_header_filename.c_str(), "rb");
if (file != nullptr)
{
while ((chr = fgetc(file)) != EOF)
RenX_Ladder_WebPlugin::header += chr;
fclose(file);
}
}
/** Load footer */
if (RenX_Ladder_WebPlugin::web_footer_filename.isNotEmpty())
{
file = fopen(RenX_Ladder_WebPlugin::web_footer_filename.c_str(), "rb");
if (file != nullptr)
{
while ((chr = fgetc(file)) != EOF)
RenX_Ladder_WebPlugin::footer += chr;
fclose(file);
}
}
/** Load profile */
if (RenX_Ladder_WebPlugin::web_profile_filename.isNotEmpty())
{
file = fopen(RenX_Ladder_WebPlugin::web_profile_filename.c_str(), "rb");
if (file != nullptr)
{
while ((chr = fgetc(file)) != EOF)
RenX_Ladder_WebPlugin::entry_profile += chr;
RenX::sanitizeTags(RenX_Ladder_WebPlugin::entry_profile);
fclose(file);
}
}
/** Load table header */
if (RenX_Ladder_WebPlugin::web_ladder_table_header_filename.isNotEmpty())
{
file = fopen(RenX_Ladder_WebPlugin::web_ladder_table_header_filename.c_str(), "rb");
if (file != nullptr)
{
while ((chr = fgetc(file)) != EOF)
RenX_Ladder_WebPlugin::ladder_table_header += chr;
fclose(file);
}
}
/** Load table footer */
if (RenX_Ladder_WebPlugin::web_ladder_table_footer_filename.isNotEmpty())
{
file = fopen(RenX_Ladder_WebPlugin::web_ladder_table_footer_filename.c_str(), "rb");
if (file != nullptr)
{
while ((chr = fgetc(file)) != EOF)
RenX_Ladder_WebPlugin::ladder_table_footer += chr;
fclose(file);
}
}
return 0;
}
/** Ladder page */
Jupiter::String RenX_Ladder_WebPlugin::generate_entry_table(size_t index, size_t count)
{
if (RenX::ladder_databases.size() == 0)
return Jupiter::String("Error: No ladder databases loaded"_jrs);
RenX::LadderDatabase *db = RenX::ladder_databases.get(0);
if (db->getEntries() == 0) // No ladder data
return Jupiter::String("Error: No ladder data"_jrs);
if (index >= db->getEntries() || count == 0) // Invalid entry range
return Jupiter::String("Error: Invalid range"_jrs);
if (index + count > db->getEntries()) // Invalid entry range; use valid portion of range
count = db->getEntries() - index;
RenX::LadderDatabase::Entry *node = db->getHead();
// iterate to requested index
while (index != 0)
{
node = node->next;
--index;
}
// table header
Jupiter::String result(2048);
result = RenX_Ladder_WebPlugin::ladder_table_header;
// append rows
Jupiter::String row(256);
while (count != 0)
{
row = RenX_Ladder_WebPlugin::entry_table_row;
RenX::processTags(row, *node);
result += row;
--count;
}
// table footer
result += RenX_Ladder_WebPlugin::ladder_table_footer;
return result;
}
Jupiter::String *RenX_Ladder_WebPlugin::generate_ladder_page(size_t index, size_t count)
{
Jupiter::String *result = new Jupiter::String(RenX_Ladder_WebPlugin::header);
result->concat(this->generate_entry_table(index, count));
result->concat(RenX_Ladder_WebPlugin::footer);
return result;
}
/** Search page */
Jupiter::String *RenX_Ladder_WebPlugin::generate_search_page(const Jupiter::ReadableString &name)
{
Jupiter::String *result = new Jupiter::String(RenX_Ladder_WebPlugin::header);
if (RenX::ladder_databases.size() == 0)
{
result->concat("Error: No ladder databases loaded"_jrs);
result->concat(RenX_Ladder_WebPlugin::footer);
return result;
}
RenX::LadderDatabase *db = RenX::ladder_databases.get(0);
if (db->getEntries() == 0) // No ladder data
{
result->concat("Error: No ladder data"_jrs);
result->concat(RenX_Ladder_WebPlugin::footer);
return result;
}
result->concat(RenX_Ladder_WebPlugin::ladder_table_header);
// append rows
Jupiter::String row(256);
RenX::LadderDatabase::Entry *node = db->getHead();
while (node != nullptr)
{
if (node->most_recent_name.findi(name) != Jupiter::INVALID_INDEX) // match found
{
row = RenX_Ladder_WebPlugin::entry_table_row;
RenX::processTags(row, *node);
result->concat(row);
}
node = node->next;
}
result->concat(RenX_Ladder_WebPlugin::ladder_table_footer);
result->concat(RenX_Ladder_WebPlugin::footer);
return result;
}
/** Profile page */
Jupiter::String *RenX_Ladder_WebPlugin::generate_profile_page(uint64_t steam_id)
{
Jupiter::String *result = new Jupiter::String(RenX_Ladder_WebPlugin::header);
if (RenX::ladder_databases.size() == 0)
{
result->concat("Error: No ladder databases loaded"_jrs);
result->concat(RenX_Ladder_WebPlugin::footer);
return result;
}
RenX::LadderDatabase *db = RenX::ladder_databases.get(0);
if (db->getEntries() == 0) // No ladder data
{
result->concat("Error: No ladder data"_jrs);
result->concat(RenX_Ladder_WebPlugin::footer);
return result;
}
RenX::LadderDatabase::Entry *entry = db->getHead();
while (entry != nullptr)
{
if (entry->steam_id == steam_id) // match found
break;
entry = entry->next;
}
if (entry == nullptr)
result->concat("Error: Player not found"_jrs);
else
{
Jupiter::String profile_data(RenX_Ladder_WebPlugin::entry_profile);
RenX::processTags(profile_data, *entry);
result->concat(profile_data);
}
result->concat(RenX_Ladder_WebPlugin::footer);
return result;
}
// Plugin instantiation and entry point.
RenX_Ladder_WebPlugin pluginInstance;
/** Content functions */
Jupiter::ReadableString *handle_ladder_page(const Jupiter::ReadableString &query_string)
{
size_t start_index = 0, count = 50;
if (query_string.isNotEmpty())
{
Jupiter::HTTP::HTMLFormResponse html_form_response(query_string);
start_index = static_cast<size_t>(html_form_response.table.getInt("start"_jrs, 0));
count = static_cast<size_t>(html_form_response.table.getInt("count"_jrs, 50));
}
return pluginInstance.generate_ladder_page(start_index, count);
}
Jupiter::ReadableString *handle_search_page(const Jupiter::ReadableString &query_string)
{
Jupiter::ReferenceString name;
if (query_string.isNotEmpty())
{
Jupiter::HTTP::HTMLFormResponse html_form_response(query_string);
name = html_form_response.table.get("name"_jrs);
}
if (name.isEmpty()) // Generate ladder page when no name specified
return handle_ladder_page(query_string);
return pluginInstance.generate_search_page(name);
}
Jupiter::ReadableString *handle_profile_page(const Jupiter::ReadableString &query_string)
{
uint64_t steam_id = 0;
if (query_string.isNotEmpty())
{
Jupiter::HTTP::HTMLFormResponse html_form_response(query_string);
steam_id = html_form_response.table.getLongLong("id"_jrs);
}
return pluginInstance.generate_profile_page(steam_id);
}
extern "C" __declspec(dllexport) Jupiter::Plugin *getPlugin()
{
return &pluginInstance;
}

66
RenX.Ladder.Web/RenX_Ladder_Web.h

@ -0,0 +1,66 @@
/**
* 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 <jessica.aj@outlook.com>
*/
#if !defined _RENX_LADDER_WEB_H
#define _RENX_LADDER_WEB_H
#include "Jupiter/Plugin.h"
#include "Jupiter/Reference_String.h"
#include "Jupiter/CString.h"
#include "RenX_Plugin.h"
class RenX_Ladder_WebPlugin : public RenX::Plugin
{
protected:
Jupiter::String generate_entry_table(size_t index, size_t count);
public:
Jupiter::StringS header;
Jupiter::StringS footer;
Jupiter::String *generate_ladder_page(size_t start_index, size_t count);
Jupiter::String *generate_search_page(const Jupiter::ReadableString &name);
Jupiter::String *generate_profile_page(uint64_t steam_id);
RenX_Ladder_WebPlugin();
~RenX_Ladder_WebPlugin();
public: // Jupiter::Plugin
const Jupiter::ReadableString &getName() override { return name; }
int OnRehash() override;
private:
STRING_LITERAL_AS_NAMED_REFERENCE(name, "RenX.Ladder.Web");
/** Configuration variables */
Jupiter::StringS ladder_page_name, search_page_name, profile_page_name, ladder_table_header, ladder_table_footer;
Jupiter::StringS web_hostname;
Jupiter::StringS web_path;
Jupiter::CStringS web_header_filename;
Jupiter::CStringS web_footer_filename;
Jupiter::CStringS web_profile_filename;
Jupiter::CStringS web_ladder_table_header_filename;
Jupiter::CStringS web_ladder_table_footer_filename;
Jupiter::StringS entry_table_row, entry_profile;
};
Jupiter::ReadableString *handle_ladder_page(const Jupiter::ReadableString &parameters);
Jupiter::ReadableString *handle_search_page(const Jupiter::ReadableString &parameters);
Jupiter::ReadableString *handle_profile_page(const Jupiter::ReadableString &parameters);
#endif // _RENX_LADDER_WEB_H

4
RenX.Ladder/RenX.Ladder.vcxproj

@ -60,7 +60,7 @@
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>../Bot;../Jupiter;../RenX.Core</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;RENX_LADDER_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -69,12 +69,10 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="RenX_LadderDatabase.h" />
<ClInclude Include="RenX_Ladder.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="RenX_Ladder.cpp" />
<ClCompile Include="RenX_LadderDatabase.cpp" />
</ItemGroup>
<ItemGroup>
<Library Include="..\Jupiter\Release\Jupiter.lib" />

6
RenX.Ladder/RenX.Ladder.vcxproj.filters

@ -29,16 +29,10 @@
<ClCompile Include="RenX_Ladder.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="RenX_LadderDatabase.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="RenX_Ladder.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="RenX_LadderDatabase.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

113
RenX.Ladder/RenX_Ladder.cpp

@ -41,107 +41,6 @@ RenX_LadderPlugin::RenX_LadderPlugin()
RenX_LadderPlugin::database.process_file(RenX_LadderPlugin::db_filename);
}
void RenX_LadderPlugin::updateLadder(RenX::Server *server, const RenX::TeamType &team)
{
if (server->players.size() != 0)
{
// update player stats in memory
RenX::PlayerInfo *player;
RenX_LadderDatabase::Entry *entry;
for (Jupiter::DLList<RenX::PlayerInfo>::Node *node = server->players.getNode(0); node != nullptr; node = node->next)
{
player = node->data;
if (player->steamid != 0 && (player->ban_flags & RenX::BanDatabase::Entry::FLAG_TYPE_LADDER) == 0)
{
entry = RenX_LadderPlugin::database.getPlayerEntry(player->steamid);
if (entry == nullptr)
{
entry = new RenX_LadderDatabase::Entry();
RenX_LadderPlugin::database.append(entry);
entry->steam_id = player->steamid;
}
entry->total_score += static_cast<uint64_t>(player->score);
entry->total_kills += player->kills;
entry->total_deaths += player->deaths;
entry->total_headshot_kills += player->headshots;
entry->total_vehicle_kills += player->vehicleKills;
entry->total_building_kills += player->buildingKills;
entry->total_defence_kills += player->defenceKills;
entry->total_captures += player->captures;
entry->total_game_time += static_cast<uint32_t>(std::chrono::duration_cast<std::chrono::seconds>(server->getGameTime(player)).count());
++entry->total_games;
switch (player->team)
{
case RenX::TeamType::GDI:
++entry->total_gdi_games;
if (player->team == team)
++entry->total_wins, ++entry->total_gdi_wins;
break;
case RenX::TeamType::Nod:
++entry->total_nod_games;
if (player->team == team)
++entry->total_wins, ++entry->total_nod_wins;
break;
default:
if (player->team == team)
++entry->total_wins;
break;
}
entry->total_beacon_placements += player->beaconPlacements;
entry->total_beacon_disarms += player->beaconDisarms;
entry->total_proxy_placements += player->proxy_placements;
entry->total_proxy_disarms += player->proxy_disarms;
auto set_if_greater = [](uint32_t &src, const uint32_t &cmp)
{
if (cmp > src)
src = cmp;
};
set_if_greater(entry->top_score, static_cast<uint32_t>(player->score));
set_if_greater(entry->top_kills, player->kills);
set_if_greater(entry->most_deaths, player->deaths);
set_if_greater(entry->top_headshot_kills, player->headshots);
set_if_greater(entry->top_vehicle_kills, player->vehicleKills);
set_if_greater(entry->top_building_kills, player->buildingKills);
set_if_greater(entry->top_defence_kills, player->defenceKills);
set_if_greater(entry->top_captures, player->captures);
set_if_greater(entry->top_game_time, static_cast<uint32_t>(std::chrono::duration_cast<std::chrono::seconds>(server->getGameTime(player)).count()));
set_if_greater(entry->top_beacon_placements, player->beaconPlacements);
set_if_greater(entry->top_beacon_disarms, player->beaconDisarms);
set_if_greater(entry->top_proxy_placements, player->proxy_placements);
set_if_greater(entry->top_proxy_disarms, player->proxy_disarms);
entry->most_recent_ip = player->ip32;
entry->last_game = time(nullptr);
entry->most_recent_name = player->name;
}
}
// sort new stats
std::chrono::steady_clock::time_point start_time = std::chrono::steady_clock::now();
RenX_LadderPlugin::database.sort_entries();
std::chrono::steady_clock::duration sort_duration = std::chrono::steady_clock::now() - start_time;
// write new stats
start_time = std::chrono::steady_clock::now();
RenX_LadderPlugin::database.write(RenX_LadderPlugin::db_filename);
std::chrono::steady_clock::duration write_duration = std::chrono::steady_clock::now() - start_time;
if (RenX_LadderPlugin::output_times)
{
Jupiter::StringS str = Jupiter::StringS::Format("Ladder: %u entries sorted in %f seconds; Database written in %f seconds." ENDL,
RenX_LadderPlugin::database.getEntries(),
static_cast<double>(sort_duration.count()) * (static_cast<double>(std::chrono::steady_clock::duration::period::num / static_cast<double>(std::chrono::steady_clock::duration::period::den) * static_cast<double>(std::chrono::seconds::duration::period::den / std::chrono::seconds::duration::period::num))),
static_cast<double>(write_duration.count()) * (static_cast<double>(std::chrono::steady_clock::duration::period::num) / static_cast<double>(std::chrono::steady_clock::duration::period::den) * static_cast<double>(std::chrono::seconds::duration::period::den / std::chrono::seconds::duration::period::num)));
str.println(stdout);
server->sendLogChan(str);
}
}
}
/** Wait until the client list has been updated to update the ladder */
void RenX_LadderPlugin::RenX_OnGameOver(RenX::Server *server, RenX::WinType winType, const RenX::TeamType &team, int gScore, int nScore)
@ -163,7 +62,7 @@ void RenX_LadderPlugin::RenX_OnCommand(RenX::Server *server, const Jupiter::Read
{
server->varData.set(this->name, "w"_jrs, "0"_jrs);
RenX::TeamType team = static_cast<RenX::TeamType>(server->varData.get(this->name, "t"_jrs, "\0"_jrs).get(0));
RenX_LadderPlugin::updateLadder(server, team);
RenX_LadderPlugin::database.updateLadder(server, team, RenX_LadderPlugin::output_times);
}
}
}
@ -178,7 +77,7 @@ RenX_LadderPlugin pluginInstance;
/** Ladder Commands */
Jupiter::StringS FormatLadderResponse(RenX_LadderDatabase::Entry *entry, size_t rank)
Jupiter::StringS FormatLadderResponse(RenX::LadderDatabase::Entry *entry, size_t rank)
{
return Jupiter::StringS::Format("#%" PRIuPTR ": \"%.*s\" - Score: %" PRIu64 " - Kills: %" PRIu32 " - Deaths: %" PRIu32 " - KDR: %.2f - SPM: %.2f", rank, entry->most_recent_name.size(), entry->most_recent_name.ptr(), entry->total_score, entry->total_kills, entry->total_deaths, static_cast<double>(entry->total_kills) / (entry->total_deaths == 0 ? 1 : static_cast<double>(entry->total_deaths)), static_cast<double>(entry->total_score) / (entry->total_game_time == 0 ? 1.0 : static_cast<double>(entry->total_game_time)) * 60.0);
}
@ -196,7 +95,7 @@ GenericCommand::ResponseLine *LadderGenericCommand::trigger(const Jupiter::Reada
if (parameters.isEmpty())
return new GenericCommand::ResponseLine("Error: Too few parameters. Syntax: ladder <name | rank>"_jrs, GenericCommand::DisplayType::PrivateError);
RenX_LadderDatabase::Entry *entry;
RenX::LadderDatabase::Entry *entry;
size_t rank;
if (parameters.span("0123456789"_jrs) == parameters.size())
{
@ -211,11 +110,11 @@ GenericCommand::ResponseLine *LadderGenericCommand::trigger(const Jupiter::Reada
return new GenericCommand::ResponseLine(FormatLadderResponse(entry, rank), GenericCommand::DisplayType::PublicSuccess);
}
Jupiter::SLList<std::pair<RenX_LadderDatabase::Entry, size_t>> list = pluginInstance.database.getPlayerEntriesAndIndexByPartName(parameters, pluginInstance.getMaxLadderCommandPartNameOutput());
Jupiter::SLList<std::pair<RenX::LadderDatabase::Entry, size_t>> list = pluginInstance.database.getPlayerEntriesAndIndexByPartName(parameters, pluginInstance.getMaxLadderCommandPartNameOutput());
if (list.size() == 0)
return new GenericCommand::ResponseLine("Error: Player not found"_jrs, GenericCommand::DisplayType::PrivateError);
std::pair<RenX_LadderDatabase::Entry, size_t> *pair = list.remove(0);
std::pair<RenX::LadderDatabase::Entry, size_t> *pair = list.remove(0);
GenericCommand::ResponseLine *response_head = new GenericCommand::ResponseLine(FormatLadderResponse(std::addressof(pair->first), pair->second + 1), GenericCommand::DisplayType::PrivateSuccess);
GenericCommand::ResponseLine *response_end = response_head;
delete pair;
@ -253,7 +152,7 @@ void LadderGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player,
{
if (player->steamid != 0)
{
std::pair<RenX_LadderDatabase::Entry *, size_t> pair = pluginInstance.database.getPlayerEntryAndIndex(player->steamid);
std::pair<RenX::LadderDatabase::Entry *, size_t> pair = pluginInstance.database.getPlayerEntryAndIndex(player->steamid);
if (pair.first != nullptr)
source->sendMessage(FormatLadderResponse(pair.first, pair.second + 1));
else

15
RenX.Ladder/RenX_Ladder.h

@ -26,6 +26,12 @@
#include "RenX_LadderDatabase.h"
#include "RenX_GameCommand.h"
/** DLL Linkage Nagging */
#if defined _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4251)
#endif
class RenX_LadderPlugin : public RenX::Plugin
{
public:
@ -36,10 +42,8 @@ public:
size_t getMaxLadderCommandPartNameOutput() const;
RenX_LadderPlugin();
RenX_LadderDatabase database;
RenX::LadderDatabase database;
private:
void updateLadder(RenX::Server *server, const RenX::TeamType &team);
/** Configuration variables */
bool only_pure, output_times;
size_t max_ladder_command_part_name_output;
@ -50,4 +54,9 @@ private:
GENERIC_GENERIC_COMMAND(LadderGenericCommand)
GENERIC_GAME_COMMAND(LadderGameCommand)
/** Re-enable warnings */
#if defined _MSC_VER
#pragma warning(pop)
#endif
#endif // _RENX_LADDER_H_HEADER

347
RenX.Ladder/RenX_LadderDatabase.cpp

@ -1,347 +0,0 @@
/**
* Copyright (C) 2015 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 <jessica.aj@outlook.com>
*/
#include "RenX_LadderDatabase.h"
RenX_LadderDatabase::~RenX_LadderDatabase()
{
while (RenX_LadderDatabase::head != nullptr)
{
RenX_LadderDatabase::end = RenX_LadderDatabase::head;
RenX_LadderDatabase::head = RenX_LadderDatabase::head->next;
delete RenX_LadderDatabase::end;
}
}
void RenX_LadderDatabase::process_data(Jupiter::DataBuffer &buffer, FILE *file, fpos_t pos)
{
RenX_LadderDatabase::Entry *entry = new RenX_LadderDatabase::Entry();
// read data from buffer to entry
entry->steam_id = buffer.pop<uint64_t>();
entry->total_score = buffer.pop<uint64_t>();
entry->total_kills = buffer.pop<uint32_t>();
entry->total_deaths = buffer.pop<uint32_t>();
entry->total_headshot_kills = buffer.pop<uint32_t>();
entry->total_vehicle_kills = buffer.pop<uint32_t>();
entry->total_building_kills = buffer.pop<uint32_t>();
entry->total_defence_kills = buffer.pop<uint32_t>();
entry->total_captures = buffer.pop<uint32_t>();
entry->total_game_time = buffer.pop<uint32_t>();
entry->total_games = buffer.pop<uint32_t>();
entry->total_gdi_games = buffer.pop<uint32_t>();
entry->total_nod_games = buffer.pop<uint32_t>();
entry->total_wins = buffer.pop<uint32_t>();
entry->total_gdi_wins = buffer.pop<uint32_t>();
entry->total_nod_wins = buffer.pop<uint32_t>();
entry->total_beacon_placements = buffer.pop<uint32_t>();
entry->total_beacon_disarms = buffer.pop<uint32_t>();
entry->total_proxy_placements = buffer.pop<uint32_t>();
entry->total_proxy_disarms = buffer.pop<uint32_t>();
entry->top_score = buffer.pop<uint32_t>();
entry->top_kills = buffer.pop<uint32_t>();
entry->most_deaths = buffer.pop<uint32_t>();
entry->top_headshot_kills = buffer.pop<uint32_t>();
entry->top_vehicle_kills = buffer.pop<uint32_t>();
entry->top_building_kills = buffer.pop<uint32_t>();
entry->top_defence_kills = buffer.pop<uint32_t>();
entry->top_captures = buffer.pop<uint32_t>();
entry->top_game_time = buffer.pop<uint32_t>();
entry->top_beacon_placements = buffer.pop<uint32_t>();
entry->top_beacon_disarms = buffer.pop<uint32_t>();
entry->top_proxy_placements = buffer.pop<uint32_t>();
entry->top_proxy_disarms = buffer.pop<uint32_t>();
entry->most_recent_ip = buffer.pop<uint32_t>();
entry->last_game = buffer.pop<time_t>();
entry->most_recent_name = buffer.pop<Jupiter::String_Strict, char>();
// push data to list
if (RenX_LadderDatabase::head == nullptr)
{
RenX_LadderDatabase::head = entry;
RenX_LadderDatabase::end = RenX_LadderDatabase::head;
}
else
{
RenX_LadderDatabase::end->next = entry;
entry->prev = end;
end = entry;
}
++RenX_LadderDatabase::entries;
}
void RenX_LadderDatabase::process_header(FILE *file)
{
int chr = fgetc(file);
if (chr != EOF)
RenX_LadderDatabase::read_version = chr;
}
void RenX_LadderDatabase::create_header(FILE *file)
{
fputc(RenX_LadderDatabase::write_version, file);
}
RenX_LadderDatabase::Entry *RenX_LadderDatabase::getHead() const
{
return RenX_LadderDatabase::head;
}
RenX_LadderDatabase::Entry *RenX_LadderDatabase::getPlayerEntry(uint64_t steamid) const
{
for (RenX_LadderDatabase::Entry *itr = RenX_LadderDatabase::head; itr != nullptr; itr = itr->next)
if (itr->steam_id == steamid)
return itr;
return nullptr;
}
std::pair<RenX_LadderDatabase::Entry *, size_t> RenX_LadderDatabase::getPlayerEntryAndIndex(uint64_t steamid) const
{
size_t index = 0;
for (RenX_LadderDatabase::Entry *itr = RenX_LadderDatabase::head; itr != nullptr; itr = itr->next, ++index)
if (itr->steam_id == steamid)
return std::pair<RenX_LadderDatabase::Entry *, size_t>(itr, index);
return std::pair<RenX_LadderDatabase::Entry *, size_t>(nullptr, Jupiter::INVALID_INDEX);
}
RenX_LadderDatabase::Entry *RenX_LadderDatabase::getPlayerEntryByName(const Jupiter::ReadableString &name) const
{
for (RenX_LadderDatabase::Entry *itr = RenX_LadderDatabase::head; itr != nullptr; itr = itr->next)
if (itr->most_recent_name.equalsi(name))
return itr;
return nullptr;
}
std::pair<RenX_LadderDatabase::Entry *, size_t> RenX_LadderDatabase::getPlayerEntryAndIndexByName(const Jupiter::ReadableString &name) const
{
size_t index = 0;
for (RenX_LadderDatabase::Entry *itr = RenX_LadderDatabase::head; itr != nullptr; itr = itr->next, ++index)
if (itr->most_recent_name.equalsi(name))
return std::pair<RenX_LadderDatabase::Entry *, size_t>(itr, index);
return std::pair<RenX_LadderDatabase::Entry *, size_t>(nullptr, Jupiter::INVALID_INDEX);
}
RenX_LadderDatabase::Entry *RenX_LadderDatabase::getPlayerEntryByPartName(const Jupiter::ReadableString &name) const
{
for (RenX_LadderDatabase::Entry *itr = RenX_LadderDatabase::head; itr != nullptr; itr = itr->next)
if (itr->most_recent_name.findi(name) != Jupiter::INVALID_INDEX)
return itr;
return nullptr;
}
std::pair<RenX_LadderDatabase::Entry *, size_t> RenX_LadderDatabase::getPlayerEntryAndIndexByPartName(const Jupiter::ReadableString &name) const
{
size_t index = 0;
for (RenX_LadderDatabase::Entry *itr = RenX_LadderDatabase::head; itr != nullptr; itr = itr->next, ++index)
if (itr->most_recent_name.findi(name) != Jupiter::INVALID_INDEX)
return std::pair<RenX_LadderDatabase::Entry *, size_t>(itr, index);
return std::pair<RenX_LadderDatabase::Entry *, size_t>(nullptr, Jupiter::INVALID_INDEX);
}
Jupiter::SLList<RenX_LadderDatabase::Entry> RenX_LadderDatabase::getPlayerEntriesByPartName(const Jupiter::ReadableString &name, size_t max) const
{
Jupiter::SLList<RenX_LadderDatabase::Entry> list;
if (max == 0)
{
for (RenX_LadderDatabase::Entry *itr = RenX_LadderDatabase::head; itr != nullptr; itr = itr->next)
if (itr->most_recent_name.findi(name) != Jupiter::INVALID_INDEX)
list.add(new RenX_LadderDatabase::Entry(*itr));
}
else
for (RenX_LadderDatabase::Entry *itr = RenX_LadderDatabase::head; itr != nullptr; itr = itr->next)
if (itr->most_recent_name.findi(name) != Jupiter::INVALID_INDEX)
{
list.add(new RenX_LadderDatabase::Entry(*itr));
if (--max == 0)
return list;
}
return list;
}
Jupiter::SLList<std::pair<RenX_LadderDatabase::Entry, size_t>> RenX_LadderDatabase::getPlayerEntriesAndIndexByPartName(const Jupiter::ReadableString &name, size_t max) const
{
Jupiter::SLList<std::pair<RenX_LadderDatabase::Entry, size_t>> list;
size_t index = 0;
if (max == 0)
{
for (RenX_LadderDatabase::Entry *itr = RenX_LadderDatabase::head; itr != nullptr; itr = itr->next, ++index)
if (itr->most_recent_name.findi(name) != Jupiter::INVALID_INDEX)
list.add(new std::pair<RenX_LadderDatabase::Entry, size_t>(*itr, index));
}
else
for (RenX_LadderDatabase::Entry *itr = RenX_LadderDatabase::head; itr != nullptr; itr = itr->next, ++index)
if (itr->most_recent_name.findi(name) != Jupiter::INVALID_INDEX)
{
list.add(new std::pair<RenX_LadderDatabase::Entry, size_t>(*itr, index));
if (--max)
return list;
}
return list;
}
RenX_LadderDatabase::Entry *RenX_LadderDatabase::getPlayerEntryByIndex(size_t index) const
{
for (RenX_LadderDatabase::Entry *itr = RenX_LadderDatabase::head; itr != nullptr; itr = itr->next, --index)
if (index == 0)
return itr;
return nullptr;
}
size_t RenX_LadderDatabase::getEntries() const
{
return RenX_LadderDatabase::entries;
}
void RenX_LadderDatabase::append(RenX_LadderDatabase::Entry *entry)
{
++RenX_LadderDatabase::entries;
if (RenX_LadderDatabase::head == nullptr)
{
RenX_LadderDatabase::head = entry;
RenX_LadderDatabase::end = RenX_LadderDatabase::head;
return;
}
end->next = entry;
entry->prev = end;
end = entry;
}
void RenX_LadderDatabase::write(const Jupiter::CStringType &filename)
{
return RenX_LadderDatabase::write(filename.c_str());
}
void RenX_LadderDatabase::write(const char *filename)
{
if (RenX_LadderDatabase::entries != 0)
{
FILE *file = fopen(filename, "wb");
if (file != nullptr)
{
Jupiter::DataBuffer buffer;
RenX_LadderDatabase::create_header(file);
RenX_LadderDatabase::Entry *entry = RenX_LadderDatabase::head;
while (entry != nullptr)
{
// push data from entry to buffer
buffer.push(entry->steam_id);
buffer.push(entry->total_score);
buffer.push(entry->total_kills);
buffer.push(entry->total_deaths);
buffer.push(entry->total_headshot_kills);
buffer.push(entry->total_vehicle_kills);
buffer.push(entry->total_building_kills);
buffer.push(entry->total_defence_kills);
buffer.push(entry->total_captures);
buffer.push(entry->total_game_time);
buffer.push(entry->total_games);
buffer.push(entry->total_gdi_games);
buffer.push(entry->total_nod_games);
buffer.push(entry->total_wins);
buffer.push(entry->total_gdi_wins);
buffer.push(entry->total_nod_wins);
buffer.push(entry->total_beacon_placements);
buffer.push(entry->total_beacon_disarms);
buffer.push(entry->total_proxy_placements);
buffer.push(entry->total_proxy_disarms);
buffer.push(entry->top_score);
buffer.push(entry->top_kills);
buffer.push(entry->most_deaths);
buffer.push(entry->top_headshot_kills);
buffer.push(entry->top_vehicle_kills);
buffer.push(entry->top_building_kills);
buffer.push(entry->top_defence_kills);
buffer.push(entry->top_captures);
buffer.push(entry->top_game_time);
buffer.push(entry->top_beacon_placements);
buffer.push(entry->top_beacon_disarms);
buffer.push(entry->top_proxy_placements);
buffer.push(entry->top_proxy_disarms);
buffer.push(entry->most_recent_ip);
buffer.push(entry->last_game);
buffer.push(entry->most_recent_name);
// push buffer to file
buffer.push_to(file);
// iterate
entry = entry->next;
}
fclose(file);
}
}
}
void RenX_LadderDatabase::sort_entries()
{
if (RenX_LadderDatabase::entries <= 1)
return;
RenX_LadderDatabase::Entry *itr = RenX_LadderDatabase::head;
RenX_LadderDatabase::Entry *itr2, *ptr;
// iterate forward (search for out-of-order content)
while (itr->next != nullptr)
{
// out-of-order content found
if (itr->next->total_score > itr->total_score)
{
// pull content out
ptr = itr->next;
itr->next = ptr->next;
if (itr->next != nullptr)
itr->next->prev = itr;
// iterate backwards from our iterator, and insert
itr2 = itr;
while (true)
{
if (itr2->prev == nullptr)
{
// push ptr to head
ptr->next = itr2;
ptr->prev = nullptr;
itr2->prev = ptr;
RenX_LadderDatabase::head = ptr;
break;
}
itr2 = itr2->prev;
if (itr2->total_score > ptr->total_score)
{
// insert ptr after itr2
ptr->next = itr2->next;
ptr->next->prev = ptr;
ptr->prev = itr2;
itr2->next = ptr;
break;
}
}
}
else // continue iterating
itr = itr->next;
}
RenX_LadderDatabase::end = itr;
}

158
RenX.Ladder/RenX_LadderDatabase.h

@ -1,158 +0,0 @@
/**
* Copyright (C) 2015 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 <jessica.aj@outlook.com>
*/
#if !defined _RENX_LADDERDATABASE_H_HEADER
#define _RENX_LADDERDATABASE_H_HEADER
#include "Jupiter/Database.h"
#include "Jupiter/String.h"
#include "Jupiter/SLList.h"
class RenX_LadderDatabase : public Jupiter::Database
{
public: // Jupiter::Database
/**
* @brief Processes a chunk of data in a database.
*
* @param buffer Buffer to process
* @param file File being processed
* @param pos position that the buffer starts at in the file
*/
void process_data(Jupiter::DataBuffer &buffer, FILE *file, fpos_t pos) override;
/**
* @brief Processes the header for a database.
*
* @param file File being processed
*/
void process_header(FILE *file) override;
/**
* @brief Generates a header for a database.
*
* @param file File being created
*/
void create_header(FILE *file) override;
public: // RenX_LadderDatabase
struct Entry
{
uint64_t steam_id, total_score;
uint32_t total_kills, total_deaths, total_headshot_kills, total_vehicle_kills, total_building_kills, total_defence_kills, total_captures, total_game_time, total_games, total_gdi_games, total_nod_games, total_wins, total_gdi_wins, total_nod_wins, total_beacon_placements, total_beacon_disarms, total_proxy_placements, total_proxy_disarms, // totals (15)
top_score, top_kills, most_deaths, top_headshot_kills, top_vehicle_kills, top_building_kills, top_defence_kills, top_captures, top_game_time, top_beacon_placements, top_beacon_disarms, top_proxy_placements, top_proxy_disarms, // tops (12)
most_recent_ip; // other (1)
time_t last_game;
Jupiter::StringS most_recent_name;
Entry *next = nullptr;
Entry *prev = nullptr;
};
/**
* @brief Fetches the head of the entry list.
*
* @return Head of the ladder entry list.
*/
Entry *getHead() const;
/**
* @brief Fetches a ladder entry by Steam ID.
*
* @param steamid Steam ID to search ladder for
* @return Ladder entry with a matching steamid if one exists, nullptr otherwise.
*/
Entry *getPlayerEntry(uint64_t steamid) const;
std::pair<Entry *, size_t> getPlayerEntryAndIndex(uint64_t steamid) const;
/**
* @brief Searches for a ladder entry by name
*
* @param name Name to search ladder for
* @return Ladder entry with a matching name if one exists, nullptr otherwise.
*/
Entry *getPlayerEntryByName(const Jupiter::ReadableString &name) const;
std::pair<Entry *, size_t> getPlayerEntryAndIndexByName(const Jupiter::ReadableString &name) const;
/**
* @brief Searches for a ladder entry by part name
*
* @param name Part of name to search ladder for
* @return Ladder entry with a matching name if one exists, nullptr otherwise.
*/
Entry *getPlayerEntryByPartName(const Jupiter::ReadableString &name) const;
std::pair<Entry *, size_t> getPlayerEntryAndIndexByPartName(const Jupiter::ReadableString &name) const;
/**
* @brief Fetches all entries matching a part name.
*
* @param name Part of name to search for
* @param max Maximum number of entries to return
* @return List containing entries with matching names.
*/
Jupiter::SLList<Entry> getPlayerEntriesByPartName(const Jupiter::ReadableString &name, size_t max) const;
Jupiter::SLList<std::pair<Entry, size_t>> getPlayerEntriesAndIndexByPartName(const Jupiter::ReadableString &name, size_t max) const;
/**
* @brief Fetches a ladder entry at a specified index
*
* @param index Index of the element to fetch
* @return Ladder entry with a matching name if one exists, nullptr otherwise.
*/
Entry *getPlayerEntryByIndex(size_t index) const;
/**
* @brief Fetches the total number of ladder entries in the list.
*
* @return Total number of entries.
*/
size_t getEntries() const;
/**
* @brief Places a ladder entry at the end of the list, regardless of order
* Note: This does not copy data from the pointer -- the pointer is added to the list.
*
* @param entry Ladder entry to add
*/
void append(Entry *entry);
/**
* @brief Writes the current ladder data to the disk.
*/
void write(const Jupiter::CStringType &filename);
void write(const char *filename);
/**
* @brief Sorts the ladder data in memory.
*/
void sort_entries();
/**
* @brief Deconstructor for the RenX_LadderDatabase class
*/
~RenX_LadderDatabase();
private:
/** Database version */
const uint8_t write_version = 0;
uint8_t read_version = write_version;
size_t entries = 0;
Entry *head = nullptr;
Entry *end;
};
#endif //_RENX_LADDERDATABASE_H_HEADER

4
RenX.Listen/RenX_Listen.cpp

@ -25,7 +25,7 @@
RenX_ListenPlugin::~RenX_ListenPlugin()
{
RenX_ListenPlugin::socket.closeSocket();
RenX_ListenPlugin::socket.close();
}
bool RenX_ListenPlugin::init()
@ -59,7 +59,7 @@ int RenX_ListenPlugin::OnRehash()
if (port != RenX_ListenPlugin::socket.getRemotePort() || address.equals(RenX_ListenPlugin::socket.getRemoteHostname()) == false)
{
puts("Notice: The Renegade-X listening socket has been changed!");
RenX_ListenPlugin::socket.closeSocket();
RenX_ListenPlugin::socket.close();
return RenX_ListenPlugin::socket.bind(Jupiter::CStringS(address).c_str(), port, true) == false || RenX_ListenPlugin::socket.setBlocking(false) == false;
}
return 0;

Loading…
Cancel
Save