From 451db1d986db98d22bffacf6e330f323df1fad34 Mon Sep 17 00:00:00 2001 From: RektInator Date: Sun, 26 Feb 2017 01:36:37 +0100 Subject: [PATCH] [Stats] Playerstats reuploading initial commit --- src/Components/Loader.cpp | 1 + src/Components/Loader.hpp | 1 + src/Components/Modules/Stats.cpp | 80 ++++++++++++++++++++++++++++++++ src/Components/Modules/Stats.hpp | 20 ++++++++ src/Game/Functions.cpp | 2 + src/Game/Functions.hpp | 6 +++ 6 files changed, 110 insertions(+) create mode 100644 src/Components/Modules/Stats.cpp create mode 100644 src/Components/Modules/Stats.hpp diff --git a/src/Components/Loader.cpp b/src/Components/Loader.cpp index 1c668411..7a5025a1 100644 --- a/src/Components/Loader.cpp +++ b/src/Components/Loader.cpp @@ -38,6 +38,7 @@ namespace Components Loader::Register(new News()); Loader::Register(new Node()); Loader::Register(new RCon()); + Loader::Register(new Stats()); Loader::Register(new Menus()); Loader::Register(new Toast()); Loader::Register(new Party()); diff --git a/src/Components/Loader.hpp b/src/Components/Loader.hpp index a66eb98e..2db71e02 100644 --- a/src/Components/Loader.hpp +++ b/src/Components/Loader.hpp @@ -106,3 +106,4 @@ namespace Components #include "Modules/StructuredData.hpp" #include "Modules/ConnectProtocol.hpp" #include "Modules/StartupMessages.hpp" +#include "Modules/Stats.hpp" diff --git a/src/Components/Modules/Stats.cpp b/src/Components/Modules/Stats.cpp new file mode 100644 index 00000000..6ba823d4 --- /dev/null +++ b/src/Components/Modules/Stats.cpp @@ -0,0 +1,80 @@ +#include "STDInclude.hpp" + +namespace Components +{ + void Stats::SendStats() + { + // check if we're connected to a server... + if (*reinterpret_cast(0xB2C540) >= 7) + { + for (int i = 0; i < 7; i++) + { + Game::Com_Printf(0, "Sending stat packet %i to server.\n", i); + + // alloc + Game::msg_t msg; + memset(&msg, 0, sizeof(Game::msg_t)); + + char* buffer = new char[2048]; + memset(buffer, 0, 2048); + + // init + Game::MSG_Init(&msg, buffer, 2048); + Game::MSG_WriteString(&msg, "stats"); + + // get stat buffer + char *statbuffer = nullptr; + if (Utils::Hook::Call(0x444CA0)(0)) + { + statbuffer = &Utils::Hook::Call(0x4C49F0)(0)[1240 * i]; + } + + // Client port? + Game::MSG_WriteShort(&msg, *(short*)0xA1E878); + + // Stat packet index + Game::MSG_WriteByte(&msg, i); + + // calculate packet size + size_t size = 8192 - (i * 1240); + if (size > 1240) + size = 1240; + + // write stat packet data + if (statbuffer) + { + Game::MSG_WriteData(&msg, statbuffer, size); + } + + // send statpacket + Game::NET_OutOfBandData(Game::NS_CLIENT, *(Game::netadr_t*)0xA1E888, msg.data, msg.cursize); + + // free memory + delete[] buffer; + } + } + } + + void Stats::UpdateClasses(UIScript::Token token) + { + SendStats(); + } + + Stats::Stats() + { + // This UIScript should be added in the onClose code of the cac_popup menu, + // so everytime the create-a-class window is closed, and a client is connected + // to a server, the stats data of the client will be reuploaded to the server. + // allowing the player to change their classes while connected to a server. + UIScript::Add("UpdateClasses", Stats::UpdateClasses); + + // Allow playerdata to be changed while connected to a server + Utils::Hook::Set(0x4376FD, 0xEB); + + // ToDo: Allow playerdata changes in setPlayerData UI script. + } + Stats::~Stats() + { + + } +} diff --git a/src/Components/Modules/Stats.hpp b/src/Components/Modules/Stats.hpp new file mode 100644 index 00000000..ba3f133d --- /dev/null +++ b/src/Components/Modules/Stats.hpp @@ -0,0 +1,20 @@ +#pragma once + +namespace Components +{ + class Stats : public Component + { + public: + Stats(); + ~Stats(); + +#if defined(DEBUG) || defined(FORCE_UNIT_TESTS) + const char* getName() override { return "Stats"; }; +#endif + + private: + static void UpdateClasses(UIScript::Token token); + static void SendStats(); + + }; +} diff --git a/src/Game/Functions.cpp b/src/Game/Functions.cpp index cf10cbd2..8279cf14 100644 --- a/src/Game/Functions.cpp +++ b/src/Game/Functions.cpp @@ -151,6 +151,8 @@ namespace Game MSG_WriteByte_t MSG_WriteByte = MSG_WriteByte_t(0x48C520); MSG_WriteData_t MSG_WriteData = MSG_WriteData_t(0x4F4120); MSG_WriteLong_t MSG_WriteLong = MSG_WriteLong_t(0x41CA20); + MSG_WriteShort_t MSG_WriteShort = MSG_WriteShort_t(0x503B90); + MSG_WriteString_t MSG_WriteString = MSG_WriteString_t(0x463820); MSG_WriteBitsCompress_t MSG_WriteBitsCompress = MSG_WriteBitsCompress_t(0x4319D0); MSG_ReadByte_t MSG_ReadByte = MSG_ReadByte_t(0x4C1C20); MSG_ReadBitsCompress_t MSG_ReadBitsCompress = MSG_ReadBitsCompress_t(0x4DCC30); diff --git a/src/Game/Functions.hpp b/src/Game/Functions.hpp index dd8783fc..58171166 100644 --- a/src/Game/Functions.hpp +++ b/src/Game/Functions.hpp @@ -394,6 +394,12 @@ namespace Game typedef void(__cdecl * MSG_WriteLong_t)(msg_t *msg, int c); extern MSG_WriteLong_t MSG_WriteLong; + typedef void(*MSG_WriteShort_t)(msg_t* msg, short s); + extern MSG_WriteShort_t MSG_WriteShort; + + typedef void(*MSG_WriteString_t)(msg_t* msg, const char *str); + extern MSG_WriteString_t MSG_WriteString; + typedef int(__cdecl * MSG_WriteBitsCompress_t)(bool trainHuffman, const char *from, char *to, int size); extern MSG_WriteBitsCompress_t MSG_WriteBitsCompress;