JustinAJ
9 years ago
6 changed files with 973 additions and 0 deletions
@ -0,0 +1,87 @@ |
|||||
|
<?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>{B2846BD6-2332-4DA6-A13B-113318F76D5E}</ProjectGuid> |
||||
|
<RootNamespace>RenX.Ladder</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</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_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" /> |
||||
|
<Library Include="..\Release\Bot.lib" /> |
||||
|
<Library Include="..\Release\Plugins\RenX.Core.lib" /> |
||||
|
</ItemGroup> |
||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> |
||||
|
<ImportGroup Label="ExtensionTargets"> |
||||
|
</ImportGroup> |
||||
|
</Project> |
@ -0,0 +1,44 @@ |
|||||
|
<?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\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> |
||||
|
</ItemGroup> |
||||
|
<ItemGroup> |
||||
|
<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> |
@ -0,0 +1,287 @@ |
|||||
|
/**
|
||||
|
* Copyright (C) 2015 Justin James. |
||||
|
* |
||||
|
* This license must be preserved. |
||||
|
* Any applications, libraries, or code which make any use of any |
||||
|
* component of this program must not be commercial, unless explicit |
||||
|
* permission is granted from the original author. The use of this |
||||
|
* program for non-profit purposes is permitted. |
||||
|
* |
||||
|
* This program is distributed in the hope that it will be useful, |
||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
||||
|
* |
||||
|
* In the event that this license restricts you from making desired use of this program, contact the original author. |
||||
|
* Written by Justin James <justin.aj@hotmail.com> |
||||
|
*/ |
||||
|
|
||||
|
#include "Console_Command.h" |
||||
|
#include "Jupiter/INIFile.h" |
||||
|
#include "RenX_Ladder.h" |
||||
|
#include "RenX_Server.h" |
||||
|
#include "RenX_PlayerInfo.h" |
||||
|
|
||||
|
using namespace Jupiter::literals; |
||||
|
|
||||
|
RenX_LadderPlugin::RenX_LadderPlugin() |
||||
|
{ |
||||
|
RenX_LadderPlugin::only_pure = Jupiter::IRC::Client::Config->getBool(this->getName(), "OnlyPure"_jrs, false); |
||||
|
RenX_LadderPlugin::output_times = Jupiter::IRC::Client::Config->getBool(this->getName(), "OutputTimes"_jrs, true); |
||||
|
int mlcpno = Jupiter::IRC::Client::Config->getInt(this->getName(), "MaxLadderCommandPartNameOutput"_jrs, 5); |
||||
|
if (mlcpno < 0) |
||||
|
RenX_LadderPlugin::max_ladder_command_part_name_output = 0; |
||||
|
else |
||||
|
RenX_LadderPlugin::max_ladder_command_part_name_output = mlcpno; |
||||
|
RenX_LadderPlugin::db_filename = Jupiter::IRC::Client::Config->get(this->getName(), "LadderDatabase"_jrs, "Ladder.db"_jrs); |
||||
|
|
||||
|
// load database
|
||||
|
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) |
||||
|
{ |
||||
|
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) |
||||
|
{ |
||||
|
if (server->hasSeenStart() && server->players.size() != 0) // the first game doesn't count!
|
||||
|
{ |
||||
|
char chr = static_cast<char>(team); |
||||
|
server->varData.set(this->name, "t"_jrs, Jupiter::ReferenceString(chr)); |
||||
|
server->varData.set(this->name, "w"_jrs, "1"_jrs); |
||||
|
server->updateClientList(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void RenX_LadderPlugin::RenX_OnCommand(RenX::Server *server, const Jupiter::ReadableString &) |
||||
|
{ |
||||
|
if (server->getCurrentRCONCommand().equalsi("clientvarlist"_jrs)) |
||||
|
{ |
||||
|
if (server->varData.get(this->name, "w"_jrs, "0"_jrs).equals("1")) |
||||
|
{ |
||||
|
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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
size_t RenX_LadderPlugin::getMaxLadderCommandPartNameOutput() const |
||||
|
{ |
||||
|
return RenX_LadderPlugin::max_ladder_command_part_name_output; |
||||
|
} |
||||
|
|
||||
|
// Plugin instantiation and entry point.
|
||||
|
RenX_LadderPlugin pluginInstance; |
||||
|
|
||||
|
/** Ladder Commands */ |
||||
|
#include <cinttypes> |
||||
|
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); |
||||
|
} |
||||
|
|
||||
|
// Ladder Command
|
||||
|
|
||||
|
LadderGenericCommand::LadderGenericCommand() |
||||
|
{ |
||||
|
this->addTrigger("ladder"_jrs); |
||||
|
this->addTrigger("rank"_jrs); |
||||
|
} |
||||
|
|
||||
|
GenericCommand::ResponseLine *LadderGenericCommand::trigger(const Jupiter::ReadableString ¶meters) |
||||
|
{ |
||||
|
if (parameters.isEmpty()) |
||||
|
return new GenericCommand::ResponseLine("Error: Too few parameters. Syntax: ladder <name | rank>"_jrs, GenericCommand::DisplayType::PrivateError); |
||||
|
|
||||
|
RenX_LadderDatabase::Entry *entry; |
||||
|
size_t rank; |
||||
|
if (parameters.span("0123456789"_jrs) == parameters.size()) |
||||
|
{ |
||||
|
rank = parameters.asUnsignedInt(10); |
||||
|
if (rank == 0) |
||||
|
return new GenericCommand::ResponseLine("Error: Invalid parameters"_jrs, GenericCommand::DisplayType::PrivateError); |
||||
|
|
||||
|
entry = pluginInstance.database.getPlayerEntryByIndex(rank - 1); |
||||
|
if (entry == nullptr) |
||||
|
return new GenericCommand::ResponseLine("Error: Player not found"_jrs, GenericCommand::DisplayType::PrivateError); |
||||
|
|
||||
|
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()); |
||||
|
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); |
||||
|
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; |
||||
|
while (list.size() != 0) |
||||
|
{ |
||||
|
pair = list.remove(0); |
||||
|
response_end->next = new GenericCommand::ResponseLine(FormatLadderResponse(std::addressof(pair->first), pair->second + 1), GenericCommand::DisplayType::PrivateSuccess); |
||||
|
response_end = response_end->next; |
||||
|
delete pair; |
||||
|
} |
||||
|
return response_head; |
||||
|
} |
||||
|
|
||||
|
const Jupiter::ReadableString &LadderGenericCommand::getHelp(const Jupiter::ReadableString &) |
||||
|
{ |
||||
|
static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Fetches ladder information about a player. Syntax: ladder <name | rank>"); |
||||
|
return defaultHelp; |
||||
|
} |
||||
|
|
||||
|
GENERIC_COMMAND_INIT(LadderGenericCommand) |
||||
|
GENERIC_COMMAND_AS_CONSOLE_COMMAND(LadderGenericCommand) |
||||
|
GENERIC_COMMAND_AS_IRC_COMMAND_NO_CREATE(LadderGenericCommand) |
||||
|
|
||||
|
// Ladder Game Command
|
||||
|
|
||||
|
void LadderGameCommand::create() |
||||
|
{ |
||||
|
this->addTrigger("ladder"_jrs); |
||||
|
this->addTrigger("rank"_jrs); |
||||
|
} |
||||
|
|
||||
|
void LadderGameCommand::trigger(RenX::Server *source, RenX::PlayerInfo *player, const Jupiter::ReadableString ¶meters) |
||||
|
{ |
||||
|
if (parameters.isEmpty()) |
||||
|
{ |
||||
|
if (player->steamid != 0) |
||||
|
{ |
||||
|
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 |
||||
|
source->sendMessage(player, "Error: You have no ladder data. Get started by sticking around until the end of the match!"_jrs); |
||||
|
} |
||||
|
else |
||||
|
source->sendMessage(player, "Error: You have no ladder data, because you're not using Steam."_jrs); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
GenericCommand::ResponseLine *response = LadderGenericCommand_instance.trigger(parameters); |
||||
|
GenericCommand::ResponseLine *ptr; |
||||
|
while (response != nullptr) |
||||
|
{ |
||||
|
source->sendMessage(player, response->response); |
||||
|
ptr = response; |
||||
|
response = response->next; |
||||
|
delete ptr; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
const Jupiter::ReadableString &LadderGameCommand::getHelp(const Jupiter::ReadableString &) |
||||
|
{ |
||||
|
static STRING_LITERAL_AS_NAMED_REFERENCE(defaultHelp, "Displays ladder information about yourself, or another player. Syntax: ladder [name / rank]"); |
||||
|
return defaultHelp; |
||||
|
} |
||||
|
|
||||
|
GAME_COMMAND_INIT(LadderGameCommand) |
||||
|
|
||||
|
extern "C" __declspec(dllexport) Jupiter::Plugin *getPlugin() |
||||
|
{ |
||||
|
return &pluginInstance; |
||||
|
} |
@ -0,0 +1,52 @@ |
|||||
|
/**
|
||||
|
* Copyright (C) 2015 Justin James. |
||||
|
* |
||||
|
* This license must be preserved. |
||||
|
* Any applications, libraries, or code which make any use of any |
||||
|
* component of this program must not be commercial, unless explicit |
||||
|
* permission is granted from the original author. The use of this |
||||
|
* program for non-profit purposes is permitted. |
||||
|
* |
||||
|
* This program is distributed in the hope that it will be useful, |
||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
||||
|
* |
||||
|
* In the event that this license restricts you from making desired use of this program, contact the original author. |
||||
|
* Written by Justin James <justin.aj@hotmail.com> |
||||
|
*/ |
||||
|
|
||||
|
#if !defined _RENX_LADDER_H_HEADER |
||||
|
#define _RENX_LADDER_H_HEADER |
||||
|
|
||||
|
#include "Jupiter/Plugin.h" |
||||
|
#include "Jupiter/Reference_String.h" |
||||
|
#include "IRC_Command.h" |
||||
|
#include "RenX_Plugin.h" |
||||
|
#include "RenX_LadderDatabase.h" |
||||
|
#include "RenX_GameCommand.h" |
||||
|
|
||||
|
class RenX_LadderPlugin : public RenX::Plugin |
||||
|
{ |
||||
|
public: |
||||
|
const Jupiter::ReadableString &getName() override { return name; } |
||||
|
void RenX_OnGameOver(RenX::Server *server, RenX::WinType winType, const RenX::TeamType &team, int gScore, int nScore) override; |
||||
|
void RenX_OnCommand(RenX::Server *server, const Jupiter::ReadableString &) override; |
||||
|
|
||||
|
size_t getMaxLadderCommandPartNameOutput() const; |
||||
|
RenX_LadderPlugin(); |
||||
|
|
||||
|
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; |
||||
|
Jupiter::CStringS db_filename; |
||||
|
STRING_LITERAL_AS_NAMED_REFERENCE(name, "RenX.Ladder"); |
||||
|
}; |
||||
|
|
||||
|
GENERIC_GENERIC_COMMAND(LadderGenericCommand) |
||||
|
GENERIC_GAME_COMMAND(LadderGameCommand) |
||||
|
|
||||
|
#endif // _RENX_LADDER_H_HEADER
|
@ -0,0 +1,346 @@ |
|||||
|
/**
|
||||
|
* Copyright (C) 2015 Justin James. |
||||
|
* |
||||
|
* This license must be preserved. |
||||
|
* Any applications, libraries, or code which make any use of any |
||||
|
* component of this program must not be commercial, unless explicit |
||||
|
* permission is granted from the original author. The use of this |
||||
|
* program for non-profit purposes is permitted. |
||||
|
* |
||||
|
* This program is distributed in the hope that it will be useful, |
||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
||||
|
* |
||||
|
* In the event that this license restricts you from making desired use of this program, contact the original author. |
||||
|
* Written by Justin James <justin.aj@hotmail.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; |
||||
|
} |
@ -0,0 +1,157 @@ |
|||||
|
/**
|
||||
|
* Copyright (C) 2015 Justin James. |
||||
|
* |
||||
|
* This license must be preserved. |
||||
|
* Any applications, libraries, or code which make any use of any |
||||
|
* component of this program must not be commercial, unless explicit |
||||
|
* permission is granted from the original author. The use of this |
||||
|
* program for non-profit purposes is permitted. |
||||
|
* |
||||
|
* This program is distributed in the hope that it will be useful, |
||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
||||
|
* |
||||
|
* In the event that this license restricts you from making desired use of this program, contact the original author. |
||||
|
* Written by Justin James <justin.aj@hotmail.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
|
Loading…
Reference in new issue