First work-in-progress dedicated implementation

Based on MrSteyk's dedicated patch.
Additional patches targets the disabling of the client.dll library and VGUI. The disabling of the client.dll library initialization caused several issues to be investigated still (currently loops fine in _Host_RunFrame()). but executing a map command currently makes it only load the mp_common VPK before getting stuck somewhere. Setting hoststate to a valid map with HS_NEW_GAME (manually) does something to the engine but does not force the server to load anything yet.

Added enums and classes from r5dev project.
This commit is contained in:
Amos 2021-09-12 16:41:30 -07:00
parent fad7906fd8
commit b42e85b1f4
15 changed files with 1700 additions and 57 deletions

View File

@ -1,5 +1,6 @@
#include "pch.h"
#include "hooks.h"
#include "opcodes.h"
#include "console.h"
//#############################################################################
@ -80,6 +81,7 @@ DWORD __stdcall ProcessConsoleWorker(LPVOID)
// Exec toggles
if (sCommand == "1") { addr_CommandExecute(NULL, "exec autoexec_dev"); }
if (sCommand == "2") { g_bDebugLoading = !g_bDebugLoading; continue; }
if (sCommand == "3") { SetCHostState(); continue; } // TEST
///////////////////////////////////////////////////////////////////////
// Execute the command in the r5 SQVM

View File

@ -0,0 +1,36 @@
#include "pch.h"
#include "hooks.h"
namespace Hooks
{
CSourceAppSystemGroup_CreateFn originalCSourceAppSystemGroup_Create = nullptr;
}
auto g_bIsDedicated = (uint8_t*)0x162C61208;
//-----------------------------------------------------------------------------
// Purpose: sets 'EbisuSDK' globals required in certain engine callbacks.
//-----------------------------------------------------------------------------
void HEbisuSDK_Init()
{
auto ofs000 = (uint8_t*)0x1634F1690;
auto ofs001 = (uint8_t*)0x1634F16B0;
auto ofs002 = (uint8_t*)0x1634F1695;
auto ofs003 = (uint8_t*)0x1634F30D8;
auto ofs004 = (uint8_t*)0x1634F31D8;
*(char*)(ofs000) = (char)0x1; // <-- | 1st EbisuSDK boolean to be checked.
*(char*)(ofs001) = (char)0x1; // <-- | 2nd EbisuSDK boolean to be checked.
*(char*)(ofs002) = (char)0x1; // <-- | 3rd EbisuSDK boolean to be checked.
*(char*)(ofs003) = (char)0x1; // <-- | Gets tested on listenserver for certain ConCommands.
*(char*)(ofs004) = (char)0x0; // <-- | TODO: enforces Necleus cvars when not equal to NULL.
}
//-----------------------------------------------------------------------------
// Purpose: hook 'SourceAppSystemGroup::Create' and set m_bIsDedicated to true.
//-----------------------------------------------------------------------------
char __fastcall Hooks::CSourceAppSystemGroup_Create(__int64 a1)
{
*g_bIsDedicated = 1; // HAS TO BE HERE!!!
HEbisuSDK_Init();
return originalCSourceAppSystemGroup_Create(a1);
}

View File

@ -11,6 +11,7 @@ void InitializeR5Dedicated()
{
SetupConsole();
Hooks::InstallHooks();
Hooks::DedicatedPatch();
printf("+-----------------------------------------------------------------------------+\n");
printf("| R5 DEDICATED SERVER --------------------------------------------------- |\n");
printf("+-----------------------------------------------------------------------------+\n");

422
r5dedicated/enums.h Normal file
View File

@ -0,0 +1,422 @@
#pragma once
/* Enumerations */
enum class D3D11DeviceVTbl : short
{
// IUnknown
QueryInterface = 0,
AddRef = 1,
Release = 2,
// ID3D11Device
CreateBuffer = 3,
CreateTexture1D = 4,
CreateTexture2D = 5,
CreateTexture3D = 6,
CreateShaderResourceView = 7,
CreateUnorderedAccessView = 8,
CreateRenderTargetView = 9,
CreateDepthStencilView = 10,
CreateInputLayout = 11,
CreateVertexShader = 12,
CreateGeometryShader = 13,
CreateGeometryShaderWithStreamOutput = 14,
CreatePixelShader = 15,
CreateHullShader = 16,
CreateDomainShader = 17,
CreateComputeShader = 18,
CreateClassLinkage = 19,
CreateBlendState = 20,
CreateDepthStencilState = 21,
CreateRasterizerState = 22,
CreateSamplerState = 23,
CreateQuery = 24,
CreatePredicate = 25,
CreateCounter = 26,
CreateDeferredContext = 27,
OpenSharedResource = 28,
CheckFormatSupport = 29,
CheckMultisampleQualityLevels = 30,
CheckCounterInfo = 31,
CheckCounter = 32,
CheckFeatureSupport = 33,
GetPrivateData = 34,
SetPrivateData = 35,
SetPrivateDataInterface = 36,
GetFeatureLevel = 37,
GetCreationFlags = 38,
GetDeviceRemovedReason = 39,
GetImmediateContext = 40,
SetExceptionMode = 41,
GetExceptionMode = 42,
};
enum class DXGISwapChainVTbl : short
{
// IUnknown
QueryInterface = 0,
AddRef = 1,
Release = 2,
// IDXGIObject
SetPrivateData = 3,
SetPrivateDataInterface = 4,
GetPrivateData = 5,
GetParent = 6,
// IDXGIDeviceSubObject
GetDevice = 7,
// IDXGISwapChain
Present = 8,
GetBuffer = 9,
SetFullscreenState = 10,
GetFullscreenState = 11,
GetDesc = 12,
ResizeBuffers = 13,
ResizeTarget = 14,
GetContainingOutput = 15,
GetFrameStatistics = 16,
GetLastPresentCount = 17,
};
#define MAX_SPLITSCREEN_CLIENT_BITS 2
#define MAX_SPLITSCREEN_CLIENTS ( 1 << MAX_SPLITSCREEN_CLIENT_BITS ) // 4
enum
{
MAX_JOYSTICKS = MAX_SPLITSCREEN_CLIENTS,
MOUSE_BUTTON_COUNT = 5,
};
enum JoystickAxis_t
{
JOY_AXIS_X = 0,
JOY_AXIS_Y,
JOY_AXIS_Z,
JOY_AXIS_R,
JOY_AXIS_U,
JOY_AXIS_V,
MAX_JOYSTICK_AXES,
};
enum
{
JOYSTICK_MAX_BUTTON_COUNT = 32,
JOYSTICK_POV_BUTTON_COUNT = 4,
JOYSTICK_AXIS_BUTTON_COUNT = MAX_JOYSTICK_AXES * 2,
};
#define JOYSTICK_BUTTON_INTERNAL( _joystick, _button ) ( JOYSTICK_FIRST_BUTTON + ((_joystick) * JOYSTICK_MAX_BUTTON_COUNT) + (_button) )
#define JOYSTICK_POV_BUTTON_INTERNAL( _joystick, _button ) ( JOYSTICK_FIRST_POV_BUTTON + ((_joystick) * JOYSTICK_POV_BUTTON_COUNT) + (_button) )
#define JOYSTICK_AXIS_BUTTON_INTERNAL( _joystick, _button ) ( JOYSTICK_FIRST_AXIS_BUTTON + ((_joystick) * JOYSTICK_AXIS_BUTTON_COUNT) + (_button) )
#define JOYSTICK_BUTTON( _joystick, _button ) ( (ButtonCode_t)JOYSTICK_BUTTON_INTERNAL( _joystick, _button ) )
#define JOYSTICK_POV_BUTTON( _joystick, _button ) ( (ButtonCode_t)JOYSTICK_POV_BUTTON_INTERNAL( _joystick, _button ) )
#define JOYSTICK_AXIS_BUTTON( _joystick, _button ) ( (ButtonCode_t)JOYSTICK_AXIS_BUTTON_INTERNAL( _joystick, _button ) )
enum ButtonCode_t
{
BUTTON_CODE_INVALID = -1,
BUTTON_CODE_NONE = 0,
KEY_FIRST = 0,
KEY_NONE = KEY_FIRST,
KEY_0,
KEY_1,
KEY_2,
KEY_3,
KEY_4,
KEY_5,
KEY_6,
KEY_7,
KEY_8,
KEY_9,
KEY_A,
KEY_B,
KEY_C,
KEY_D,
KEY_E,
KEY_F,
KEY_G,
KEY_H,
KEY_I,
KEY_J,
KEY_K,
KEY_L,
KEY_M,
KEY_N,
KEY_O,
KEY_P,
KEY_Q,
KEY_R,
KEY_S,
KEY_T,
KEY_U,
KEY_V,
KEY_W,
KEY_X,
KEY_Y,
KEY_Z,
KEY_PAD_0,
KEY_PAD_1,
KEY_PAD_2,
KEY_PAD_3,
KEY_PAD_4,
KEY_PAD_5,
KEY_PAD_6,
KEY_PAD_7,
KEY_PAD_8,
KEY_PAD_9,
KEY_PAD_DIVIDE,
KEY_PAD_MULTIPLY,
KEY_PAD_MINUS,
KEY_PAD_PLUS,
KEY_PAD_ENTER,
KEY_PAD_DECIMAL,
KEY_LBRACKET,
KEY_RBRACKET,
KEY_SEMICOLON,
KEY_APOSTROPHE,
KEY_BACKQUOTE,
KEY_COMMA,
KEY_PERIOD,
KEY_SLASH,
KEY_BACKSLASH,
KEY_MINUS,
KEY_EQUAL,
KEY_ENTER,
KEY_SPACE,
KEY_BACKSPACE,
KEY_TAB,
KEY_CAPSLOCK,
KEY_NUMLOCK,
KEY_ESCAPE,
KEY_SCROLLLOCK,
KEY_INSERT,
KEY_DELETE,
KEY_HOME,
KEY_END,
KEY_PAGEUP,
KEY_PAGEDOWN,
KEY_BREAK,
KEY_LSHIFT,
KEY_RSHIFT,
KEY_LALT,
KEY_RALT,
KEY_LCONTROL,
KEY_RCONTROL,
KEY_LWIN,
KEY_RWIN,
KEY_APP,
KEY_UP,
KEY_LEFT,
KEY_DOWN,
KEY_RIGHT,
KEY_F1,
KEY_F2,
KEY_F3,
KEY_F4,
KEY_F5,
KEY_F6,
KEY_F7,
KEY_F8,
KEY_F9,
KEY_F10,
KEY_F11,
KEY_F12,
KEY_CAPSLOCKTOGGLE,
KEY_NUMLOCKTOGGLE,
KEY_SCROLLLOCKTOGGLE,
KEY_LAST = KEY_SCROLLLOCKTOGGLE,
KEY_COUNT = KEY_LAST - KEY_FIRST + 1,
// Mouse
MOUSE_FIRST = KEY_LAST + 1,
MOUSE_LEFT = MOUSE_FIRST,
MOUSE_RIGHT,
MOUSE_MIDDLE,
MOUSE_4,
MOUSE_5,
MOUSE_WHEEL_UP, // A fake button which is 'pressed' and 'released' when the wheel is moved up
MOUSE_WHEEL_DOWN, // A fake button which is 'pressed' and 'released' when the wheel is moved down
MOUSE_LAST = MOUSE_WHEEL_DOWN,
MOUSE_COUNT = MOUSE_LAST - MOUSE_FIRST + 1,
// Joystick
JOYSTICK_FIRST = MOUSE_LAST + 1,
JOYSTICK_FIRST_BUTTON = JOYSTICK_FIRST,
JOYSTICK_LAST_BUTTON = JOYSTICK_BUTTON_INTERNAL(MAX_JOYSTICKS - 1, JOYSTICK_MAX_BUTTON_COUNT - 1),
JOYSTICK_FIRST_POV_BUTTON,
JOYSTICK_LAST_POV_BUTTON = JOYSTICK_POV_BUTTON_INTERNAL(MAX_JOYSTICKS - 1, JOYSTICK_POV_BUTTON_COUNT - 1),
JOYSTICK_FIRST_AXIS_BUTTON,
JOYSTICK_LAST_AXIS_BUTTON = JOYSTICK_AXIS_BUTTON_INTERNAL(MAX_JOYSTICKS - 1, JOYSTICK_AXIS_BUTTON_COUNT - 1),
JOYSTICK_LAST = JOYSTICK_LAST_AXIS_BUTTON,
BUTTON_CODE_LAST,
BUTTON_CODE_COUNT = BUTTON_CODE_LAST - KEY_FIRST + 1,
// Helpers for XBox 360
KEY_XBUTTON_UP = JOYSTICK_FIRST_POV_BUTTON, // POV buttons
KEY_XBUTTON_RIGHT,
KEY_XBUTTON_DOWN,
KEY_XBUTTON_LEFT,
KEY_XBUTTON_A = JOYSTICK_FIRST_BUTTON, // Buttons
KEY_XBUTTON_B,
KEY_XBUTTON_X,
KEY_XBUTTON_Y,
KEY_XBUTTON_LEFT_SHOULDER,
KEY_XBUTTON_RIGHT_SHOULDER,
KEY_XBUTTON_BACK,
KEY_XBUTTON_START,
KEY_XBUTTON_STICK1,
KEY_XBUTTON_STICK2,
KEY_XBUTTON_INACTIVE_START,
KEY_XSTICK1_RIGHT = JOYSTICK_FIRST_AXIS_BUTTON, // XAXIS POSITIVE
KEY_XSTICK1_LEFT, // XAXIS NEGATIVE
KEY_XSTICK1_DOWN, // YAXIS POSITIVE
KEY_XSTICK1_UP, // YAXIS NEGATIVE
KEY_XBUTTON_LTRIGGER, // ZAXIS POSITIVE
KEY_XBUTTON_RTRIGGER, // ZAXIS NEGATIVE
KEY_XSTICK2_RIGHT, // UAXIS POSITIVE
KEY_XSTICK2_LEFT, // UAXIS NEGATIVE
KEY_XSTICK2_DOWN, // VAXIS POSITIVE
KEY_XSTICK2_UP, // VAXIS NEGATIVE
};
// Buttons are not confirmed to be the same. They have been always the same throughout the source engine. Lets hope they did not change them.
enum KeyValuesTypes
{
TYPE_NONE = 0x0,
TYPE_STRING = 0x1,
TYPE_INT = 0x2,
TYPE_FLOAT = 0x3,
TYPE_PTR = 0x4,
TYPE_WSTRING = 0x5,
TYPE_COLOR = 0x6,
TYPE_UINT64 = 0x7,
TYPE_COMPILED_INT_BYTE = 0x8,
TYPE_COMPILED_INT_0 = 0x9,
TYPE_COMPILED_INT_1 = 0xA,
TYPE_NUMTYPES = 0xB,
};
enum ClientFrameStage_t
{
FRAME_UNDEFINED = -1, // (haven't run any frames yet)
FRAME_START,
// A network packet is being recieved
FRAME_NET_UPDATE_START,
// Data has been received and we're going to start calling PostDataUpdate
FRAME_NET_UPDATE_POSTDATAUPDATE_START,
// Data has been received and we've called PostDataUpdate on all data recipients
FRAME_NET_UPDATE_POSTDATAUPDATE_END,
// We've received all packets, we can now do interpolation, prediction, etc..
FRAME_NET_UPDATE_END,
// We're about to start rendering the scene
FRAME_RENDER_START,
// We've finished rendering the scene.
FRAME_RENDER_END,
FRAME_NET_FULL_FRAME_UPDATE_ON_REMOVE
};
enum HostStates_t
{
HS_NEW_GAME = 0x0,
HS_LOAD_GAME = 0x1,
HS_CHANGE_LEVEL_SP = 0x2,
HS_CHANGE_LEVEL_MP = 0x3,
HS_RUN = 0x4,
HS_GAME_SHUTDOWN = 0x5,
HS_SHUTDOWN = 0x6,
HS_RESTART = 0x7,
};
enum SIGNONSTATE
{
SIGNONSTATE_NONE = 0, // no state yet; about to connect
SIGNONSTATE_CHALLENGE = 1, // client challenging server; all OOB packets
SIGNONSTATE_CONNECTED = 2, // client is connected to server; netchans ready
SIGNONSTATE_NEW = 3, // just got serverinfo and string tables
SIGNONSTATE_PRESPAWN = 4, // received signon buffers
SIGNONSTATE_GETTING_DATA = 5, // getting persistence data I assume?
SIGNONSTATE_SPAWN = 6, // ready to receive entity packets
SIGNONSTATE_FIRST_SNAP = 7, // ???
SIGNONSTATE_FULL = 8, // we are fully connected; first non-delta packet received
SIGNONSTATE_CHANGELEVEL = 9, // server is changing level; please wait
};
enum FileWarningLevel_t
{
FILESYSTEM_WARNING = -1,
FILESYSTEM_WARNING_QUIET = 0,
FILESYSTEM_WARNING_REPORTUNCLOSED,
FILESYSTEM_WARNING_REPORTUSAGE,
FILESYSTEM_WARNING_REPORTALLACCESSES,
FILESYSTEM_WARNING_REPORTALLACCESSES_READ,
FILESYSTEM_WARNING_REPORTALLACCESSES_READWRITE,
FILESYSTEM_WARNING_REPORTALLACCESSES_ASYNC
};
#define FCVAR_NONE 0
// Command to ConVars and ConCommands
// ConVar Systems
#define FCVAR_UNREGISTERED (1<<0) // If this is set, don't add to linked list, etc.
#define FCVAR_DEVELOPMENTONLY (1<<1) // Hidden in released products. Flag is removed automatically if ALLOW_DEVELOPMENT_CVARS is defined.
#define FCVAR_GAMEDLL (1<<2) // defined by the game DLL
#define FCVAR_CLIENTDLL (1<<3) // defined by the client DLL
#define FCVAR_HIDDEN (1<<4) // Hidden. Doesn't appear in find or auto complete. Like DEVELOPMENTONLY, but can't be compiled out.
// ConVar only
#define FCVAR_PROTECTED (1<<5) // It's a server cvar, but we don't send the data since it's a password, etc. Sends 1 if it's not bland/zero, 0 otherwise as value
#define FCVAR_SPONLY (1<<6) // This cvar cannot be changed by clients connected to a multiplayer server.
#define FCVAR_ARCHIVE (1<<7) // set to cause it to be saved to vars.rc
#define FCVAR_NOTIFY (1<<8) // notifies players when changed
#define FCVAR_USERINFO (1<<9) // changes the client's info string
#define FCVAR_PRINTABLEONLY (1<<10) // This cvar's string cannot contain unprintable characters ( e.g., used for player name etc ).
#define FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS (1<<10) // When on concommands this allows remote clients to execute this cmd on the server.
// We are changing the default behavior of concommands to disallow execution by remote clients without
// this flag due to the number existing concommands that can lag or crash the server when clients abuse them.
#define FCVAR_UNLOGGED (1<<11) // If this is a FCVAR_SERVER, don't log changes to the log file / console if we are creating a log
#define FCVAR_NEVER_AS_STRING (1<<12) // never try to print that cvar
// It's a ConVar that's shared between the client and the server.
// At signon, the values of all such ConVars are sent from the server to the client (skipped for local
// client, of course )
// If a change is requested it must come from the console (i.e., no remote client changes)
// If a value is changed while a server is active, it's replicated to all connected clients
#define FCVAR_REPLICATED (1<<13) // server setting enforced on clients, TODO rename to FCAR_SERVER at some time
#define FCVAR_CHEAT (1<<14) // Only useable in singleplayer / debug / multiplayer & sv_cheats
#define FCVAR_SS (1<<15) // causes varnameN where N == 2 through max splitscreen slots for mod to be autogenerated
#define FCVAR_DEMO (1<<16) // record this cvar when starting a demo file
#define FCVAR_DONTRECORD (1<<17) // don't record these command in demofiles
#define FCVAR_SS_ADDED (1<<18) // This is one of the "added" FCVAR_SS variables for the splitscreen players
#define FCVAR_RELEASE (1<<19) // Cvars tagged with this are the only cvars avaliable to customers
#define FCVAR_RELOAD_MATERIALS (1<<20) // If this cvar changes, it forces a material reload
#define FCVAR_RELOAD_TEXTURES (1<<21) // If this cvar changes, if forces a texture reload
#define FCVAR_NOT_CONNECTED (1<<22) // cvar cannot be changed by a client that is connected to a server
#define FCVAR_MATERIAL_SYSTEM_THREAD (1<<23) // Indicates this cvar is read from the material system thread
#define FCVAR_ARCHIVE_GAMECONSOLE (1<<24) // cvar written to config.cfg on the Xbox
#define FCVAR_SERVER_CAN_EXECUTE (1<<28)// the server is allowed to execute this command on clients via ClientCommand/NET_StringCmd/CBaseClientState::ProcessStringCmd.
#define FCVAR_SERVER_CANNOT_QUERY (1<<29)// If this is set, then the server is not allowed to query this cvar's value (via IServerPluginHelpers::StartQueryCvarValue).
#define FCVAR_CLIENTCMD_CAN_EXECUTE (1<<30) // IVEngineClient::ClientCmd is allowed to execute this command.
#define MAX_PLAYERS 128 // Max R5 players.

470
r5dedicated/gameclasses.cpp Normal file
View File

@ -0,0 +1,470 @@
#include "pch.h"
#include "enums.h"
#include "gameclasses.h"
// Need this for a re-factor later.
// Interface* interfaces = *reinterpret_cast<Interface**>(0x167F4FA48);
// for (Interface* current = interfaces; current; current = reinterpret_cast<Interface*>(current->NextInterfacePtr))
// {
// printf("%s: %p\n", current->InterfaceName, current->InterfacePtr);
// }
namespace GameGlobals
{
bool IsInitialized = false;
CHostState* HostState = nullptr;
CInputSystem* InputSystem = nullptr;
CCVar* Cvar = nullptr;
CClient* Client = nullptr;
BanList* BanSystem = new BanList();
CKeyValuesSystem* KeyValuesSystem = nullptr;
KeyValues** PlaylistKeyValues = nullptr;
std::vector<std::string> allPlaylists = { "none" };
namespace CustomCommandVariations
{
void Kick_Callback(CCommand* cmd)
{
std::int32_t argSize = *(std::int32_t*)((std::uintptr_t)cmd + 0x4);
if (argSize < 2) // Do we atleast have 2 arguments?
return;
CCommand& cmdReference = *cmd; // Get reference.
const char* firstArg = cmdReference[1]; // Get first arg.
for (int i = 0; i < MAX_PLAYERS; i++) // Loop through all possible client instances.
{
CClient* client = GameGlobals::Client->GetClientInstance(i); // Get client instance.
if (!client)
continue;
if (!client->GetNetChan()) // Netchan valid?
continue;
void* clientNamePtr = (void**)(((std::uintptr_t)client->GetNetChan()) + 0x1A8D); // Get client name from netchan.
std::string clientName((char*)clientNamePtr, 32); // Get full name.
if (clientName.empty()) // Empty name?
continue;
if (strcmp(firstArg, clientName.c_str()) != 0) // Our wanted name?
continue;
DisconnectClient(client, "Kicked from Server", 0, 1); // Disconnect client.
}
}
void KickID_Callback(CCommand* cmd)
{
static auto HasOnlyDigits = [](const std::string& string)
{
for (const char& character : string)
{
if (std::isdigit(character) == 0)
return false;
}
return true;
};
std::int32_t argSize = *(std::int32_t*)((std::uintptr_t)cmd + 0x4);
if (argSize < 2) // Do we atleast have 2 arguments?
return;
CCommand& cmdReference = *cmd; // Get reference.
std::string firstArg = cmdReference[1]; // Get first arg.
try
{
bool onlyDigits = HasOnlyDigits(firstArg); // Only has digits?
for (int i = 0; i < MAX_PLAYERS; i++) // Loop through all possible client instances.
{
CClient* client = GameGlobals::Client->GetClientInstance(i); // Get client instance.
if (!client)
continue;
if (!client->GetNetChan()) // Netchan valid?
continue;
std::string finalIPAddress = "null"; // If this stays null they modified the packet somehow.
MemoryAddress ipAddressField = MemoryAddress(((std::uintptr_t)client->GetNetChan()) + 0x1AC0); // Get client ip from netchan.
if (ipAddressField)
{
std::stringstream ss;
ss << std::to_string(ipAddressField.GetValue<std::uint8_t>()) << "."
<< std::to_string(ipAddressField.Offset(0x1).GetValue<std::uint8_t>()) << "."
<< std::to_string(ipAddressField.Offset(0x2).GetValue<std::uint8_t>()) << "."
<< std::to_string(ipAddressField.Offset(0x3).GetValue<std::uint8_t>());
finalIPAddress = ss.str();
}
if (onlyDigits)
{
std::int64_t ID = static_cast<std::int64_t>(std::stoll(firstArg));
if (ID > MAX_PLAYERS) // Is it a possible originID?
{
std::int64_t originID = client->m_iOriginID;
if (originID != ID) // See if they match.
continue;
}
else // If its not try by userID.
{
std::int64_t clientID = static_cast<std::int64_t>(client->m_iUserID + 1); // Get UserID + 1.
if (clientID != ID) // See if they match.
continue;
}
DisconnectClient(client, "Kicked from Server", 0, 1); // Disconnect client.
}
else
{
if (firstArg.compare(finalIPAddress) != NULL) // Do the string equal?
continue;
DisconnectClient(client, "Kicked from Server", 0, 1); // Disconnect client.
}
}
}
catch (std::exception& e)
{
std::cout << "Kick UID asked for a userID or originID :( You can get the userID with the 'status' command. Error: " << e.what() << std::endl;
return;
}
}
void Unban_Callback(CCommand* cmd)
{
static auto HasOnlyDigits = [](const std::string& string)
{
for (const char& character : string)
{
if (std::isdigit(character) == 0)
return false;
}
return true;
};
std::int32_t argSize = *(std::int32_t*)((std::uintptr_t)cmd + 0x4);
if (argSize < 2) // Do we atleast have 2 arguments?
return;
CCommand& cmdReference = *cmd; // Get reference.
try
{
const char* firstArg = cmdReference[1];
if (HasOnlyDigits(firstArg)) // Check if we have an ip address or origin ID.
{
GameGlobals::BanSystem->DeleteEntry("noIP", std::stoll(firstArg)); // Delete ban entry.
GameGlobals::BanSystem->Save(); // Save modified vector to file.
}
else
{
GameGlobals::BanSystem->DeleteEntry(firstArg, 1); // Delete ban entry.
GameGlobals::BanSystem->Save(); // Save modified vector to file.
}
}
catch (std::exception& e)
{
std::cout << "Unban Error: " << e.what() << std::endl;
return;
}
}
void ReloadBanList_Callback(CCommand* cmd)
{
GameGlobals::BanSystem->Load(); // Reload banlist.
}
void Ban_Callback(CCommand* cmd)
{
std::int32_t argSize = *(std::int32_t*)((std::uintptr_t)cmd + 0x4);
if (argSize < 2) // Do we atleast have 2 arguments?
return;
CCommand& cmdReference = *cmd; // Get reference.
const char* firstArg = cmdReference[1]; // Get first arg.
for (int i = 0; i < MAX_PLAYERS; i++) // Loop through all possible client instances.
{
CClient* client = GameGlobals::Client->GetClientInstance(i); // Get client instance.
if (!client)
continue;
if (!client->GetNetChan()) // Netchan valid?
continue;
void* clientNamePtr = (void**)(((std::uintptr_t)client->GetNetChan()) + 0x1A8D); // Get client name from netchan.
std::string clientName((char*)clientNamePtr, 32); // Get full name.
if (clientName.empty()) // Empty name?
continue;
if (strcmp(firstArg, clientName.c_str()) != 0) // Our wanted name?
continue;
std::string finalIPAddress = "null"; // If this stays null they modified the packet somehow.
MemoryAddress ipAddressField = MemoryAddress(((std::uintptr_t)client->GetNetChan()) + 0x1AC0); // Get client ip from netchan.
if (ipAddressField && ipAddressField.GetValue<int>() != 0x0)
{
std::stringstream ss;
ss << std::to_string(ipAddressField.GetValue<std::uint8_t>()) << "."
<< std::to_string(ipAddressField.Offset(0x1).GetValue<std::uint8_t>()) << "."
<< std::to_string(ipAddressField.Offset(0x2).GetValue<std::uint8_t>()) << "."
<< std::to_string(ipAddressField.Offset(0x3).GetValue<std::uint8_t>());
finalIPAddress = ss.str();
}
GameGlobals::BanSystem->AddEntry(finalIPAddress, client->m_iOriginID); // Add ban entry.
GameGlobals::BanSystem->Save(); // Save ban list.
DisconnectClient(client, "Banned from Server", 0, 1); // Disconnect client.
}
}
void BanID_Callback(CCommand* cmd)
{
static auto HasOnlyDigits = [](const std::string& string)
{
for (const char& character : string)
{
if (std::isdigit(character) == 0)
return false;
}
return true;
};
std::int32_t argSize = *(std::int32_t*)((std::uintptr_t)cmd + 0x4);
if (argSize < 2) // Do we atleast have 2 arguments?
return;
CCommand& cmdReference = *cmd; // Get reference.
std::string firstArg = cmdReference[1];
try
{
bool onlyDigits = HasOnlyDigits(firstArg); // Only has digits?
for (int i = 0; i < MAX_PLAYERS; i++) // Loop through all possible client instances.
{
CClient* client = GameGlobals::Client->GetClientInstance(i); // Get client instance.
if (!client)
continue;
if (!client->GetNetChan()) // Netchan valid?
continue;
std::string finalIPAddress = "null"; // If this stays null they modified the packet somehow.
MemoryAddress ipAddressField = MemoryAddress(((std::uintptr_t)client->GetNetChan()) + 0x1AC0); // Get client ip from netchan.
if (ipAddressField)
{
std::stringstream ss;
ss << std::to_string(ipAddressField.GetValue<std::uint8_t>()) << "."
<< std::to_string(ipAddressField.Offset(0x1).GetValue<std::uint8_t>()) << "."
<< std::to_string(ipAddressField.Offset(0x2).GetValue<std::uint8_t>()) << "."
<< std::to_string(ipAddressField.Offset(0x3).GetValue<std::uint8_t>());
finalIPAddress = ss.str();
}
if (onlyDigits)
{
std::int64_t ID = static_cast<std::int64_t>(std::stoll(firstArg));
if (ID > MAX_PLAYERS) // Is it a possible originID?
{
std::int64_t originID = client->m_iOriginID;
if (originID != ID) // See if they match.
continue;
}
else // If its not try by userID.
{
std::int64_t clientID = static_cast<std::int64_t>(client->m_iUserID + 1); // Get UserID + 1.
if (clientID != ID) // See if they match.
continue;
}
GameGlobals::BanSystem->AddEntry(finalIPAddress, client->m_iOriginID); // Add ban entry.
GameGlobals::BanSystem->Save(); // Save ban list.
DisconnectClient(client, "Banned from Server", 0, 1); // Disconnect client.
}
else
{
if (firstArg.compare(finalIPAddress) != NULL) // Do the string equal?
continue;
GameGlobals::BanSystem->AddEntry(finalIPAddress, client->m_iOriginID); // Add ban entry.
GameGlobals::BanSystem->Save(); // Save ban list.
DisconnectClient(client, "Banned from Server", 0, 1); // Disconnect client.
}
}
}
catch (std::exception& e)
{
std::cout << "Banid Error: " << e.what() << std::endl;
return;
}
}
}
void NullHostNames()
{
const char* hostnameArray[] =
{
"pin_telemetry_hostname",
"assetdownloads_hostname",
"users_hostname",
"persistence_hostname",
"speechtotexttoken_hostname",
"communities_hostname",
"persistenceDef_hostname",
"party_hostname",
"speechtotext_hostname",
"serverReports_hostname",
"subscription_hostname",
"steamlink_hostname",
"staticfile_hostname",
"matchmaking_hostname",
"skill_hostname",
"publication_hostname",
"stats_hostname"
};
for (int i = 0; i < 17; i++)
{
const char* name = hostnameArray[i];
Cvar->FindVar(name)->m_pzsCurrentValue = "0.0.0.0";
}
}
void InitGameGlobals()
{
HostState = reinterpret_cast<CHostState*>(0x141736120); // Get CHostState from memory.
InputSystem = *reinterpret_cast<CInputSystem**>(0x14D40B380); // Get IInputSystem from memory.
Cvar = *reinterpret_cast<CCVar**>(0x14D40B348); // Get CCVar from memory.
//KeyValuesSystem = reinterpret_cast<CKeyValuesSystem*>(0x141F105C0); // Get CKeyValuesSystem from memory.
//PlaylistKeyValues = reinterpret_cast<KeyValues**>(0x16705B980); // Get the KeyValue for the playlist file.
//Client = reinterpret_cast<CClient*>(0x16073B200);
//NullHostNames(); // Null all hostnames.
//InitAllCommandVariations(); // Initialize our custom ConVars.
//*(char*)addr_m_bRestrictServerCommands = true; // Restrict commands.
//void* disconnect = Cvar->FindCommand("disconnect");
//*(std::int32_t*)((std::uintptr_t)disconnect + 0x38) |= FCVAR_SERVER_CAN_EXECUTE; // Make sure server is not restricted to this.
//std::thread t1(InitPlaylist); // Start thread to grab playlists.
//t1.detach(); // Detach thread from current one.
IsInitialized = true;
}
void InitPlaylist()
{
while (true)
{
if ((*PlaylistKeyValues))
{
KeyValues* playlists = (*PlaylistKeyValues)->FindKey("Playlists", false); // Find playlists key.
if (playlists)
{
allPlaylists.clear();
for (KeyValues* dat = playlists->m_pSub; dat != nullptr; dat = dat->m_pPeer) // Parse through all sub keys.
{
allPlaylists.push_back(dat->GetName()); // Get all playlist names.
}
break; // Break if playlist got filled.
}
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
}
void InitAllCommandVariations()
{
void* KickConCommand = CreateCustomConCommand("kick", "Kick a client from the Server via name. | Usage: kick (name).", 0, CustomCommandVariations::Kick_Callback, nullptr);
void* KickIDConCommand = CreateCustomConCommand("kickid", "Kick a client from the Server via userID or originID | Usage: kickid (originID/userID)", 0, CustomCommandVariations::KickID_Callback, nullptr);
void* UnbanConCommand = CreateCustomConCommand("unban", "Unbans a client from the Server via IP or originID | Usage: unban (originID/ipAddress)", 0, CustomCommandVariations::Unban_Callback, nullptr);
void* ReloadBanListConCommand = CreateCustomConCommand("reloadbanlist", "Reloads the ban list from disk.", 0, CustomCommandVariations::ReloadBanList_Callback, nullptr);
void* BanConCommand = CreateCustomConCommand("ban", "Bans a client from the Server via name. | Usage: ban (name)", 0, CustomCommandVariations::Ban_Callback, nullptr);
void* BanIDConCommand = CreateCustomConCommand("banid", "Bans a client from the Server via originID, userID or IP | Usage: banid (originID/ipAddress/userID)", 0, CustomCommandVariations::BanID_Callback, nullptr);
}
void* CreateCustomConCommand(const char* name, const char* helpString, int flags, void* callback, void* callbackAfterExecution)
{
static MemoryAddress ConCommandVtable = MemoryAddress(0x14136BD70);
static MemoryAddress NullSub = MemoryAddress(0x1401B3280);
static MemoryAddress CallbackCompletion = MemoryAddress(0x1401E3990);
static MemoryAddress RegisterConCommand = MemoryAddress(0x14046F470);
void* command = reinterpret_cast<void*>(addr_MemAlloc_Wrapper(0x68)); // Allocate new memory with StdMemAlloc else we crash.
memset(command, 0, 0x68); // Set all to null.
std::uintptr_t commandPtr = reinterpret_cast<std::uintptr_t>(command); // To ptr.
*(void**)commandPtr = ConCommandVtable.RCast<void*>(); // 0x0 to ConCommand vtable.
*(const char**)(commandPtr + 0x18) = name; // 0x18 to ConCommand Name.
*(const char**)(commandPtr + 0x20) = helpString; // 0x20 to ConCommand help string.
*(std::int32_t*)(commandPtr + 0x38) = flags; // 0x38 to ConCommand Flags.
*(void**)(commandPtr + 0x40) = NullSub.RCast<void*>(); // 0x40 Nullsub since every concommand has it.
*(void**)(commandPtr + 0x50) = callback; // 0x50 has function callback.
*(std::int32_t*)(commandPtr + 0x60) = 2; // 0x60 Set to use callback and newcommand callback.
if (callbackAfterExecution) // Do we wanna have a callback after execution?
{
*(void**)(commandPtr + 0x58) = callbackAfterExecution; // 0x58 to our callback after execution.
}
else
{
*(void**)(commandPtr + 0x58) = CallbackCompletion.RCast<void*>(); // 0x58 nullsub.
}
RegisterConCommand.RCast<void(*)(void*)>()((void*)commandPtr); // Register command in ConVarAccessor.
return command;
}
ConVar* CreateCustomConVar(const char* name, const char* defaultValue, int flags, const char* helpString, bool bMin, float fMin, bool bMax, float fMax, void* callback, void* unk)
{
static MemoryAddress ConVarVtable = MemoryAddress(0x14046FB50).Offset(0x12).ResolveRelativeAddress(); // Get vtable ptr for ConVar table.
static MemoryAddress ICvarVtable = MemoryAddress(0x14046FB50).Offset(0x29).ResolveRelativeAddress(); // Get vtable ptr for ICvar table.
static MemoryAddress CreateConVar = MemoryAddress(0x140470540); // Get CreateConvar address.
ConVar* allocatedConvar = reinterpret_cast<ConVar*>(addr_MemAlloc_Wrapper(0xA0)); // Allocate new memory with StdMemAlloc else we crash.
memset(allocatedConvar, 0, 0xA0); // Set all to null.
std::uintptr_t cvarPtr = reinterpret_cast<std::uintptr_t>(allocatedConvar); // To ptr.
*(void**)(cvarPtr + 0x40) = ICvarVtable.RCast<void*>(); // 0x40 to ICvar table.
*(void**)cvarPtr = ConVarVtable.RCast<void*>(); // 0x0 to ConVar vtable.
CreateConVar.RCast<void(*)(ConVar*, const char*, const char*, int, const char*, bool, float, bool, float, void*, void*)>() // Call to create ConVar.
(allocatedConvar, name, defaultValue, flags, helpString, bMin, fMin, bMax, fMax, callback, unk);
return allocatedConvar; // Return allocated ConVar.
}
void DisconnectClient(CClient* client, const char* reason, unsigned __int8 unk1, char unk2)
{
if (!client) // Client valid?
return;
if (std::strlen(reason) == NULL) // Is reason null?
return;
if (!client->GetNetChan())
return;
addr_NetChan_Shutdown(client->GetNetChan(), reason, unk1, unk2); // Shutdown netchan.
client->GetNetChan() = nullptr; // Null netchan.
MemoryAddress(0x140302FD0).RCast<void(*)(CClient*)>()(client); // Reset CClient instance for client.
}
}
#pragma region KeyValues
const char* KeyValues::GetName()
{
return GameGlobals::KeyValuesSystem->GetStringForSymbol(MAKE_3_BYTES_FROM_1_AND_2(m_iKeyNameCaseSensitive, m_iKeyNameCaseSensitive2));
}
#pragma endregion

487
r5dedicated/gameclasses.h Normal file
View File

@ -0,0 +1,487 @@
#pragma once
#include "pch.h"
#include "hooks.h"
#include "enums.h"
#include "banlist.h"
/////////////////////////////////////////////////////////////////////////////
// Classes and Structs
class CInputSystem
{
public:
void EnableInput(bool bEnabled)// @0x14039F100 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
using OriginalFn = void(__thiscall*)(CInputSystem*, bool);
(*reinterpret_cast<OriginalFn**>(this))[10](this, bEnabled);
}
void EnableMessagePump(bool bEnabled) // @0x14039F110 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
using OriginalFn = void(__thiscall*)(CInputSystem*, bool);
(*reinterpret_cast<OriginalFn**>(this))[11](this, bEnabled);
}
bool IsButtonDown(ButtonCode_t Button) // @0x1403A0140 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
using OriginalFn = bool(__thiscall*)(CInputSystem*, ButtonCode_t);
return (*reinterpret_cast<OriginalFn**>(this))[13](this, Button);
}
private:
char pad_0000[16]; //0x0000
public:
bool m_bEnabled; //0x0010 IsInputEnabled variable.
bool m_bPumpEnabled; //0x0011 EnabledMessagePump variable.
};
typedef int HKeySymbol;
#define MAKE_3_BYTES_FROM_1_AND_2( x1, x2 ) (( (( std::uint16_t )x2) << 8 ) | (std::uint8_t)(x1))
class CKeyValuesSystem // VTABLE @ 0x1413AA1E8 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
public:
void RegisterSizeofKeyValues(__int64 size) //@0x1413AA1F0 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
using OriginalFn = void(__thiscall*)(CKeyValuesSystem*, __int64);
(*reinterpret_cast<OriginalFn**>(this))[0](this, size);
}
void* AllocKeyValuesMemory(__int64 size) // @0x1413AA1F8 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
using OriginalFn = void* (__thiscall*)(CKeyValuesSystem*, __int64);
return (*reinterpret_cast<OriginalFn**>(this))[1](this, size);
}
void FreeKeyValuesMemory(void* pMem) // @0x1413AA200 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
using OriginalFn = void(__thiscall*)(CKeyValuesSystem*, void*);
(*reinterpret_cast<OriginalFn**>(this))[2](this, pMem);
}
HKeySymbol GetSymbolForString(const char* name, bool bCreate) // @0x1413AA208 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
using OriginalFn = HKeySymbol(__thiscall*)(CKeyValuesSystem*, const char*, bool);
return (*reinterpret_cast<OriginalFn**>(this))[3](this, name, bCreate);
}
const char* GetStringForSymbol(HKeySymbol symbol) // @0x1413AA210 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
using OriginalFn = const char* (__thiscall*)(CKeyValuesSystem*, HKeySymbol);
return (*reinterpret_cast<OriginalFn**>(this))[4](this, symbol);
}
// void __fastcall CKeyValuesSystem::FreeKeyValuesMemory(CKeyValuesSystem* this_arg, void* ptr_mem_arg)
// {
// __int64* v2; // rax
// __int64 v4; // rax
// __int64* v5; // rax
//
// v2 = qword_14D40B538;
// if (!qword_14D40B538)
// {
// v2 = sub_140462930();
// qword_14D40B538 = v2;
// }
// v4 = (*(*v2 + 48))(v2, ptr_mem_arg);
// if (v4 > 0)
// CKeyValuesSystem::m_pMemPool -= v4;
// v5 = qword_14D40B538;
// if (!qword_14D40B538)
// {
// v5 = sub_140462930();
// qword_14D40B538 = v5;
// }
// (*(*v5 + 40))(v5, ptr_mem_arg);
// }
// GetMemPool return a global variable called m_pMemPool it gets modified by AllocKeyValuesMemory and FreeKeyValuesMemory above you can see where the find it in FreeKeyValuesMemory.
void* GetMemPool() // @0x1413AA228 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
return reinterpret_cast<void*>(0x14D412768); // May need to dereference is once more not sure right now.
}
void SetKeyValuesExpressionSymbol(const char* name, bool bValue) // @0x1413AA230 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
using OriginalFn = void(__thiscall*)(CKeyValuesSystem*, const char*, bool);
(*reinterpret_cast<OriginalFn**>(this))[8](this, name, bValue);
}
bool GetKeyValuesExpressionSymbol(const char* name) // @0x1413AA238 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
using OriginalFn = bool(__thiscall*)(CKeyValuesSystem*, const char*);
return (*reinterpret_cast<OriginalFn**>(this))[9](this, name);
}
HKeySymbol GetSymbolForStringCaseSensitive(HKeySymbol& hCaseInsensitiveSymbol, const char* name, bool bCreate) // @0x1413AA240 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
using OriginalFn = HKeySymbol(__thiscall*)(CKeyValuesSystem*, HKeySymbol&, const char*, bool);
return (*reinterpret_cast<OriginalFn**>(this))[10](this, hCaseInsensitiveSymbol, name, bCreate);
}
// Datatypes aren't accurate. But full fill the actual byte distance.
public:
void* vtable; // 0x0000
__int64 m_iMaxKeyValuesSize; // 0x0008
private:
char gap10[240]; // 0x0010
public:
__int32 m_KvConditionalSymbolTable; // 0x0100
private:
char gap104[4]; // 0x0104
public:
__int64 field_108; // 0x0108
private:
char gap110[32]; // 0x0110
public:
int m_mutex; // 0x0130
};
class KeyValues
{
public:
KeyValues* FindKey(const char* keyName, bool bCreate)
{
static auto func = reinterpret_cast<KeyValues*(__thiscall*)(KeyValues*, const char*, bool)>(addr_KeyValues_FindKey);
return func(this, keyName, bCreate);
}
const char* GetName();
int GetInt(const char* keyName, int defaultValue)
{
KeyValues* dat = FindKey(keyName, false);
if (!dat)
return defaultValue;
switch (dat->m_iDataType)
{
case TYPE_STRING:
return atoi(dat->m_sValue);
case TYPE_FLOAT:
return static_cast<int>(m_flValue());
case TYPE_WSTRING:
return _wtoi(dat->m_wsValue);
case TYPE_UINT64:
return 0;
default:
return dat->m_iValue();
}
return defaultValue;
}
void SetInt(const char* keyName, int iValue)
{
KeyValues* dat = FindKey(keyName, true);
if (dat)
{
dat->m_iValue() = iValue;
dat->m_iDataType = TYPE_INT;
}
}
void SetFloat(const char* keyName, float flValue)
{
KeyValues* dat = FindKey(keyName, true);
if (dat)
{
dat->m_flValue() = flValue;
dat->m_iDataType = TYPE_FLOAT;
}
}
// Compiler makes it so m_Value shares the offset spot with m_flValue that why we cast it like this.
float& m_flValue()
{
static __int32 offset = 0x18;
return *(float*)((std::uintptr_t)this + offset);
}
int& m_iValue()
{
static __int32 offset = 0x18;
return *(int*)((std::uintptr_t)this + offset);
}
public:
unsigned __int32 m_iKeyName : 24; // 0x0000
unsigned __int32 m_iKeyNameCaseSensitive : 8; // 0x0003
char* m_sValue; // 0x0008
wchar_t* m_wsValue; // 0x0010
int m_Value; // 0x0018
private:
char gap1C[12]; // 0x0020
public:
char m_iDataType; // 0x0028
unsigned __int16 m_iKeyNameCaseSensitive2; // 0x002A
KeyValues* m_pPeer; // 0x0030
KeyValues* m_pSub; // 0x0038
KeyValues* m_pChain; // 0x0040
};
struct Vector3 // Implement the proper class of this at some point.
{
float x; // 0x0000
float y; // 0x0004
float z; // 0x0008
};
struct QAngle // Implement the proper class of this at some point.
{
float pitch; //0x0000
float yaw; // 0x0004
float roll; // 0x0008
};
class CHostState
{
public:
int m_iCurrentState; //0x0000
int m_iNextState; //0x0004
Vector3 m_vecLocation; //0x0008
QAngle m_angLocation; //0x0014
char m_levelName[64]; //0x0020
char m_mapGroupName[256]; //0x0060
char m_landMarkName[256]; //0x0160
float m_flShortFrameTime; //0x0260
bool m_bActiveGame; //0x0264
bool m_bRememberLocation; //0x0265
bool m_bBackgroundLevel; //0x0266
bool m_bWaitingForConnection; //0x0267
bool m_bSplitScreenConnect; //0x0268
bool m_bGameHasShutDownAndFlushedMemory; //0x0269
bool m_bWorkshopMapDownloadPending; //0x026A
};
class CHLClient
{
public:
void FrameStageNotify(ClientFrameStage_t curStage) // @0x1405C0740 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
using OriginalFn = void(__thiscall*)(CHLClient*, ClientFrameStage_t);
(*reinterpret_cast<OriginalFn**>(this))[58](this, curStage); /* 48 83 EC 28 89 15 ? ? ? ? */
}
};
class CClient
{
public:
inline CClient* GetClientInstance(int index)
{
return (CClient*)(std::uintptr_t)(0x16073B200 + (index * (std::uintptr_t)0x4A4C0));
}
void*& GetNetChan()
{
return m_nNetChannel;
}
private:
char pad_0000[16]; //0x0000
public:
int m_iUserID; //0x0010
private:
char pad_0014[908]; //0x0014
public:
void* m_nNetChannel; //0x03A0
private:
char pad_03A8[8]; //0x03A8
public:
int m_iSignonstate; //0x03B0
private:
char pad_03B4[4]; //0x03B4
public:
std::int64_t m_iOriginID; //0x03B8
private:
char pad_03C0[303360]; //0x03C0
};
class CCommand
{
private:
enum
{
COMMAND_MAX_ARGC = 64,
COMMAND_MAX_LENGTH = 512,
};
public:
CCommand() = delete;
inline int MaxCommandLength()
{
return COMMAND_MAX_LENGTH - 1;
}
inline int64_t ArgC() const
{
return m_nArgc;
}
inline const char** ArgV() const
{
return m_nArgc ? (const char**)m_ppArgv : NULL;
}
inline const char* ArgS() const
{
return m_nArgv0Size ? &m_pArgSBuffer[m_nArgv0Size] : "";
}
inline const char* GetCommandString() const
{
return m_nArgc ? m_pArgSBuffer : "";
}
inline const char* Arg(int nIndex) const
{
// FIXME: Many command handlers appear to not be particularly careful
// about checking for valid argc range. For now, we're going to
// do the extra check and return an empty string if it's out of range
if (nIndex < 0 || nIndex >= m_nArgc)
return "";
return m_ppArgv[nIndex];
}
inline const char* operator[](int nIndex) const
{
return Arg(nIndex);
}
private:
std::int64_t m_nArgc;
std::int64_t m_nArgv0Size;
char m_pArgSBuffer[COMMAND_MAX_LENGTH];
char m_pArgvBuffer[COMMAND_MAX_LENGTH];
const char* m_ppArgv[COMMAND_MAX_ARGC];
};
class ConCommandBase
{
public:
void* m_pConCommandBaseVTable; //0x0000
ConCommandBase* m_pNext; //0x0008
bool m_bRegistered; //0x0010
private:
char pad_0011[7]; //0x0011
public:
const char* m_pszName; //0x0018
const char* m_pszHelpString; //0x0020
private:
char pad_0028[16]; //0x0028
public:
__int32 m_nFlags; //0x0038
private:
char pad_003C[4]; //0x003C
}; //Size: 0x0038
class ConVar
{
public:
ConCommandBase m_ConCommandBase; // 0x0000
void* m_pConVarVTable; //0x0040
ConVar* m_pParent; //0x0048
const char* n_pszDefaultValue; //0x0050
const char* m_pzsCurrentValue; //0x0058
__int64 m_iStringLength; //0x0060
float m_flValue; //0x0068
int m_iValue; //0x006C
bool m_bHasMin; //0x0070
float m_flMinValue; //0x0074
bool m_bHasMax; //0x0078
float m_flMaxValue; //0x007C
char pad_0080[32]; //0x0080
}; //Size: 0x00A0
class CCVarIteratorInternal // Fully reversed table, just look at the virtual function table and rename the function.
{
public:
virtual void SetFirst(void) = 0; //0
virtual void Next(void) = 0; //1
virtual bool IsValid(void) = 0; //2
virtual ConCommandBase* Get(void) = 0; //3
};
class CCVar
{
public:
ConCommandBase* FindCommandBase(const char* szCommandName) // @0x1405983A0 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
using OriginalFn = ConCommandBase*(__thiscall*)(CCVar*, const char*);
return (*reinterpret_cast<OriginalFn**>(this))[14](this, szCommandName);
}
ConVar* FindVar(const char* szVarName) // @0x1405983B0 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
using OriginalFn = ConVar*(__thiscall*)(CCVar*, const char*);
return (*reinterpret_cast<OriginalFn**>(this))[16](this, szVarName);
}
void* /*Implement ConCommand class.*/ FindCommand(const char* szCommandName) // @0x1405983F0 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
using OriginalFn = void*(__thiscall*)(CCVar*, const char*);
return (*reinterpret_cast<OriginalFn**>(this))[18](this, szCommandName);
}
CCVarIteratorInternal* FactoryInternalIterator() // @0x140597C10 in R5pc_r5launch_N1094_CL456479_2019_10_30_05_20_PM
{
using OriginalFn = CCVarIteratorInternal*(__thiscall*)(CCVar*);
return (*reinterpret_cast<OriginalFn**>(this))[41](this);
}
std::unordered_map<std::string, ConCommandBase*> DumpToMap()
{
std::stringstream ss;
CCVarIteratorInternal* itint = FactoryInternalIterator(); // Allocatd new InternalIterator.
std::unordered_map<std::string, ConCommandBase*> allConVars;
for (itint->SetFirst(); itint->IsValid(); itint->Next()) // Loop through all instances.
{
ConCommandBase* command = itint->Get();
const char* commandName = command->m_pszName;
allConVars[commandName] = command;
}
return allConVars;
}
};
struct Interface
{
__int64 (*InterfacePtr)(void);
const char* InterfaceName;
__int64* NextInterfacePtr;
};
/////////////////////////////////////////////////////////////////////////////
// Initialize Game Globals
namespace GameGlobals
{
// Class Instances
extern CHostState* HostState;
extern CInputSystem* InputSystem;
extern CCVar* Cvar;
extern KeyValues** PlaylistKeyValues;
extern CKeyValuesSystem* KeyValuesSystem;
extern CClient* Client;
extern BanList* BanSystem;
// Var
ConVar* CreateCustomConVar(const char* name, const char* defaultValue, int flags, const char* helpString, bool bMin, float fMin, bool bMax, float fMax, void* callback, void* unk);
void* CreateCustomConCommand(const char* name, const char* helpString, int flags, void* callback, void* callbackAfterExecution);
// Init
void InitGameGlobals();
void InitAllCommandVariations();
void InitPlaylist();
extern std::vector<std::string> allPlaylists;
extern bool IsInitialized;
// Utility
void DisconnectClient(CClient* client, const char* reason, unsigned __int8 unk1, char unk2);
}

View File

@ -1,6 +1,7 @@
#include "pch.h"
#include "hooks.h"
#include "opcodes.h"
#include "gameclasses.h"
void Hooks::InstallHooks()
{
@ -8,6 +9,11 @@ void Hooks::InstallHooks()
// Initialize Minhook
MH_Initialize();
///////////////////////////////////////////////////////////////////////////////
// Hook SourceAppSystemGroup functions
MH_CreateHook(addr_CSourceAppSystemGroup_Create, &Hooks::CSourceAppSystemGroup_Create, reinterpret_cast<void**>(&originalCSourceAppSystemGroup_Create));
///////////////////////////////////////////////////////////////////////////////
// Hook Squirrel functions
MH_CreateHook(addr_SQVM_Print, &Hooks::SQVM_Print, NULL);
MH_CreateHook(addr_SQVM_LoadRson, &Hooks::SQVM_LoadRson, reinterpret_cast<void**>(&originalSQVM_LoadRson));
@ -32,6 +38,10 @@ void Hooks::InstallHooks()
// Hook Utility functions
MH_CreateHook(addr_MSG_EngineError, &Hooks::MSG_EngineError, reinterpret_cast<void**>(&originalMSG_EngineError));
///////////////////////////////////////////////////////////////////////////////
// Enable SourceAppSystemGroup hooks
MH_EnableHook(addr_CSourceAppSystemGroup_Create);
///////////////////////////////////////////////////////////////////////////////
// Enable Squirrel hooks
MH_EnableHook(addr_SQVM_Print);
@ -52,11 +62,17 @@ void Hooks::InstallHooks()
// Enabled Utility hooks
MH_EnableHook(addr_MSG_EngineError);
InstallOpcodes();
///////////////////////////////////////////////////////////////////////////////
// Set global variables
GameGlobals::InitGameGlobals();
}
void Hooks::RemoveHooks()
{
///////////////////////////////////////////////////////////////////////////////
// Hook SourceAppSystemGroup functions
MH_RemoveHook(addr_CSourceAppSystemGroup_Create);
///////////////////////////////////////////////////////////////////////////////
// Unhook Squirrel functions
MH_RemoveHook(addr_SQVM_Print);

View File

@ -5,6 +5,10 @@ namespace
{
Module r5_patterns = Module("r5apex.exe"); // Create module class instance.
#pragma region CSourceAppSystemGroup
FUNC_AT_ADDRESS(addr_CSourceAppSystemGroup_Create, char(*)(__int64), r5_patterns.PatternSearch("48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC 20 48 8B F9 E8 ? ? ? ? 33 C9").GetPtr());
#pragma endregion
#pragma region Console
/*0x140202090*/
FUNC_AT_ADDRESS(addr_CommandExecute, void(*)(void*, const char*), r5_patterns.PatternSearch("48 89 5C 24 ? 57 48 83 EC 20 48 8D 0D ? ? ? ? 41 8B D8").GetPtr());
@ -36,6 +40,9 @@ namespace
/*0x1402662D0*/
FUNC_AT_ADDRESS(addr_NET_SendDatagram, int(*)(SOCKET, const char*, int, int), r5_patterns.PatternSearch("48 89 5C 24 08 48 89 6C 24 10 48 89 74 24 18 57 41 56 41 57 48 81 EC ? 05 ? ?").GetPtr());
/*0x14025F190*/
FUNC_AT_ADDRESS(addr_NetChan_Shutdown, void(*)(void*, const char*, unsigned __int8, char), r5_patterns.StringSearch("Disconnect by server.\n").FindPatternSelf("E8 ? ? ? ? 4C 89 B3 ? ? ? ?", MemoryAddress::Direction::DOWN).FollowNearCallSelf().GetPtr());
#pragma endregion
#pragma region CHLClient
@ -43,6 +50,11 @@ namespace
FUNC_AT_ADDRESS(addr_CHLClient_FrameStageNotify, void(*)(void* rcx, int curStage), r5_patterns.PatternSearch("48 83 EC 28 89 15 ?? ?? ?? ??").GetPtr());
#pragma endregion
#pragma region CClientState
/*0x1418223E4*/
FUNC_AT_ADDRESS(addr_m_bRestrictServerCommands, void*, r5_patterns.StringSearch("DevShotGenerator_Init()").FindPatternSelf("88 05", MemoryAddress::Direction::UP).ResolveRelativeAddressSelf(0x2).OffsetSelf(0x2).GetPtr());
#pragma endregion
#pragma region CVEngineServer
/*0x140315CF0*/
FUNC_AT_ADDRESS(addr_CVEngineServer_IsPersistenceDataAvailable, bool(*)(__int64, int), r5_patterns.PatternSearch("3B 15 ?? ?? ?? ?? 7D 33").GetPtr());
@ -51,13 +63,23 @@ namespace
#pragma region Utility
/*0x140295600*/
FUNC_AT_ADDRESS(addr_MSG_EngineError, int(*)(char*, va_list), r5_patterns.PatternSearch("48 89 5C 24 08 48 89 74 24 10 57 48 81 EC 30 08 00 00 48 8B DA").GetPtr());
/*0x1401B31C0*/
FUNC_AT_ADDRESS(addr_MemAlloc_Wrapper, void* (*)(__int64), r5_patterns.StringSearch("ConversionModeMenu").FindPatternSelf("E8 ? ? ? ? 48", MemoryAddress::Direction::UP).FollowNearCallSelf().GetPtr());
#pragma endregion
// Un-used atm.
// DWORD64 p_KeyValues_FindKey = /*1404744E0*/ reinterpret_cast<DWORD64>(PatternScan("r5apex.exe", "40 56 57 41 57 48 81 EC ?? ?? ?? ?? 45"));
#pragma region KeyValues
/*0x1404744E0*/
FUNC_AT_ADDRESS(addr_KeyValues_FindKey, void* (*)(void*, const char*, bool), r5_patterns.PatternSearch("40 56 57 41 57 48 81 EC ?? ?? ?? ?? 45").GetPtr());
#pragma endregion
void PrintHAddress() // Test the sigscan results
{
std::cout << "+--------------------------------------------------------+" << std::endl;
PRINT_ADDRESS("CSourceAppSystemGroup::Create", addr_CSourceAppSystemGroup_Create);
PRINT_ADDRESS("CommandExecute", addr_CommandExecute);
PRINT_ADDRESS("ConVar_IsFlagSet", addr_ConVar_IsFlagSet);
PRINT_ADDRESS("ConCommand_IsFlagSet", addr_ConCommand_IsFlagSet);
@ -66,9 +88,12 @@ namespace
PRINT_ADDRESS("SQVM_LoadRson", addr_SQVM_LoadRson);
PRINT_ADDRESS("NET_ReceiveDatagram", addr_NET_ReceiveDatagram);
PRINT_ADDRESS("NET_SendDatagram ", addr_NET_SendDatagram);
PRINT_ADDRESS("NetChan_Shutdown ", addr_NetChan_Shutdown);
PRINT_ADDRESS("CHLClient::FrameStageNotify", addr_CHLClient_FrameStageNotify);
PRINT_ADDRESS("CVEngineServer::IsPersistenceDataAvailable", addr_CVEngineServer_IsPersistenceDataAvailable);
PRINT_ADDRESS("MSG_EngineError", addr_MSG_EngineError);
PRINT_ADDRESS("MemAlloc_Wrapper", addr_MemAlloc_Wrapper);
PRINT_ADDRESS("KeyValues_FindKey", addr_KeyValues_FindKey);
std::cout << "+--------------------------------------------------------+" << std::endl;
// TODO implement error handling when sigscan fails or result is 0
}
@ -80,6 +105,13 @@ inline bool g_bDebugConsole = false;
namespace Hooks
{
#pragma region CSourceAppSystemGroup
char __fastcall CSourceAppSystemGroup_Create(__int64 a1);
using CSourceAppSystemGroup_CreateFn = char(*)(__int64);
extern CSourceAppSystemGroup_CreateFn originalCSourceAppSystemGroup_Create;
#pragma endregion
#pragma region CHLClient
// void __fastcall FrameStageNotify(CHLClient* rcx, ClientFrameStage_t curStage);
@ -122,7 +154,7 @@ namespace Hooks
bool ConCommand_IsFlagSet(int* cmd, int flag);
#pragma endregion
#pragma region Other
#pragma region Utility
int MSG_EngineError(char* fmt, va_list args);
using MSG_EngineErrorFn = int(*)(char*, va_list);
@ -133,4 +165,5 @@ namespace Hooks
void RemoveHooks();
void ToggleNetTrace();
void ToggleDevCommands();
void DedicatedPatch();
}

View File

@ -1,29 +1,152 @@
#include "pch.h"
#include "hooks.h"
#include "enums.h"
#include "opcodes.h"
#include "gameclasses.h"
/*-----------------------------------------------------------------------------
* _opcodes.cpp
*-----------------------------------------------------------------------------*/
void InstallOpcodes() /* .TEXT */
void DisableRenderer()
{
//-------------------------------------------------------------------------
// JNZ --> JMP | Prevent OriginSDK from initializing on the client
//Origin_Init.Offset(0x0B).Patch({ 0xE9, 0x63, 0x02, 0x00, 0x00, 0x00 });
//Origin_SetState.Offset(0x0E).Patch({ 0xE9, 0xCB, 0x03, 0x00, 0x00 });
// FUN --> RET | Called from CEngineClient and CEngineVGUI (Init()?).
r0.Patch({ 0xC3 }); // This patch is likely not required if client.dll isn't initialized.
//-------------------------------------------------------------------------
// JNE --> JMP | Allow games to be loaded without the optional texture streaming file
dst002.Offset(0x8E5).Patch({ 0xEB, 0x19 });
// FUN --> RET | Skip ShaderSetup(). CShaderGlue.
r1.Patch({ 0xC3 });
//-------------------------------------------------------------------------
// JNE --> JMP | Prevent connect command from crashing by invalid call to UI function
dst004.Offset(0x1D6).Patch({ 0xEB, 0x27 });
// FUN --> RET | Skip Matsync. Called from CMaterialSystem.
r2.Patch({ 0xC3 });
//-------------------------------------------------------------------------
// JNE --> JMP | Prevent connect localhost from being executed after listenserver init
//Host_NewGame.Offset(0x637).Patch({ 0xE9, 0xC1, 0x00, 0x00, 0x00});
// JE --> JMP | Matsys mode init (CMaterialSystem).
r3.Offset(0x22).Patch({ 0xEB, 0x66 });
//-------------------------------------------------------------------------
// JA --> JMP | Disable server-side verification for duplicate accounts on the server
CServer_Auth.Offset(0x284).Patch({ 0x90, 0x90 });
// FUN --> RET | Clear render buffer? Called from CMatRenderContext and CTexture.
r4.Patch({ 0xC3 });
//-------------------------------------------------------------------------
// JA --> JMP | Prevent FairFight anti-cheat from initializing on the server
// FUN --> RET | Heavy render stuff. Called from CMatRenderContext.
r5.Patch({ 0xC3 });
//-------------------------------------------------------------------------
// FUN --> RET | Set shader resource.
r6.Patch({ 0xC3 });
//-------------------------------------------------------------------------
// FUN --> RET | Begin.
r7.Patch({ 0xC3, 0x90, 0x90, 0x90, 0x90 });
//-------------------------------------------------------------------------
// FUN --> RET | End.
r8.Patch({ 0xC3, 0x90, 0x90, 0x90, 0x90, 0x90 });
}
void DisableClient()
{
//-------------------------------------------------------------------------
// JNZ --> JMP | Prevent EbisuSDK from initializing on the engine and server.
Origin_Init.Offset(0x0B).Patch({ 0xE9, 0x63, 0x02, 0x00, 0x00, 0x00 });
Origin_SetState.Offset(0x0E).Patch({ 0xE9, 0xCB, 0x03, 0x00, 0x00 });
//-------------------------------------------------------------------------
// JE --> JMP | Skip CreateGameWindow initialization code.
CreateGameWindow.Offset(0x3DD).Patch({ 0xEB, 0x6D });
//-------------------------------------------------------------------------
// JNZ --> JMP | Skip CreateGameWindow validation code.
CreateGameWindow.Offset(0x44C).Patch({ 0xEB, 0x49 });
//-------------------------------------------------------------------------
// PUS --> XOR | Prevent ShowWindow and CreateGameWindow from being initialized.
c1.Patch({ 0x30, 0xC0, 0xC3 });
//-------------------------------------------------------------------------
// PUS --> XOR | Prevent ShowWindow and CreateGameWindow from being initialized.
c1.Patch({ 0x30, 0xC0, 0xC3 });
//-------------------------------------------------------------------------
// JNE --> NOP | TODO: NOP 'particle_script' instead.
c2.Offset(0x23C).Patch({ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 });
//-------------------------------------------------------------------------
// MOV --> NOP | TODO: NOP 'particle_script' instead.
c2.Offset(0x2BD).Patch({ 0x90, 0x90, 0x90 });
//-------------------------------------------------------------------------
// MOV --> NOP | TODO: NOP 'highlight_system' instead.
c3.Offset(0xA9).Patch({ 0x90, 0x90, 0x90, 0x90 });
}
void DisableVGUI()
{
//-------------------------------------------------------------------------
// CMP --> XOR | Skip VGUI initialization jumptable.
v0.Patch({ 0x48, 0x33, 0xC0, 0xC3, 0x90, 0x90, 0x90 });
//-------------------------------------------------------------------------
// JNE --> JMP | Skip call to VGUI loadscreen func.
SCR_BeginLoadingPlaque.Offset(0x427).Patch({ 0xEB, 0x09 });
}
void Hooks::DedicatedPatch()
{
//Sleep(10000);
// for future reference 14171A9B4 - matsys mode
*(uintptr_t*)0x14D415040 = 0x1417304E8;
*(uintptr_t*)0x14B37C3C0 = 0x141F10CA0;
*(uintptr_t*)0x14B3800D7 = 0x1; // bDedicated
DisableRenderer();
DisableClient();
DisableVGUI();
//-------------------------------------------------------------------------
// CAL --> NOP | HLClient call inside eng->frame.
addr_CEngine_Frame.Offset(0x410).Patch({ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 });
//-------------------------------------------------------------------------
// JA --> JMP | Prevent FairFight anti-cheat from initializing on the server.
// TODO: fix and re-enable this.
FairFight_Init.Offset(0x61).Patch({ 0xE9, 0xED, 0x00, 0x00, 0x00, 0x00 });
//-------------------------------------------------------------------------
// JNE --> JMP | Take dedicated initialization routine instead.
s0.Offset(0x19).Patch({ 0xEB, 0x6E });
//-------------------------------------------------------------------------
// JE --> JMP | Skip client.dll Init_PostVideo() validation code.
s0.Offset(0x609).Patch({ 0xEB, 0x2B });
//-------------------------------------------------------------------------
// JNE --> JMP | Skip client.dll Init_PostVideo() validation code.
s0.Offset(0x621).Patch({ 0xEB, 0x0C });
//-------------------------------------------------------------------------
// JE --> JMP | Skip NULL call as client is never initialized.
s0.Offset(0x658).Patch({ 0xE9, 0x8C, 0x00, 0x00, 0x00 });
//-------------------------------------------------------------------------
// JNE --> JMP | Skip shader preloading as cvar can't be checked due to client being NULL.
s0.Offset(0x6E9).Patch({ 0xE9, 0xB0, 0x00, 0x00, 0x00 });
//-------------------------------------------------------------------------
// JNE --> JMP | Return early in _Host_RunFrame() for debugging perposes.
//s1.Offset(0x1C6).Patch({ 0xE9, 0xAD, 0x11, 0x00, 0x00 }); // <-- this one was only used to debug.
//-------------------------------------------------------------------------
// JNE --> JMP | Return early in _Host_RunFrame() for debugging perposes.
s1.Offset(0x1010).Patch({ 0xEB, 0x14 });
//-------------------------------------------------------------------------
// CAL --> NOP | NOP NULL call as client is never initialized.
s1.Offset(0x1023).Patch({ 0x90, 0x90, 0x90 });
//-------------------------------------------------------------------------
// JS --> JMP | Skip ListenServer HeartBeat.
s2.Offset(0xF).Patch({ 0xE9, 0x22, 0x01, 0x00, 0x00 });
//-------------------------------------------------------------------------
// CAL --> NOP | NOP call to UI texture asset preloading.
e0.Offset(0x182).Patch({ 0x90, 0x90, 0x90, 0x90, 0x90 });
//-------------------------------------------------------------------------
// JNE --> JNP | Skip client.dll library initialization.
e0.Offset(0xA7D).Patch({ 0xE9, 0xF0, 0x01, 0x00, 0x00 });
//-------------------------------------------------------------------------
// JNE --> NOP | Skip settings field loading for client texture assets.
// TODO: this is also used by server.dll library.
e1.Offset(0x213).Patch({ 0x90, 0x90, 0x90, 0x90, 0x90, 0x90 });
//-------------------------------------------------------------------------
// ??? 1403DFC30 = 0x94490 ??? // an expensive stuff that wasted many CPU cycles, this one seems to be the best candidate to return
}
// TEST
void SetCHostState()
{
static std::string ServerMap = std::string();
ServerMap = "mp_rr_canyonlands_64k_x_64k";
strncpy_s(GameGlobals::HostState->m_levelName, ServerMap.c_str(), 64); // Copy new map into hoststate levelname. 64 is size of m_levelname.
GameGlobals::HostState->m_iNextState = HostStates_t::HS_NEW_GAME; // Force CHostState::FrameUpdate to start a server.
}

View File

@ -1,7 +1,7 @@
#pragma once
void InstallOpcodes();
inline HANDLE GameProcess = GetCurrentProcess();
void SetCHostState();
namespace
{
@ -36,6 +36,42 @@ namespace
MemoryAddress FairFight_Init = r5_op.PatternSearch("40 53 48 83 EC 20 8B 81 B0 03 ? ? 48 8B D9 C6");
#pragma endregion
// TODO: create patterns instead and rename to function names.
// Renderer
MemoryAddress r0 = 0x00000001402FE280; //
MemoryAddress r1 = 0x00000001403B3A50; //
MemoryAddress r2 = 0x00000001403DEE90; //
MemoryAddress r3 = 0x00000001403BD120; //
MemoryAddress r4 = 0x0000000140404380; //
MemoryAddress r5 = 0x000000014040D850; //
MemoryAddress r6 = 0x0000000140413260; //
MemoryAddress r7 = 0x00000001404093F0; //
MemoryAddress r8 = 0x00000001403D2E60; //
MemoryAddress d3d11init = 0x000000014043CDF0; //
// Engine
MemoryAddress e0 = 0x0000000140236E40; // main Host_Init()?
MemoryAddress e1 = 0x0000000140FB2F10; // also used by CServerGameDLL
MemoryAddress addr_CEngine_Frame = 0x00000001402970E0;
// SERVER
MemoryAddress s0 = 0x0000000140237B00; // server Host_Init()?
MemoryAddress s1 = 0x0000000140231C00; // _Host_RunFrame() with inlined CFrameTimer::MarkFrame()?
MemoryAddress s2 = 0x00000001402312A0; // server HeartBeat? (baseserver.cpp)
// CLIENT
MemoryAddress c0 = 0x0000000140236640; // client Host_Init()?
MemoryAddress c1 = 0x0000000140299100; // CreateGameWindowInit()?
MemoryAddress c2 = 0x00000001403F4360; // 1403DF870 --> 1403F4360
MemoryAddress c3 = 0x00000001403F8A80; // 1403DF870 --> 1403F8A40
MemoryAddress CreateGameWindow = 0x0000000140343DE0;
// VGUI
MemoryAddress v0 = 0x0000000140282E40; // jumptable
MemoryAddress SCR_BeginLoadingPlaque = 0x000000014023E870;
void PrintOAddress() // Test the sigscan results
{
std::cout << "+--------------------------------------------------------+" << std::endl;

View File

@ -1,5 +1,5 @@
#pragma once
#pragma message("Pre-compiling headers.\n")
#pragma message("[DEDICATED] pre-compiling headers.\n")
#define WIN32_LEAN_AND_MEAN // Prevent winsock2 redefinition.
#include <windows.h>
@ -27,8 +27,8 @@
#include "sinks/stdout_sinks.h"
#include "sinks/ostream_sink.h"
#include "utility.h"
//#include "httplib.h"
//#include "json.hpp"
#include "httplib.h"
#include "json.hpp"
#include "address.h"

View File

@ -185,7 +185,9 @@
<ItemGroup>
<ClCompile Include="..\shared\utility.cpp" />
<ClCompile Include="console.cpp" />
<ClCompile Include="csourceappsystemgroup.cpp" />
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="gameclasses.cpp" />
<ClCompile Include="hooks.cpp" />
<ClCompile Include="iconvar.cpp" />
<ClCompile Include="msgbox.cpp" />
@ -300,6 +302,8 @@
<ClInclude Include="..\shared\include\utility.h" />
<ClInclude Include="console.h" />
<ClInclude Include="dllmain.h" />
<ClInclude Include="enums.h" />
<ClInclude Include="gameclasses.h" />
<ClInclude Include="hooks.h" />
<ClInclude Include="opcodes.h" />
<ClInclude Include="pch.h" />

View File

@ -50,36 +50,36 @@
<Filter Include="shared\libraries\minhook\include">
<UniqueIdentifier>{485b5648-149f-4664-a961-be9cd520e9e3}</UniqueIdentifier>
</Filter>
<Filter Include="r5-sdk">
<UniqueIdentifier>{f5326cf2-826e-4499-98de-e818e096939d}</UniqueIdentifier>
</Filter>
<Filter Include="r5-sdk\include">
<UniqueIdentifier>{4c680991-cc41-4265-a6f3-b46d698bd72f}</UniqueIdentifier>
</Filter>
<Filter Include="r5-sdk\src">
<UniqueIdentifier>{8aac7eb6-9810-4fa2-bbfe-499fb2950f01}</UniqueIdentifier>
</Filter>
<Filter Include="hooks\src">
<UniqueIdentifier>{f28b1a49-9b41-48d2-9462-1674af3d72a2}</UniqueIdentifier>
</Filter>
<Filter Include="hooks\src\other">
<UniqueIdentifier>{cc424eef-0c7a-4fb0-9d84-30bf8db2e253}</UniqueIdentifier>
</Filter>
<Filter Include="hooks\src\squirrel">
<UniqueIdentifier>{74afa89f-72af-4e13-aa90-70f7a1957154}</UniqueIdentifier>
</Filter>
<Filter Include="hooks\src\netchannel">
<UniqueIdentifier>{05e6e9a7-801b-49b0-9c5a-21c4868befb7}</UniqueIdentifier>
</Filter>
<Filter Include="hooks\src\iconvar">
<UniqueIdentifier>{06affed3-5a59-4b95-88ca-72d92c91909b}</UniqueIdentifier>
</Filter>
<Filter Include="hooks\src\cvengineserver">
<UniqueIdentifier>{338a4fb7-7519-4628-9206-679d33824965}</UniqueIdentifier>
</Filter>
<Filter Include="hooks\include">
<UniqueIdentifier>{31cdde4d-3641-497c-9b34-20d3d7c89d87}</UniqueIdentifier>
</Filter>
<Filter Include="hooks\cvengineserver">
<UniqueIdentifier>{338a4fb7-7519-4628-9206-679d33824965}</UniqueIdentifier>
</Filter>
<Filter Include="hooks\iconvar">
<UniqueIdentifier>{06affed3-5a59-4b95-88ca-72d92c91909b}</UniqueIdentifier>
</Filter>
<Filter Include="hooks\netchannel">
<UniqueIdentifier>{05e6e9a7-801b-49b0-9c5a-21c4868befb7}</UniqueIdentifier>
</Filter>
<Filter Include="hooks\other">
<UniqueIdentifier>{cc424eef-0c7a-4fb0-9d84-30bf8db2e253}</UniqueIdentifier>
</Filter>
<Filter Include="hooks\squirrel">
<UniqueIdentifier>{74afa89f-72af-4e13-aa90-70f7a1957154}</UniqueIdentifier>
</Filter>
<Filter Include="hooks\csourceappsystemgroup">
<UniqueIdentifier>{9381fa63-cf89-4980-8e5a-bf6e43cb2283}</UniqueIdentifier>
</Filter>
<Filter Include="r5-sdk">
<UniqueIdentifier>{7fd080e8-390a-430b-a94c-e19c5792bf10}</UniqueIdentifier>
</Filter>
<Filter Include="r5-sdk\src">
<UniqueIdentifier>{e7e154b6-398e-42f9-bfb9-e80cd306254e}</UniqueIdentifier>
</Filter>
<Filter Include="r5-sdk\include">
<UniqueIdentifier>{3c89e0ef-e415-4a91-86b7-2a04a5f03340}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\shared\include\address.h">
@ -388,12 +388,18 @@
<ClInclude Include="..\external\minhook\include\MinHook.h">
<Filter>shared\libraries\minhook\include</Filter>
</ClInclude>
<ClInclude Include="opcodes.h">
<Filter>r5-sdk\include</Filter>
</ClInclude>
<ClInclude Include="hooks.h">
<Filter>hooks\include</Filter>
</ClInclude>
<ClInclude Include="opcodes.h">
<Filter>hooks\include</Filter>
</ClInclude>
<ClInclude Include="gameclasses.h">
<Filter>r5-sdk\include</Filter>
</ClInclude>
<ClInclude Include="enums.h">
<Filter>r5-sdk\include</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="console.cpp">
@ -406,28 +412,34 @@
<Filter>core</Filter>
</ClCompile>
<ClCompile Include="net.cpp">
<Filter>hooks\src\netchannel</Filter>
<Filter>hooks\netchannel</Filter>
</ClCompile>
<ClCompile Include="cvengineserver.cpp">
<Filter>hooks\src\cvengineserver</Filter>
<Filter>hooks\cvengineserver</Filter>
</ClCompile>
<ClCompile Include="sqvm.cpp">
<Filter>hooks\src\squirrel</Filter>
<Filter>hooks\squirrel</Filter>
</ClCompile>
<ClCompile Include="msgbox.cpp">
<Filter>hooks\src\other</Filter>
<Filter>hooks\other</Filter>
</ClCompile>
<ClCompile Include="..\shared\utility.cpp">
<Filter>shared</Filter>
</ClCompile>
<ClCompile Include="iconvar.cpp">
<Filter>hooks\src\iconvar</Filter>
<Filter>hooks\iconvar</Filter>
</ClCompile>
<ClCompile Include="opcodes.cpp">
<Filter>r5-sdk\src</Filter>
<Filter>hooks</Filter>
</ClCompile>
<ClCompile Include="hooks.cpp">
<Filter>hooks\src</Filter>
<Filter>hooks</Filter>
</ClCompile>
<ClCompile Include="csourceappsystemgroup.cpp">
<Filter>hooks\csourceappsystemgroup</Filter>
</ClCompile>
<ClCompile Include="gameclasses.cpp">
<Filter>r5-sdk\src</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>

View File

@ -1,5 +1,5 @@
#pragma once
#pragma message("Pre-compiling headers.\n")
#pragma message("[DEV] pre-compiling headers.\n")
#define WIN32_LEAN_AND_MEAN // Prevent winsock2 redefinition.
#include <windows.h>

View File

@ -1,4 +1,5 @@
#pragma once
#include "pch.h"
class BanList
{