Use premake.
This commit is contained in:
55
src/Components/Loader.cpp
Normal file
55
src/Components/Loader.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
#include "..\STDInclude.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
std::vector<Component*> Loader::Components;
|
||||
|
||||
void Loader::Initialize()
|
||||
{
|
||||
Loader::Register(new Dedicated());
|
||||
|
||||
Loader::Register(new Dvar());
|
||||
Loader::Register(new Maps());
|
||||
Loader::Register(new Menus());
|
||||
Loader::Register(new Party());
|
||||
Loader::Register(new Colors());
|
||||
Loader::Register(new Logger());
|
||||
Loader::Register(new Window());
|
||||
Loader::Register(new Command());
|
||||
Loader::Register(new Console());
|
||||
Loader::Register(new Network());
|
||||
Loader::Register(new RawFiles());
|
||||
Loader::Register(new Renderer());
|
||||
Loader::Register(new UIFeeder());
|
||||
Loader::Register(new UIScript());
|
||||
Loader::Register(new FastFiles());
|
||||
Loader::Register(new Materials());
|
||||
Loader::Register(new Singleton());
|
||||
Loader::Register(new FileSystem());
|
||||
Loader::Register(new QuickPatch());
|
||||
Loader::Register(new ServerList());
|
||||
Loader::Register(new AssetHandler());
|
||||
Loader::Register(new Localization());
|
||||
Loader::Register(new MusicalTalent());
|
||||
}
|
||||
|
||||
void Loader::Uninitialize()
|
||||
{
|
||||
for (auto component : Loader::Components)
|
||||
{
|
||||
Logger::Print("Unregistering component: %s", component->GetName());
|
||||
delete component;
|
||||
}
|
||||
|
||||
Loader::Components.clear();
|
||||
}
|
||||
|
||||
void Loader::Register(Component* component)
|
||||
{
|
||||
if (component)
|
||||
{
|
||||
Logger::Print("Component registered: %s", component->GetName());
|
||||
Loader::Components.push_back(component);
|
||||
}
|
||||
}
|
||||
}
|
46
src/Components/Loader.hpp
Normal file
46
src/Components/Loader.hpp
Normal file
@ -0,0 +1,46 @@
|
||||
namespace Components
|
||||
{
|
||||
class Component
|
||||
{
|
||||
public:
|
||||
Component() {};
|
||||
virtual ~Component() {};
|
||||
virtual const char* GetName() { return "Unknown"; };
|
||||
};
|
||||
|
||||
class Loader
|
||||
{
|
||||
public:
|
||||
static void Initialize();
|
||||
static void Uninitialize();
|
||||
static void Register(Component* component);
|
||||
|
||||
private:
|
||||
static std::vector<Component*> Components;
|
||||
};
|
||||
}
|
||||
|
||||
#include "Modules\Dvar.hpp"
|
||||
#include "Modules\Maps.hpp"
|
||||
#include "Modules\Menus.hpp"
|
||||
#include "Modules\Colors.hpp"
|
||||
#include "Modules\Logger.hpp"
|
||||
#include "Modules\Window.hpp"
|
||||
#include "Modules\Command.hpp"
|
||||
#include "Modules\Console.hpp"
|
||||
#include "Modules\Network.hpp"
|
||||
#include "Modules\Party.hpp" // Destroys the order, but requires network classes :D
|
||||
#include "Modules\RawFiles.hpp"
|
||||
#include "Modules\Renderer.hpp"
|
||||
#include "Modules\UIFeeder.hpp"
|
||||
#include "Modules\UIScript.hpp"
|
||||
#include "Modules\Dedicated.hpp"
|
||||
#include "Modules\FastFiles.hpp"
|
||||
#include "Modules\Materials.hpp"
|
||||
#include "Modules\Singleton.hpp"
|
||||
#include "Modules\FileSystem.hpp"
|
||||
#include "Modules\QuickPatch.hpp"
|
||||
#include "Modules\ServerList.hpp"
|
||||
#include "Modules\AssetHandler.hpp"
|
||||
#include "Modules\Localization.hpp"
|
||||
#include "Modules\MusicalTalent.hpp"
|
158
src/Components/Modules/AssetHandler.cpp
Normal file
158
src/Components/Modules/AssetHandler.cpp
Normal file
@ -0,0 +1,158 @@
|
||||
#include "..\..\STDInclude.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
bool AssetHandler::BypassState = false;
|
||||
std::map<Game::XAssetType, AssetHandler::Callback> AssetHandler::TypeCallbacks;
|
||||
std::vector<AssetHandler::RestrictCallback> AssetHandler::RestrictCallbacks;
|
||||
|
||||
std::map<void*, void*> AssetHandler::Relocations;
|
||||
|
||||
Game::XAssetHeader AssetHandler::FindAsset(Game::XAssetType type, const char* filename)
|
||||
{
|
||||
Game::XAssetHeader header = { 0 };
|
||||
|
||||
// Allow call DB_FindXAssetHeader within the hook
|
||||
AssetHandler::BypassState = true;
|
||||
|
||||
if (AssetHandler::TypeCallbacks.find(type) != AssetHandler::TypeCallbacks.end())
|
||||
{
|
||||
header = AssetHandler::TypeCallbacks[type](type, filename);
|
||||
}
|
||||
|
||||
// Disallow calling DB_FindXAssetHeader ;)
|
||||
AssetHandler::BypassState = false;
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
void __declspec(naked) AssetHandler::FindAssetStub()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
push ecx
|
||||
push ebx
|
||||
push ebp
|
||||
push esi
|
||||
push edi
|
||||
|
||||
// Check if custom handler should be bypassed
|
||||
xor eax, eax
|
||||
mov al, AssetHandler::BypassState
|
||||
|
||||
test al, al
|
||||
jnz finishOriginal
|
||||
|
||||
mov ecx, [esp + 18h] // Asset type
|
||||
mov ebx, [esp + 1Ch] // Filename
|
||||
|
||||
push ebx
|
||||
push ecx
|
||||
|
||||
call AssetHandler::FindAsset
|
||||
|
||||
add esp, 8h
|
||||
|
||||
test eax, eax
|
||||
jnz finishFound
|
||||
|
||||
finishOriginal:
|
||||
// Asset not found using custom handlers, redirect to DB_FindXAssetHeader
|
||||
mov ebx, ds:6D7190h // InterlockedDecrement
|
||||
mov eax, 40793Bh
|
||||
jmp eax
|
||||
|
||||
finishFound:
|
||||
pop edi
|
||||
pop esi
|
||||
pop ebp
|
||||
pop ebx
|
||||
pop ecx
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
bool AssetHandler::IsAssetEligible(Game::XAssetType type, Game::XAssetHeader *asset)
|
||||
{
|
||||
const char* name = Game::DB_GetXAssetNameHandlers[type](asset);
|
||||
if (!name) return false;
|
||||
|
||||
for (auto callback : AssetHandler::RestrictCallbacks)
|
||||
{
|
||||
if (!callback(type, *asset, name))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void __declspec(naked) AssetHandler::AddAssetStub()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
push [esp + 8]
|
||||
push [esp + 8]
|
||||
call AssetHandler::IsAssetEligible
|
||||
add esp, 08h
|
||||
|
||||
test al, al
|
||||
jz doNotLoad
|
||||
|
||||
mov eax, [esp + 8]
|
||||
sub esp, 14h
|
||||
mov ecx, 5BB657h
|
||||
jmp ecx
|
||||
|
||||
doNotLoad:
|
||||
mov eax, [esp + 8]
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
void AssetHandler::OnFind(Game::XAssetType type, AssetHandler::Callback callback)
|
||||
{
|
||||
AssetHandler::TypeCallbacks[type] = callback;
|
||||
}
|
||||
|
||||
void AssetHandler::OnLoad(RestrictCallback callback)
|
||||
{
|
||||
AssetHandler::RestrictCallbacks.push_back(callback);
|
||||
}
|
||||
|
||||
void AssetHandler::Relocate(void* start, void* to, DWORD size)
|
||||
{
|
||||
for (DWORD i = 0; i < size; i += 4)
|
||||
{
|
||||
AssetHandler::Relocations[reinterpret_cast<char*>(start) + i] = reinterpret_cast<char*>(to) + i;
|
||||
}
|
||||
}
|
||||
|
||||
void AssetHandler::OffsetToAlias(FastFiles::Offset* offset)
|
||||
{
|
||||
offset->fullPointer = *reinterpret_cast<void**>((*Game::g_streamBlocks)[offset->GetDecrementedStream()].data + offset->GetDecrementedPointer());
|
||||
|
||||
if (AssetHandler::Relocations.find(offset->fullPointer) != AssetHandler::Relocations.end())
|
||||
{
|
||||
offset->fullPointer = AssetHandler::Relocations[offset->fullPointer];
|
||||
}
|
||||
}
|
||||
|
||||
AssetHandler::AssetHandler()
|
||||
{
|
||||
// DB_FindXAssetHeader
|
||||
Utils::Hook(Game::DB_FindXAssetHeader, AssetHandler::FindAssetStub).Install()->Quick();
|
||||
|
||||
// DB_ConvertOffsetToAlias
|
||||
Utils::Hook(0x4FDFA0, AssetHandler::OffsetToAlias, HOOK_JUMP).Install()->Quick();
|
||||
|
||||
// DB_AddXAsset
|
||||
Utils::Hook(0x5BB650, AssetHandler::AddAssetStub, HOOK_JUMP).Install()->Quick();
|
||||
}
|
||||
|
||||
AssetHandler::~AssetHandler()
|
||||
{
|
||||
AssetHandler::TypeCallbacks.clear();
|
||||
}
|
||||
}
|
33
src/Components/Modules/AssetHandler.hpp
Normal file
33
src/Components/Modules/AssetHandler.hpp
Normal file
@ -0,0 +1,33 @@
|
||||
namespace Components
|
||||
{
|
||||
class AssetHandler : public Component
|
||||
{
|
||||
public:
|
||||
typedef Game::XAssetHeader(*Callback)(Game::XAssetType, const char*);
|
||||
typedef bool(*RestrictCallback)(Game::XAssetType type, Game::XAssetHeader asset, const char* name);
|
||||
|
||||
AssetHandler();
|
||||
~AssetHandler();
|
||||
const char* GetName() { return "AssetHandler"; };
|
||||
|
||||
static void OnFind(Game::XAssetType type, Callback callback);
|
||||
static void OnLoad(RestrictCallback callback);
|
||||
|
||||
static void Relocate(void* start, void* to, DWORD size = 4);
|
||||
|
||||
private:
|
||||
static bool BypassState;
|
||||
|
||||
static Game::XAssetHeader FindAsset(Game::XAssetType type, const char* filename);
|
||||
static bool IsAssetEligible(Game::XAssetType type, Game::XAssetHeader* asset);
|
||||
static void FindAssetStub();
|
||||
static void AddAssetStub();
|
||||
|
||||
static void OffsetToAlias(FastFiles::Offset* offset);
|
||||
|
||||
static std::map<Game::XAssetType, Callback> TypeCallbacks;
|
||||
static std::vector<RestrictCallback> RestrictCallbacks;
|
||||
|
||||
static std::map<void*, void*> Relocations;
|
||||
};
|
||||
}
|
112
src/Components/Modules/Colors.cpp
Normal file
112
src/Components/Modules/Colors.cpp
Normal file
@ -0,0 +1,112 @@
|
||||
#include "..\..\STDInclude.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
Dvar::Var Colors::NewColors;
|
||||
|
||||
void Colors::Strip(const char* in, char* out, int max)
|
||||
{
|
||||
max--;
|
||||
int current = 0;
|
||||
while (*in != 0 && current < max)
|
||||
{
|
||||
if (!Q_IsColorString(in))
|
||||
{
|
||||
*out = *in;
|
||||
out++;
|
||||
current++;
|
||||
}
|
||||
else
|
||||
{
|
||||
*in++;
|
||||
}
|
||||
*in++;
|
||||
}
|
||||
*out = '\0';
|
||||
}
|
||||
|
||||
void __declspec(naked) Colors::ClientUserinfoChanged(int length)
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov eax, [esp + 4h] // length
|
||||
sub eax, 1
|
||||
push eax
|
||||
|
||||
push ecx // name
|
||||
push edx // buffer
|
||||
|
||||
call strncpy
|
||||
|
||||
add esp, 0Ch
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
char* Colors::CL_GetClientName(int a1, int a2, char* buffer, size_t _length)
|
||||
{
|
||||
__asm
|
||||
{
|
||||
push _length
|
||||
push buffer
|
||||
push a2
|
||||
push a1
|
||||
mov eax, 4563D0h
|
||||
call eax
|
||||
add esp, 10h
|
||||
}
|
||||
|
||||
// Remove the colors
|
||||
char tempBuffer[100] = { 0 };
|
||||
Colors::Strip(buffer, tempBuffer, _length);
|
||||
strncpy(buffer, tempBuffer, _length);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void Colors::UpdateColorTable()
|
||||
{
|
||||
static int LastState = 2;
|
||||
static DWORD DefaultTable[8] = { 0 };
|
||||
DWORD* gColorTable = (DWORD*)0x78DC70;
|
||||
|
||||
if (LastState == 2)
|
||||
{
|
||||
memcpy(DefaultTable, gColorTable, sizeof(DefaultTable));
|
||||
}
|
||||
|
||||
if (Colors::NewColors.Get<bool>() && (0xF & (int)Colors::NewColors.Get<bool>()) != LastState)
|
||||
{
|
||||
// Apply NTA's W<> colors :3 (slightly modified though^^)
|
||||
gColorTable[1] = RGB(255, 49, 49);
|
||||
gColorTable[2] = RGB(134, 192, 0);
|
||||
gColorTable[3] = RGB(255, 173, 34);
|
||||
gColorTable[4] = RGB(0, 135, 193);
|
||||
gColorTable[5] = RGB(32, 197, 255);
|
||||
gColorTable[6] = RGB(151, 80, 221);
|
||||
|
||||
LastState = Colors::NewColors.Get<bool>();
|
||||
}
|
||||
else if (!Colors::NewColors.Get<bool>() && (0xF & (int)Colors::NewColors.Get<bool>()) != LastState)
|
||||
{
|
||||
memcpy(gColorTable, DefaultTable, sizeof(DefaultTable));
|
||||
|
||||
LastState = Colors::NewColors.Get<bool>();
|
||||
}
|
||||
}
|
||||
|
||||
Colors::Colors()
|
||||
{
|
||||
// Allow colored names ingame
|
||||
Utils::Hook(0x5D8B40, Colors::ClientUserinfoChanged, HOOK_JUMP).Install()->Quick();
|
||||
|
||||
// Though, don't apply that to overhead names.
|
||||
Utils::Hook(0x581932, Colors::CL_GetClientName, HOOK_CALL).Install()->Quick();
|
||||
|
||||
// Set frame handler
|
||||
Renderer::OnFrame(Colors::UpdateColorTable);
|
||||
|
||||
// Register dvar
|
||||
Colors::NewColors = Dvar::Register<bool>("cg_newColors", true, Game::dvar_flag::DVAR_FLAG_SAVED, "Use Warfare<72> color code style.");
|
||||
}
|
||||
}
|
20
src/Components/Modules/Colors.hpp
Normal file
20
src/Components/Modules/Colors.hpp
Normal file
@ -0,0 +1,20 @@
|
||||
#define Q_IsColorString( p ) ( ( p ) && *( p ) == '^' && *( ( p ) + 1 ) && isdigit( *( ( p ) + 1 ) ) ) // ^[0-9]
|
||||
|
||||
namespace Components
|
||||
{
|
||||
class Colors : public Component
|
||||
{
|
||||
public:
|
||||
Colors();
|
||||
const char* GetName() { return "Colors"; };
|
||||
|
||||
static Dvar::Var NewColors;
|
||||
|
||||
static void ClientUserinfoChanged(int length);
|
||||
static char* CL_GetClientName(int a1, int a2, char* buffer, size_t _length);
|
||||
|
||||
static void UpdateColorTable();
|
||||
|
||||
static void Strip(const char* in, char* out, int max);
|
||||
};
|
||||
}
|
77
src/Components/Modules/Command.cpp
Normal file
77
src/Components/Modules/Command.cpp
Normal file
@ -0,0 +1,77 @@
|
||||
#include "..\..\STDInclude.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
std::vector<Game::cmd_function_t*> Command::Functions;
|
||||
std::map<std::string, Command::Callback> Command::FunctionMap;
|
||||
|
||||
char* Command::Params::operator[](size_t index)
|
||||
{
|
||||
if (index >= this->Length())
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
return Game::cmd_argv[this->CommandId][index];
|
||||
}
|
||||
|
||||
size_t Command::Params::Length()
|
||||
{
|
||||
return Game::cmd_argc[this->CommandId];
|
||||
}
|
||||
|
||||
Command::~Command()
|
||||
{
|
||||
for (auto command : Command::Functions)
|
||||
{
|
||||
delete command;
|
||||
}
|
||||
|
||||
Command::Functions.clear();
|
||||
}
|
||||
|
||||
void Command::Add(const char* name, Command::Callback callback)
|
||||
{
|
||||
Command::FunctionMap[Utils::StrToLower(name)] = callback;
|
||||
Game::Cmd_AddCommand(name, Command::MainCallback, Command::Allocate(), 0);
|
||||
}
|
||||
|
||||
void Command::Execute(std::string command, bool sync)
|
||||
{
|
||||
command.append("\n"); // Make sure it's terminated
|
||||
|
||||
if (sync)
|
||||
{
|
||||
Game::Cmd_ExecuteSingleCommand(0, 0, command.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
Game::Cbuf_AddText(0, command.data());
|
||||
}
|
||||
}
|
||||
|
||||
Game::cmd_function_t* Command::Allocate()
|
||||
{
|
||||
Game::cmd_function_t* cmd = new Game::cmd_function_t;
|
||||
Command::Functions.push_back(cmd);
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
void Command::MainCallback()
|
||||
{
|
||||
Command::Params params(*Game::cmd_id);
|
||||
|
||||
std::string command = Utils::StrToLower(params[0]);
|
||||
|
||||
if (Command::FunctionMap.find(command) != Command::FunctionMap.end())
|
||||
{
|
||||
Command::FunctionMap[command](params);
|
||||
}
|
||||
}
|
||||
|
||||
Command::Command()
|
||||
{
|
||||
// TODO: Add commands here?
|
||||
}
|
||||
}
|
36
src/Components/Modules/Command.hpp
Normal file
36
src/Components/Modules/Command.hpp
Normal file
@ -0,0 +1,36 @@
|
||||
namespace Components
|
||||
{
|
||||
class Command : public Component
|
||||
{
|
||||
public:
|
||||
class Params
|
||||
{
|
||||
public:
|
||||
Params(DWORD id) : CommandId(id) {};
|
||||
Params(const Params &obj) { this->CommandId = obj.CommandId; };
|
||||
Params() : Params(*Game::cmd_id) {};
|
||||
|
||||
char* operator[](size_t index);
|
||||
size_t Length();
|
||||
|
||||
private:
|
||||
DWORD CommandId;
|
||||
};
|
||||
|
||||
typedef void(*Callback)(Command::Params params);
|
||||
|
||||
Command();
|
||||
~Command();
|
||||
const char* GetName() { return "Command"; };
|
||||
|
||||
static void Add(const char* name, Callback callback);
|
||||
|
||||
static void Execute(std::string command, bool sync = true);
|
||||
|
||||
private:
|
||||
static Game::cmd_function_t* Allocate();
|
||||
static std::vector<Game::cmd_function_t*> Functions;
|
||||
static std::map<std::string, Callback> FunctionMap;
|
||||
static void MainCallback();
|
||||
};
|
||||
}
|
38
src/Components/Modules/Console.cpp
Normal file
38
src/Components/Modules/Console.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
#include "..\..\STDInclude.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
char** Console::GetAutoCompleteFileList(const char *path, const char *extension, Game::FsListBehavior_e behavior, int *numfiles, int allocTrackType)
|
||||
{
|
||||
if (path == (char*)0xBAADF00D || IsBadReadPtr(path, 1)) return nullptr;
|
||||
return Game::FS_ListFiles(path, extension, behavior, numfiles, allocTrackType);
|
||||
}
|
||||
|
||||
void Console::ToggleConsole()
|
||||
{
|
||||
// possibly cls.keyCatchers?
|
||||
Utils::Hook::Xor<DWORD>(0xB2C538, 1);
|
||||
|
||||
// g_consoleField
|
||||
Game::Field_Clear((void*)0xA1B6B0);
|
||||
|
||||
// show console output?
|
||||
Utils::Hook::Set<BYTE>(0xA15F38, 0);
|
||||
}
|
||||
|
||||
Console::Console()
|
||||
{
|
||||
// External console
|
||||
Utils::Hook::Nop(0x60BB58, 11);
|
||||
|
||||
// Console '%s: %s> ' string
|
||||
Utils::Hook::Set<char*>(0x5A44B4, "IW4x > ");
|
||||
|
||||
// Internal console
|
||||
Utils::Hook(0x4F690C, Console::ToggleConsole, HOOK_CALL).Install()->Quick();
|
||||
Utils::Hook(0x4F65A5, Console::ToggleConsole, HOOK_JUMP).Install()->Quick();
|
||||
|
||||
// Check for bad food ;)
|
||||
Utils::Hook(0x4CB9F4, Console::GetAutoCompleteFileList, HOOK_CALL).Install()->Quick();
|
||||
}
|
||||
}
|
13
src/Components/Modules/Console.hpp
Normal file
13
src/Components/Modules/Console.hpp
Normal file
@ -0,0 +1,13 @@
|
||||
namespace Components
|
||||
{
|
||||
class Console : public Component
|
||||
{
|
||||
public:
|
||||
Console();
|
||||
const char* GetName() { return "Console"; };
|
||||
|
||||
private:
|
||||
static void ToggleConsole();
|
||||
static char** GetAutoCompleteFileList(const char *path, const char *extension, Game::FsListBehavior_e behavior, int *numfiles, int allocTrackType);
|
||||
};
|
||||
}
|
113
src/Components/Modules/Dedicated.cpp
Normal file
113
src/Components/Modules/Dedicated.cpp
Normal file
@ -0,0 +1,113 @@
|
||||
#include "..\..\STDInclude.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
Dvar::Var Dedicated::Dedi;
|
||||
|
||||
bool Dedicated::IsDedicated()
|
||||
{
|
||||
return (Dedicated::Dedi.Get<int>() != 0);
|
||||
}
|
||||
|
||||
void Dedicated::InitDedicatedServer()
|
||||
{
|
||||
const char* fastfiles[7] =
|
||||
{
|
||||
"code_post_gfx_mp",
|
||||
"localized_code_post_gfx_mp",
|
||||
"ui_mp",
|
||||
"localized_ui_mp",
|
||||
"common_mp",
|
||||
"localized_common_mp",
|
||||
"patch_mp"
|
||||
};
|
||||
|
||||
memcpy((void*)0x66E1CB0, &fastfiles, sizeof(fastfiles));
|
||||
Game::LoadInitialFF();
|
||||
|
||||
Utils::Hook::Call<void>(0x4F84C0);
|
||||
}
|
||||
|
||||
Dedicated::Dedicated()
|
||||
{
|
||||
Dedicated::Dedi = Dvar::Register<int>("dedicated", 0, 0, 2, Game::dvar_flag::DVAR_FLAG_SERVERINFO | Game::dvar_flag::DVAR_FLAG_WRITEPROTECTED, "Start as dedicated");
|
||||
|
||||
// TODO: Beautify!
|
||||
char* cmd = GetCommandLineA();
|
||||
char* value = strstr(cmd, " dedicated");
|
||||
|
||||
if (value)
|
||||
{
|
||||
value += 10;
|
||||
|
||||
while (*value == ' ' || *value == '"')
|
||||
value++;
|
||||
|
||||
char num[2] = { 0, 0 };
|
||||
num[0] = *value;
|
||||
|
||||
int dediVal = atoi(num);
|
||||
|
||||
if (dediVal && dediVal < 3)
|
||||
{
|
||||
Dedicated::Dedi.SetRaw(dediVal);
|
||||
}
|
||||
}
|
||||
|
||||
if (Dedicated::IsDedicated())
|
||||
{
|
||||
Utils::Hook(0x60BE98, Dedicated::InitDedicatedServer, HOOK_CALL).Install()->Quick();
|
||||
|
||||
Utils::Hook::Set<BYTE>(0x683370, 0xC3); // steam sometimes doesn't like the server
|
||||
|
||||
Utils::Hook::Set<BYTE>(0x5B4FF0, 0xC3); // self-registration on party
|
||||
Utils::Hook::Set<BYTE>(0x426130, 0xC3); // other party stuff?
|
||||
|
||||
Utils::Hook::Set<BYTE>(0x4D7030, 0xC3); // upnp stuff
|
||||
|
||||
Utils::Hook::Set<BYTE>(0x4B0FC3, 0x04); // make CL_Frame do client packets, even for game state 9
|
||||
Utils::Hook::Set<BYTE>(0x4F5090, 0xC3); // init sound system (1)
|
||||
Utils::Hook::Set<BYTE>(0x507B80, 0xC3); // start render thread
|
||||
Utils::Hook::Set<BYTE>(0x4F84C0, 0xC3); // R_Init caller
|
||||
Utils::Hook::Set<BYTE>(0x46A630, 0xC3); // init sound system (2)
|
||||
Utils::Hook::Set<BYTE>(0x41FDE0, 0xC3); // Com_Frame audio processor?
|
||||
Utils::Hook::Set<BYTE>(0x41B9F0, 0xC3); // called from Com_Frame, seems to do renderer stuff
|
||||
Utils::Hook::Set<BYTE>(0x41D010, 0xC3); // CL_CheckForResend, which tries to connect to the local server constantly
|
||||
Utils::Hook::Set<BYTE>(0x62B6C0, 0xC3); // UI expression 'DebugPrint', mainly to prevent some console spam
|
||||
|
||||
Utils::Hook::Set<BYTE>(0x468960, 0xC3); // some mixer-related function called on shutdown
|
||||
Utils::Hook::Set<BYTE>(0x60AD90, 0); // masterServerName flags
|
||||
|
||||
Utils::Hook::Nop(0x4DCEC9, 2); // some check preventing proper game functioning
|
||||
Utils::Hook::Nop(0x507C79, 6); // another similar bsp check
|
||||
Utils::Hook::Nop(0x414E4D, 6); // unknown check in SV_ExecuteClientMessage (0x20F0890 == 0, related to client->f_40)
|
||||
Utils::Hook::Nop(0x4DCEE9, 5); // some deinit renderer function
|
||||
Utils::Hook::Nop(0x59A896, 5); // warning message on a removed subsystem
|
||||
Utils::Hook::Nop(0x4B4EEF, 5); // same as above
|
||||
Utils::Hook::Nop(0x64CF77, 5); // function detecting video card, causes Direct3DCreate9 to be called
|
||||
Utils::Hook::Nop(0x60BC52, 0x15); // recommended settings check
|
||||
|
||||
// isHost script call return 0
|
||||
Utils::Hook::Set<DWORD>(0x5DEC04, 0);
|
||||
|
||||
// map_rotate func
|
||||
//*(DWORD*)0x4152E8 = (DWORD)SV_MapRotate_f;
|
||||
|
||||
// sv_network_fps max 1000, and uncheat
|
||||
Utils::Hook::Set<BYTE>(0x4D3C67, 0); // ?
|
||||
Utils::Hook::Set<DWORD>(0x4D3C69, 1000);
|
||||
|
||||
// r_loadForRenderer default to 0
|
||||
Utils::Hook::Set<BYTE>(0x519DDF, 0);
|
||||
|
||||
// disable cheat protection on onlinegame
|
||||
Utils::Hook::Set<BYTE>(0x404CF7, 0x80);
|
||||
|
||||
// some d3d9 call on error
|
||||
Utils::Hook::Set<BYTE>(0x508470, 0xC3);
|
||||
|
||||
// stop saving a config_mp.cfg
|
||||
Utils::Hook::Set<BYTE>(0x60B240, 0xC3);
|
||||
}
|
||||
}
|
||||
}
|
16
src/Components/Modules/Dedicated.hpp
Normal file
16
src/Components/Modules/Dedicated.hpp
Normal file
@ -0,0 +1,16 @@
|
||||
namespace Components
|
||||
{
|
||||
class Dedicated : public Component
|
||||
{
|
||||
public:
|
||||
Dedicated();
|
||||
const char* GetName() { return "Dedicated"; };
|
||||
|
||||
static bool IsDedicated();
|
||||
|
||||
private:
|
||||
static Dvar::Var Dedi;
|
||||
|
||||
static void InitDedicatedServer();
|
||||
};
|
||||
}
|
149
src/Components/Modules/Dvar.cpp
Normal file
149
src/Components/Modules/Dvar.cpp
Normal file
@ -0,0 +1,149 @@
|
||||
#include "..\..\STDInclude.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
Dvar::Var::Var(std::string dvarName) : Var()
|
||||
{
|
||||
this->dvar = Game::Dvar_FindVar(dvarName.data());
|
||||
|
||||
if (!this->dvar)
|
||||
{
|
||||
// Quick-register the dvar
|
||||
Game::SetConsole(dvarName.data(), "");
|
||||
this->dvar = Game::Dvar_FindVar(dvarName.data());
|
||||
}
|
||||
}
|
||||
|
||||
template <> Game::dvar_t* Dvar::Var::Get()
|
||||
{
|
||||
return this->dvar;
|
||||
}
|
||||
template <> char* Dvar::Var::Get()
|
||||
{
|
||||
if (this->dvar && this->dvar->type == Game::dvar_type::DVAR_TYPE_STRING && this->dvar->current.string)
|
||||
{
|
||||
return this->dvar->current.string;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
template <> const char* Dvar::Var::Get()
|
||||
{
|
||||
return this->Get<char*>();
|
||||
}
|
||||
template <> int Dvar::Var::Get()
|
||||
{
|
||||
if (this->dvar && this->dvar->type == Game::dvar_type::DVAR_TYPE_INT)
|
||||
{
|
||||
return this->dvar->current.integer;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
template <> float Dvar::Var::Get()
|
||||
{
|
||||
if (this->dvar && this->dvar->type == Game::dvar_type::DVAR_TYPE_FLOAT)
|
||||
{
|
||||
return this->dvar->current.value;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
template <> float* Dvar::Var::Get()
|
||||
{
|
||||
static float val[4] = { 0 };
|
||||
|
||||
if (this->dvar && (this->dvar->type == Game::dvar_type::DVAR_TYPE_FLOAT_2 || this->dvar->type == Game::dvar_type::DVAR_TYPE_FLOAT_3 || this->dvar->type == Game::dvar_type::DVAR_TYPE_FLOAT_4))
|
||||
{
|
||||
return this->dvar->current.vec4;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
template <> bool Dvar::Var::Get()
|
||||
{
|
||||
if (this->dvar && this->dvar->type == Game::dvar_type::DVAR_TYPE_BOOL)
|
||||
{
|
||||
return this->dvar->current.boolean;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Dvar::Var::Set(char* string)
|
||||
{
|
||||
this->Set(reinterpret_cast<const char*>(string));
|
||||
}
|
||||
void Dvar::Var::Set(const char* string)
|
||||
{
|
||||
if (this->dvar && this->dvar->name)
|
||||
{
|
||||
Game::Dvar_SetCommand(this->dvar->name, string);
|
||||
}
|
||||
}
|
||||
void Dvar::Var::Set(std::string string)
|
||||
{
|
||||
this->Set(string.data());
|
||||
}
|
||||
void Dvar::Var::Set(int integer)
|
||||
{
|
||||
if (this->dvar && this->dvar->name)
|
||||
{
|
||||
Game::Dvar_SetCommand(this->dvar->name, Utils::VA("%i", integer));
|
||||
}
|
||||
}
|
||||
void Dvar::Var::Set(float value)
|
||||
{
|
||||
if (this->dvar && this->dvar->name)
|
||||
{
|
||||
Game::Dvar_SetCommand(this->dvar->name, Utils::VA("%f", value));
|
||||
}
|
||||
}
|
||||
|
||||
void Dvar::Var::SetRaw(int integer)
|
||||
{
|
||||
if (this->dvar)
|
||||
{
|
||||
this->dvar->current.integer = integer;
|
||||
}
|
||||
}
|
||||
|
||||
template<> static Dvar::Var Dvar::Register(const char* name, bool value, Dvar::Flag flag, const char* description)
|
||||
{
|
||||
return Game::Dvar_RegisterBool(name, value, flag.val, description);
|
||||
}
|
||||
template<> static Dvar::Var Dvar::Register(const char* name, const char* value, Dvar::Flag flag, const char* description)
|
||||
{
|
||||
return Game::Dvar_RegisterString(name, value, flag.val, description);
|
||||
}
|
||||
template<> static Dvar::Var Dvar::Register(const char* name, int value, int min, int max, Dvar::Flag flag, const char* description)
|
||||
{
|
||||
return Game::Dvar_RegisterInt(name, value, min, max, flag.val, description);
|
||||
}
|
||||
|
||||
Game::dvar_t* Dvar::RegisterName(const char* name, const char* default, Game::dvar_flag flag, const char* description)
|
||||
{
|
||||
// TODO: Register string dvars here
|
||||
|
||||
return Dvar::Register<const char*>(name, "Unknown Soldier", Dvar::Flag(flag | Game::dvar_flag::DVAR_FLAG_SAVED).val, description).Get<Game::dvar_t*>();
|
||||
}
|
||||
|
||||
Dvar::Dvar()
|
||||
{
|
||||
// set flags of cg_drawFPS to archive
|
||||
Utils::Hook::Or<BYTE>(0x4F8F69, Game::dvar_flag::DVAR_FLAG_SAVED);
|
||||
|
||||
// un-cheat cg_fov and add archive flags
|
||||
Utils::Hook::Xor<BYTE>(0x4F8E35, Game::dvar_flag::DVAR_FLAG_CHEAT | Game::dvar_flag::DVAR_FLAG_SAVED);
|
||||
|
||||
// set flags of cg_drawFPS to archive
|
||||
Utils::Hook::Or<BYTE>(0x4F8F69, Game::dvar_flag::DVAR_FLAG_SAVED);
|
||||
|
||||
// set cg_fov max to 90.0
|
||||
static float cgFov90 = 90.0f;
|
||||
Utils::Hook::Set<float*>(0x4F8E28, &cgFov90);
|
||||
|
||||
// Hook dvar 'name' registration
|
||||
Utils::Hook(0x40531C, Dvar::RegisterName, HOOK_CALL).Install()->Quick();
|
||||
}
|
||||
}
|
49
src/Components/Modules/Dvar.hpp
Normal file
49
src/Components/Modules/Dvar.hpp
Normal file
@ -0,0 +1,49 @@
|
||||
namespace Components
|
||||
{
|
||||
class Dvar : public Component
|
||||
{
|
||||
public:
|
||||
struct Flag
|
||||
{
|
||||
Flag(Game::dvar_flag flag) : val(flag){};
|
||||
Flag(int flag) : Flag((Game::dvar_flag)flag) {};
|
||||
|
||||
Game::dvar_flag val;
|
||||
};
|
||||
|
||||
class Var
|
||||
{
|
||||
public:
|
||||
Var() : dvar(0) {};
|
||||
Var(const Var &obj) { this->dvar = obj.dvar; };
|
||||
Var(Game::dvar_t* _dvar) : dvar(_dvar) {};
|
||||
Var(std::string dvarName);
|
||||
Var(std::string dvarName, std::string value);
|
||||
|
||||
template<typename T> T Get();
|
||||
|
||||
void Set(char* string);
|
||||
void Set(const char* string);
|
||||
void Set(std::string string);
|
||||
|
||||
void Set(int integer);
|
||||
void Set(float value);
|
||||
|
||||
// TODO: Add others
|
||||
void SetRaw(int integer);
|
||||
|
||||
private:
|
||||
Game::dvar_t* dvar;
|
||||
};
|
||||
|
||||
Dvar();
|
||||
const char* GetName() { return "Dvar"; };
|
||||
|
||||
// Only strings and bools use this type of declaration
|
||||
template<typename T> static Var Register(const char* name, T value, Flag flag, const char* description);
|
||||
template<typename T> static Var Register(const char* name, T value, T min, T max, Flag flag, const char* description);
|
||||
|
||||
private:
|
||||
static Game::dvar_t* RegisterName(const char* name, const char* default, Game::dvar_flag flag, const char* description);
|
||||
};
|
||||
}
|
107
src/Components/Modules/FastFiles.cpp
Normal file
107
src/Components/Modules/FastFiles.cpp
Normal file
@ -0,0 +1,107 @@
|
||||
#include "..\..\STDInclude.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
std::vector<std::string> FastFiles::ZonePaths;
|
||||
|
||||
void FastFiles::LoadDLCUIZones(Game::XZoneInfo *zoneInfo, unsigned int zoneCount, int sync)
|
||||
{
|
||||
Game::XZoneInfo* data = new Game::XZoneInfo[zoneCount + 2];
|
||||
memcpy(data, zoneInfo, sizeof(Game::XZoneInfo) * zoneCount);
|
||||
|
||||
data[zoneCount].name = "dlc1_ui_mp";
|
||||
data[zoneCount].allocFlags = 2;
|
||||
data[zoneCount].freeFlags = 0;
|
||||
zoneCount++;
|
||||
|
||||
data[zoneCount].name = "dlc2_ui_mp";
|
||||
data[zoneCount].allocFlags = 2;
|
||||
data[zoneCount].freeFlags = 0;
|
||||
zoneCount++;
|
||||
|
||||
Game::DB_LoadXAssets(data, zoneCount, sync);
|
||||
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
const char* FastFiles::GetZoneLocation(const char* file)
|
||||
{
|
||||
const char* dir = Dvar::Var("fs_basepath").Get<const char*>();
|
||||
|
||||
for (auto &path : FastFiles::ZonePaths)
|
||||
{
|
||||
std::string absoluteFile = Utils::VA("%s\\%s%s", dir, path.data(), file);
|
||||
|
||||
// No ".ff" appended, append it manually
|
||||
if (!Utils::EndsWith(file, ".ff"))
|
||||
{
|
||||
absoluteFile.append(".ff");
|
||||
}
|
||||
|
||||
// Check if FastFile exists
|
||||
if (GetFileAttributes(absoluteFile.data()) != INVALID_FILE_ATTRIBUTES)
|
||||
{
|
||||
return Utils::VA("%s", path.data());
|
||||
}
|
||||
}
|
||||
|
||||
return Utils::VA("zone\\%s\\", Game::Win_GetLanguage());
|
||||
}
|
||||
|
||||
void FastFiles::AddZonePath(std::string path)
|
||||
{
|
||||
FastFiles::ZonePaths.push_back(path);
|
||||
}
|
||||
|
||||
std::string FastFiles::Current()
|
||||
{
|
||||
const char* file = (Utils::Hook::Get<char*>(0x112A680) + 4);
|
||||
|
||||
if ((int)file == 4)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
FastFiles::FastFiles()
|
||||
{
|
||||
// Redirect zone paths
|
||||
Utils::Hook(0x44DA90, FastFiles::GetZoneLocation, HOOK_JUMP).Install()->Quick();
|
||||
|
||||
// Allow dlc ui zone loading
|
||||
Utils::Hook(0x506BC7, FastFiles::LoadDLCUIZones, HOOK_CALL).Install()->Quick();
|
||||
Utils::Hook(0x60B4AC, FastFiles::LoadDLCUIZones, HOOK_CALL).Install()->Quick();
|
||||
|
||||
// basic checks (hash jumps, both normal and playlist)
|
||||
Utils::Hook::Nop(0x5B97A3, 2);
|
||||
Utils::Hook::Nop(0x5BA493, 2);
|
||||
|
||||
Utils::Hook::Nop(0x5B991C, 2);
|
||||
Utils::Hook::Nop(0x5BA60C, 2);
|
||||
|
||||
Utils::Hook::Nop(0x5B97B4, 2);
|
||||
Utils::Hook::Nop(0x5BA4A4, 2);
|
||||
|
||||
// allow loading of IWffu (unsigned) files
|
||||
Utils::Hook::Set<BYTE>(0x4158D9, 0xEB); // main function
|
||||
Utils::Hook::Nop(0x4A1D97, 2); // DB_AuthLoad_InflateInit
|
||||
|
||||
// some other, unknown, check
|
||||
Utils::Hook::Set<BYTE>(0x5B9912, 0xB8);
|
||||
Utils::Hook::Set<DWORD>(0x5B9913, 1);
|
||||
|
||||
Utils::Hook::Set<BYTE>(0x5BA602, 0xB8);
|
||||
Utils::Hook::Set<DWORD>(0x5BA603, 1);
|
||||
|
||||
// Add custom zone paths
|
||||
FastFiles::AddZonePath("zone\\patch\\");
|
||||
FastFiles::AddZonePath("zone\\dlc\\");
|
||||
}
|
||||
|
||||
FastFiles::~FastFiles()
|
||||
{
|
||||
FastFiles::ZonePaths.clear();
|
||||
}
|
||||
}
|
48
src/Components/Modules/FastFiles.hpp
Normal file
48
src/Components/Modules/FastFiles.hpp
Normal file
@ -0,0 +1,48 @@
|
||||
namespace Components
|
||||
{
|
||||
class FastFiles : public Component
|
||||
{
|
||||
public:
|
||||
|
||||
class Offset
|
||||
{
|
||||
public:
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint32_t pointer : 28;
|
||||
int stream : 4;
|
||||
};
|
||||
uint32_t fullValue;
|
||||
void* fullPointer;
|
||||
};
|
||||
|
||||
uint32_t GetDecrementedPointer()
|
||||
{
|
||||
Offset offset = *this;
|
||||
offset.fullValue--;
|
||||
return offset.pointer;
|
||||
};
|
||||
|
||||
int GetDecrementedStream()
|
||||
{
|
||||
Offset offset = *this;
|
||||
offset.fullValue--;
|
||||
return offset.stream;
|
||||
};
|
||||
};
|
||||
|
||||
FastFiles();
|
||||
~FastFiles();
|
||||
const char* GetName() { return "FastFiles"; };
|
||||
|
||||
static void AddZonePath(std::string path);
|
||||
static std::string Current();
|
||||
|
||||
private:
|
||||
static std::vector<std::string> ZonePaths;
|
||||
static const char* GetZoneLocation(const char* file);
|
||||
static void LoadDLCUIZones(Game::XZoneInfo *zoneInfo, unsigned int zoneCount, int sync);
|
||||
};
|
||||
}
|
30
src/Components/Modules/FileSystem.cpp
Normal file
30
src/Components/Modules/FileSystem.cpp
Normal file
@ -0,0 +1,30 @@
|
||||
#include "..\..\STDInclude.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
void FileSystem::File::Read()
|
||||
{
|
||||
char* buffer = nullptr;
|
||||
int size = Game::FS_ReadFile(this->FilePath.data(), &buffer);
|
||||
|
||||
this->Buffer.clear();
|
||||
|
||||
if (size < 0)
|
||||
{
|
||||
if (buffer)
|
||||
{
|
||||
Game::FS_FreeFile(buffer);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this->Buffer.append(buffer, size);
|
||||
Game::FS_FreeFile(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
FileSystem::FileSystem()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
27
src/Components/Modules/FileSystem.hpp
Normal file
27
src/Components/Modules/FileSystem.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
namespace Components
|
||||
{
|
||||
class FileSystem : public Component
|
||||
{
|
||||
public:
|
||||
|
||||
class File
|
||||
{
|
||||
public:
|
||||
//File() {};
|
||||
File(std::string file) : FilePath(file) { this->Read(); };
|
||||
|
||||
bool Exists() { return this->Buffer.size() > 0; };
|
||||
std::string GetName() { return this->FilePath; };
|
||||
std::string& GetBuffer() { return this->Buffer; };
|
||||
|
||||
private:
|
||||
std::string FilePath;
|
||||
std::string Buffer;
|
||||
|
||||
void Read();
|
||||
};
|
||||
|
||||
FileSystem();
|
||||
const char* GetName() { return "FileSystem"; };
|
||||
};
|
||||
}
|
44
src/Components/Modules/Localization.cpp
Normal file
44
src/Components/Modules/Localization.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
#include "..\..\STDInclude.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
Dvar::Var Localization::UseLocalization;
|
||||
std::map<std::string, std::string> Localization::LocalizeMap;
|
||||
|
||||
void Localization::Set(const char* key, const char* value)
|
||||
{
|
||||
Localization::LocalizeMap[key] = value;
|
||||
}
|
||||
|
||||
const char* Localization::Get(const char* key)
|
||||
{
|
||||
if (!Localization::UseLocalization.Get<bool>()) return key;
|
||||
|
||||
if (Localization::LocalizeMap.find(key) != Localization::LocalizeMap.end())
|
||||
{
|
||||
return Localization::LocalizeMap[key].data();
|
||||
}
|
||||
|
||||
Game::localizedEntry_s* entry = Game::DB_FindXAssetHeader(Game::XAssetType::ASSET_TYPE_LOCALIZE, key).localize;
|
||||
|
||||
if (entry)
|
||||
{
|
||||
return entry->value;
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
Localization::Localization()
|
||||
{
|
||||
Utils::Hook(0x629B90, Localization::Get, HOOK_JUMP).Install()->Quick();
|
||||
|
||||
//Localization::Set("MENU_MULTIPLAYER_CAPS", "^5Fotze");
|
||||
Localization::UseLocalization = Dvar::Register<bool>("ui_localize", true, Game::dvar_flag::DVAR_FLAG_NONE, "Use localization strings");
|
||||
}
|
||||
|
||||
Localization::~Localization()
|
||||
{
|
||||
Localization::LocalizeMap.clear();
|
||||
}
|
||||
}
|
17
src/Components/Modules/Localization.hpp
Normal file
17
src/Components/Modules/Localization.hpp
Normal file
@ -0,0 +1,17 @@
|
||||
namespace Components
|
||||
{
|
||||
class Localization : public Component
|
||||
{
|
||||
public:
|
||||
Localization();
|
||||
~Localization();
|
||||
const char* GetName() { return "Localization"; };
|
||||
|
||||
static void Set(const char* key, const char* value);
|
||||
static const char* Get(const char* key);
|
||||
|
||||
private:
|
||||
static std::map<std::string, std::string> LocalizeMap;
|
||||
static Dvar::Var UseLocalization;
|
||||
};
|
||||
}
|
57
src/Components/Modules/Logger.cpp
Normal file
57
src/Components/Modules/Logger.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
#include "..\..\STDInclude.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
bool Logger::IsConsoleReady()
|
||||
{
|
||||
return (IsWindow(*(HWND*)0x64A3288) != FALSE);
|
||||
}
|
||||
|
||||
void Logger::Print(const char* message, ...)
|
||||
{
|
||||
char buffer[0x1000] = { 0 };
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, message);
|
||||
vsprintf_s(buffer, message, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (Logger::IsConsoleReady())
|
||||
{
|
||||
Game::Com_Printf(0, "%s", buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
OutputDebugStringA(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::Error(const char* message, ...)
|
||||
{
|
||||
char buffer[0x1000] = { 0 };
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, message);
|
||||
vsprintf_s(buffer, message, ap);
|
||||
va_end(ap);
|
||||
|
||||
Game::Com_Error(0, "%s", buffer);
|
||||
}
|
||||
|
||||
void Logger::SoftError(const char* message, ...)
|
||||
{
|
||||
char buffer[0x1000] = { 0 };
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, message);
|
||||
vsprintf_s(buffer, message, ap);
|
||||
va_end(ap);
|
||||
|
||||
Game::Com_Error(2, "%s", buffer);
|
||||
}
|
||||
|
||||
Logger::Logger()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
14
src/Components/Modules/Logger.hpp
Normal file
14
src/Components/Modules/Logger.hpp
Normal file
@ -0,0 +1,14 @@
|
||||
namespace Components
|
||||
{
|
||||
class Logger : public Component
|
||||
{
|
||||
public:
|
||||
Logger();
|
||||
const char* GetName() { return "Logger"; };
|
||||
|
||||
static void Print(const char* message, ...);
|
||||
static void Error(const char* message, ...);
|
||||
static void SoftError(const char* message, ...);
|
||||
static bool IsConsoleReady();
|
||||
};
|
||||
}
|
183
src/Components/Modules/Maps.cpp
Normal file
183
src/Components/Modules/Maps.cpp
Normal file
@ -0,0 +1,183 @@
|
||||
#include "..\..\STDInclude.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
void* Maps::WorldMP = 0;
|
||||
void* Maps::WorldSP = 0;
|
||||
|
||||
std::map<std::string, std::string> Maps::DependencyList;
|
||||
std::vector<std::string> Maps::CurrentDependencies;
|
||||
|
||||
std::vector<Game::XAssetEntry> Maps::EntryPool;
|
||||
|
||||
void Maps::LoadMapZones(Game::XZoneInfo *zoneInfo, unsigned int zoneCount, int sync)
|
||||
{
|
||||
Maps::CurrentDependencies.clear();
|
||||
for (auto i = Maps::DependencyList.begin(); i != Maps::DependencyList.end(); i++)
|
||||
{
|
||||
if (std::regex_match(zoneInfo->name, std::regex(i->first)))
|
||||
{
|
||||
if (std::find(Maps::CurrentDependencies.begin(), Maps::CurrentDependencies.end(), i->second) == Maps::CurrentDependencies.end())
|
||||
{
|
||||
Maps::CurrentDependencies.push_back(i->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Game::XZoneInfo* data = new Game::XZoneInfo[zoneCount + Maps::CurrentDependencies.size()];
|
||||
memcpy(data, zoneInfo, sizeof(Game::XZoneInfo) * zoneCount);
|
||||
|
||||
for (unsigned int i = 0; i < Maps::CurrentDependencies.size(); i++)
|
||||
{
|
||||
data[zoneCount + i].name = (&Maps::CurrentDependencies[i])->data();
|
||||
data[zoneCount + i].allocFlags = data->allocFlags;
|
||||
data[zoneCount + i].freeFlags = data->freeFlags;
|
||||
}
|
||||
|
||||
Game::DB_LoadXAssets(data, zoneCount + Maps::CurrentDependencies.size(), sync);
|
||||
|
||||
delete[] data;
|
||||
}
|
||||
|
||||
bool Maps::LoadAssetRestrict(Game::XAssetType type, Game::XAssetHeader asset, const char* name)
|
||||
{
|
||||
if (std::find(Maps::CurrentDependencies.begin(), Maps::CurrentDependencies.end(), FastFiles::Current()) != Maps::CurrentDependencies.end())
|
||||
{
|
||||
if (type == Game::XAssetType::ASSET_TYPE_GAME_MAP_MP || type == Game::XAssetType::ASSET_TYPE_COL_MAP_MP || type == Game::XAssetType::ASSET_TYPE_GFX_MAP || type == Game::XAssetType::ASSET_TYPE_MAP_ENTS || type == Game::XAssetType::ASSET_TYPE_COM_MAP || type == Game::XAssetType::ASSET_TYPE_FX_MAP)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (type == Game::XAssetType::ASSET_TYPE_MAP_ENTS)
|
||||
{
|
||||
static std::string mapEntities;
|
||||
FileSystem::File ents(Utils::VA("%s.ents", name));
|
||||
if (ents.Exists())
|
||||
{
|
||||
mapEntities = ents.GetBuffer();
|
||||
asset.mapEnts->entitystring = mapEntities.data();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Maps::GetBSPName(char* buffer, size_t size, const char* format, const char* mapname)
|
||||
{
|
||||
if (_strnicmp("mp_", mapname, 3))
|
||||
{
|
||||
format = "maps/%s.d3dbsp";
|
||||
|
||||
// Adjust pointer to GameMap_Data
|
||||
Utils::Hook::Set<void*>(0x4D90B7, Maps::WorldSP);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Adjust pointer to GameMap_Data
|
||||
Utils::Hook::Set<void*>(0x4D90B7, Maps::WorldMP);
|
||||
}
|
||||
|
||||
_snprintf(buffer, size, format, mapname);
|
||||
}
|
||||
|
||||
void Maps::AddDependency(std::string expression, std::string zone)
|
||||
{
|
||||
// Test expression before adding it
|
||||
try
|
||||
{
|
||||
std::regex _(expression);
|
||||
}
|
||||
catch (std::exception e)
|
||||
{
|
||||
MessageBoxA(0, Utils::VA("Invalid regular expression: %s", expression.data()), "Warning", MB_ICONEXCLAMATION);
|
||||
return;
|
||||
}
|
||||
|
||||
Maps::DependencyList[expression] = zone;
|
||||
}
|
||||
|
||||
void Maps::ReallocateEntryPool()
|
||||
{
|
||||
static_assert(sizeof(Game::XAssetEntry) == 16, "XAssetEntry size mismatch");
|
||||
|
||||
Maps::EntryPool.clear();
|
||||
Maps::EntryPool.resize(789312);
|
||||
|
||||
// Apply new size
|
||||
Utils::Hook::Set<DWORD>(0x5BAEB0, Maps::EntryPool.size());
|
||||
|
||||
// Apply new pool
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x48E6F4, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x4C67E4, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x4C8584, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BAEA8, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BB0C4, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BB0F5, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BB1D4, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BB235, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BB278, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BB34C, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BB484, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BB570, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BB6B7, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BB844, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BB98D, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BBA66, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BBB8D, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BBCB1, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BBD9B, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BBE4C, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BBF14, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BBF54, Maps::EntryPool.data());
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BBFB8, Maps::EntryPool.data());
|
||||
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BAE91, Maps::EntryPool.data() + 1);
|
||||
Utils::Hook::Set<Game::XAssetEntry*>(0x5BAEA2, Maps::EntryPool.data() + 1);
|
||||
}
|
||||
|
||||
Maps::Maps()
|
||||
{
|
||||
// Restrict asset loading
|
||||
AssetHandler::OnLoad(Maps::LoadAssetRestrict);
|
||||
|
||||
// hunk size (was 300 MiB)
|
||||
Utils::Hook::Set<DWORD>(0x64A029, 0x1C200000); // 450 MiB
|
||||
Utils::Hook::Set<DWORD>(0x64A057, 0x1C200000);
|
||||
|
||||
// Intercept BSP name resolving
|
||||
Utils::Hook(0x4C5979, Maps::GetBSPName, HOOK_CALL).Install()->Quick();
|
||||
|
||||
// Intercept map zone loading
|
||||
Utils::Hook(0x42C2AF, Maps::LoadMapZones, HOOK_CALL).Install()->Quick();
|
||||
|
||||
Maps::WorldSP = reinterpret_cast<char*>(Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_GAME_MAP_SP, 1)) + 52; // Skip name and other padding to reach world data
|
||||
Maps::WorldMP = Utils::Hook::Get<char*>(0x4D90B7);
|
||||
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_IMAGE, 7168);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_LOADED_SOUND, 2700);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_FX, 1200);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_LOCALIZE, 14000);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_XANIM, 8192);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_XMODEL, 5125);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_PHYSPRESET, 128);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_PIXELSHADER, 10000);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_VERTEXSHADER, 3072);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_MATERIAL, 8192);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_VERTEXDECL, 196);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_WEAPON, 2400);
|
||||
Game::ReallocateAssetPool(Game::XAssetType::ASSET_TYPE_STRINGTABLE, 800);
|
||||
|
||||
Maps::ReallocateEntryPool();
|
||||
|
||||
// Dependencies
|
||||
Maps::AddDependency("oilrig", "mp_subbase");
|
||||
Maps::AddDependency("gulag", "mp_subbase");
|
||||
Maps::AddDependency("^(?!mp_).*", "mp_subbase"); // All maps not starting with "mp_"
|
||||
}
|
||||
|
||||
Maps::~Maps()
|
||||
{
|
||||
Maps::EntryPool.clear();
|
||||
}
|
||||
}
|
27
src/Components/Modules/Maps.hpp
Normal file
27
src/Components/Modules/Maps.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
namespace Components
|
||||
{
|
||||
class Maps : public Component
|
||||
{
|
||||
public:
|
||||
Maps();
|
||||
~Maps();
|
||||
const char* GetName() { return "Maps"; };
|
||||
|
||||
static void AddDependency(std::string expression, std::string zone);
|
||||
|
||||
private:
|
||||
static void* WorldMP;
|
||||
static void* WorldSP;
|
||||
|
||||
static std::vector<Game::XAssetEntry> EntryPool;
|
||||
|
||||
static std::map<std::string, std::string> DependencyList;
|
||||
static std::vector<std::string> CurrentDependencies;
|
||||
|
||||
static void GetBSPName(char* buffer, size_t size, const char* format, const char* mapname);
|
||||
static bool LoadAssetRestrict(Game::XAssetType type, Game::XAssetHeader asset, const char* name);
|
||||
static void LoadMapZones(Game::XZoneInfo *zoneInfo, unsigned int zoneCount, int sync);
|
||||
|
||||
void ReallocateEntryPool();
|
||||
};
|
||||
}
|
33
src/Components/Modules/Materials.cpp
Normal file
33
src/Components/Modules/Materials.cpp
Normal file
@ -0,0 +1,33 @@
|
||||
#include "..\..\STDInclude.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
Utils::Hook Materials::ImageVersionCheckHook;
|
||||
|
||||
void __declspec(naked) Materials::ImageVersionCheck()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
cmp eax, 9
|
||||
je returnSafely
|
||||
|
||||
jmp Materials::ImageVersionCheckHook.Original
|
||||
|
||||
returnSafely:
|
||||
mov al, 1
|
||||
add esp, 18h
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
Materials::Materials()
|
||||
{
|
||||
// Allow codo images
|
||||
Materials::ImageVersionCheckHook.Initialize(0x53A456, Materials::ImageVersionCheck, HOOK_CALL)->Install();
|
||||
}
|
||||
|
||||
Materials::~Materials()
|
||||
{
|
||||
Materials::ImageVersionCheckHook.Uninstall();
|
||||
}
|
||||
}
|
14
src/Components/Modules/Materials.hpp
Normal file
14
src/Components/Modules/Materials.hpp
Normal file
@ -0,0 +1,14 @@
|
||||
namespace Components
|
||||
{
|
||||
class Materials : public Component
|
||||
{
|
||||
public:
|
||||
Materials();
|
||||
~Materials();
|
||||
const char* GetName() { return "Materials"; };
|
||||
|
||||
private:
|
||||
static Utils::Hook ImageVersionCheckHook;
|
||||
static void ImageVersionCheck();
|
||||
};
|
||||
}
|
535
src/Components/Modules/Menus.cpp
Normal file
535
src/Components/Modules/Menus.cpp
Normal file
@ -0,0 +1,535 @@
|
||||
#include "..\..\STDInclude.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
std::vector<Game::menuDef_t*> Menus::MenuList;
|
||||
std::vector<Game::MenuList*> Menus::MenuListList;
|
||||
|
||||
int Menus::ReserveSourceHandle()
|
||||
{
|
||||
// Check if a free slot is available
|
||||
int i = 1;
|
||||
for (; i < MAX_SOURCEFILES; i++)
|
||||
{
|
||||
if (!Game::sourceFiles[i])
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= MAX_SOURCEFILES)
|
||||
return 0;
|
||||
|
||||
// Reserve it, if yes
|
||||
Game::sourceFiles[i] = (Game::source_t*)1;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
Game::script_t* Menus::LoadMenuScript(std::string name, std::string buffer)
|
||||
{
|
||||
Game::script_t* script = Game::Script_Alloc(sizeof(Game::script_t) + 1 + buffer.length());
|
||||
|
||||
strcpy_s(script->filename, sizeof(script->filename), name.data());
|
||||
script->buffer = (char*)(script + 1);
|
||||
|
||||
*((char*)(script + 1) + buffer.length()) = '\0';
|
||||
|
||||
script->script_p = script->buffer;
|
||||
script->lastscript_p = script->buffer;
|
||||
script->length = buffer.length();
|
||||
script->end_p = &script->buffer[buffer.length()];
|
||||
script->line = 1;
|
||||
script->lastline = 1;
|
||||
script->tokenavailable = 0;
|
||||
|
||||
Game::Script_SetupTokens(script, (void*)0x797F80);
|
||||
script->punctuations = (Game::punctuation_t*)0x797F80;
|
||||
|
||||
strcpy(script->buffer, buffer.data());
|
||||
|
||||
script->length = Game::Script_CleanString(script->buffer);
|
||||
|
||||
return script;
|
||||
}
|
||||
|
||||
int Menus::LoadMenuSource(std::string name, std::string buffer)
|
||||
{
|
||||
int handle = Menus::ReserveSourceHandle();
|
||||
if (!Menus::IsValidSourceHandle(handle)) return 0; // No free source slot!
|
||||
|
||||
Game::source_t *source = nullptr;
|
||||
Game::script_t *script = Menus::LoadMenuScript(name, buffer);
|
||||
|
||||
if (!script)
|
||||
{
|
||||
Game::sourceFiles[handle] = nullptr; // Free reserved slot
|
||||
return 0;
|
||||
}
|
||||
|
||||
script->next = NULL;
|
||||
|
||||
source = (Game::source_t *)calloc(1, sizeof(Game::source_t));
|
||||
|
||||
strncpy(source->filename, "string", 64);
|
||||
source->scriptstack = script;
|
||||
source->tokens = NULL;
|
||||
source->defines = NULL;
|
||||
source->indentstack = NULL;
|
||||
source->skip = 0;
|
||||
source->definehash = (Game::define_t**)calloc(1, 4096);
|
||||
|
||||
Game::sourceFiles[handle] = source;
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
bool Menus::IsValidSourceHandle(int handle)
|
||||
{
|
||||
return (handle > 0 && handle < MAX_SOURCEFILES && Game::sourceFiles[handle]);
|
||||
}
|
||||
|
||||
int Menus::KeywordHash(char* key)
|
||||
{
|
||||
// patch this function on-the-fly, as it's some ugly C.
|
||||
Utils::Hook::Set<DWORD>(0x63FE9E, 3523);
|
||||
Utils::Hook::Set<DWORD>(0x63FECB, 0x7F);
|
||||
|
||||
int var = 0x63FE90;
|
||||
__asm
|
||||
{
|
||||
mov eax, key
|
||||
call var
|
||||
mov var, eax
|
||||
}
|
||||
|
||||
Utils::Hook::Set<DWORD>(0x63FE9E, 531);
|
||||
Utils::Hook::Set<DWORD>(0x63FECB, 0x1FF);
|
||||
|
||||
return var;
|
||||
}
|
||||
|
||||
Game::menuDef_t* Menus::ParseMenu(int handle)
|
||||
{
|
||||
Game::menuDef_t* menu = (Game::menuDef_t*)calloc(1, sizeof(Game::menuDef_t));
|
||||
menu->items = (Game::itemDef_t**)calloc(512, sizeof(Game::itemDef_t*));
|
||||
Menus::MenuList.push_back(menu);
|
||||
|
||||
Game::pc_token_t token;
|
||||
Game::keywordHash_t *key;
|
||||
|
||||
if (!Game::PC_ReadTokenHandle(handle, &token) || token.string[0] != '{')
|
||||
{
|
||||
return menu;
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
ZeroMemory(&token, sizeof(token));
|
||||
|
||||
if (!Game::PC_ReadTokenHandle(handle, &token))
|
||||
{
|
||||
Game::PC_SourceError(handle, "end of file inside menu\n");
|
||||
break; // Fail
|
||||
}
|
||||
|
||||
if (*token.string == '}')
|
||||
{
|
||||
break; // Success
|
||||
}
|
||||
|
||||
int idx = Menus::KeywordHash(token.string);
|
||||
|
||||
key = Game::menuParseKeywordHash[idx];
|
||||
|
||||
if (!key)
|
||||
{
|
||||
Game::PC_SourceError(handle, "unknown menu keyword %s", token.string);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!key->func((Game::itemDef_t*)menu, handle))
|
||||
{
|
||||
Game::PC_SourceError(handle, "couldn't parse menu keyword %s", token.string);
|
||||
break; // Fail
|
||||
}
|
||||
}
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
std::vector<Game::menuDef_t*> Menus::LoadMenu(std::string menu)
|
||||
{
|
||||
std::vector<Game::menuDef_t*> menus;
|
||||
FileSystem::File menuFile(menu);
|
||||
|
||||
if (menuFile.Exists())
|
||||
{
|
||||
Game::pc_token_t token;
|
||||
int handle = Menus::LoadMenuSource(menu, menuFile.GetBuffer());
|
||||
|
||||
if (Menus::IsValidSourceHandle(handle))
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
ZeroMemory(&token, sizeof(token));
|
||||
|
||||
if (!Game::PC_ReadTokenHandle(handle, &token) || token.string[0] == '}')
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (!_stricmp(token.string, "loadmenu"))
|
||||
{
|
||||
Game::PC_ReadTokenHandle(handle, &token);
|
||||
|
||||
std::vector<Game::menuDef_t*> newMenus = Menus::LoadMenu(Utils::VA("ui_mp\\%s.menu", token.string));
|
||||
|
||||
for (auto newMenu : newMenus)
|
||||
{
|
||||
menus.push_back(newMenu);
|
||||
}
|
||||
}
|
||||
|
||||
if (!_stricmp(token.string, "menudef"))
|
||||
{
|
||||
menus.push_back(Menus::ParseMenu(handle));
|
||||
}
|
||||
}
|
||||
|
||||
Menus::FreeMenuSource(handle);
|
||||
}
|
||||
}
|
||||
|
||||
return menus;
|
||||
}
|
||||
|
||||
std::vector<Game::menuDef_t*> Menus::LoadMenu(Game::menuDef_t* menudef)
|
||||
{
|
||||
std::vector<Game::menuDef_t*> menus = Menus::LoadMenu(Utils::VA("ui_mp\\%s.menu", menudef->window.name));
|
||||
|
||||
if (!menus.size())
|
||||
{
|
||||
menus.push_back(menudef);
|
||||
}
|
||||
|
||||
return menus;
|
||||
}
|
||||
|
||||
Game::MenuList* Menus::LoadScriptMenu(const char* menu)
|
||||
{
|
||||
std::vector<Game::menuDef_t*> menus = Menus::LoadMenu(menu);
|
||||
if (!menus.size()) return nullptr;
|
||||
|
||||
// Allocate new menu list
|
||||
Game::MenuList* newList = (Game::MenuList*)calloc(1, sizeof(Game::MenuList));
|
||||
newList->name = _strdup(menu);
|
||||
newList->menus = (Game::menuDef_t **)calloc(menus.size(), sizeof(Game::menuDef_t *));
|
||||
newList->menuCount = menus.size();
|
||||
|
||||
// Copy new menus
|
||||
memcpy(newList->menus, menus.data(), menus.size() * sizeof(Game::menuDef_t *));
|
||||
|
||||
Menus::MenuListList.push_back(newList);
|
||||
|
||||
return newList;
|
||||
}
|
||||
|
||||
Game::MenuList* Menus::LoadMenuList(Game::MenuList* menuList)
|
||||
{
|
||||
std::vector<Game::menuDef_t*> menus;
|
||||
|
||||
for (int i = 0; i < menuList->menuCount; i++)
|
||||
{
|
||||
if (!menuList->menus[i])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
std::vector<Game::menuDef_t*> newMenus = Menus::LoadMenu(menuList->menus[i]);
|
||||
|
||||
for (auto newMenu : newMenus)
|
||||
{
|
||||
menus.push_back(newMenu);
|
||||
}
|
||||
}
|
||||
|
||||
// Allocate new menu list
|
||||
Game::MenuList* newList = (Game::MenuList*)calloc(1, sizeof(Game::MenuList));
|
||||
newList->name = _strdup(menuList->name);
|
||||
newList->menus = (Game::menuDef_t **)calloc(menus.size(), sizeof(Game::menuDef_t *));
|
||||
newList->menuCount = menus.size();
|
||||
|
||||
// Copy new menus
|
||||
memcpy(newList->menus, menus.data(), menus.size() * sizeof(Game::menuDef_t *));
|
||||
|
||||
Menus::MenuListList.push_back(newList);
|
||||
|
||||
return newList;
|
||||
}
|
||||
|
||||
void Menus::FreeMenuSource(int handle)
|
||||
{
|
||||
if (!Menus::IsValidSourceHandle(handle)) return;
|
||||
|
||||
Game::script_t *script;
|
||||
Game::token_t *token;
|
||||
Game::define_t *define;
|
||||
Game::indent_t *indent;
|
||||
Game::source_t *source = Game::sourceFiles[handle];
|
||||
|
||||
while (source->scriptstack)
|
||||
{
|
||||
script = source->scriptstack;
|
||||
source->scriptstack = source->scriptstack->next;
|
||||
Game::FreeMemory(script);
|
||||
}
|
||||
|
||||
while (source->tokens)
|
||||
{
|
||||
token = source->tokens;
|
||||
source->tokens = source->tokens->next;
|
||||
Game::FreeMemory(token);
|
||||
}
|
||||
|
||||
while (source->defines)
|
||||
{
|
||||
define = source->defines;
|
||||
source->defines = source->defines->next;
|
||||
Game::FreeMemory(define);
|
||||
}
|
||||
|
||||
while (source->indentstack)
|
||||
{
|
||||
indent = source->indentstack;
|
||||
source->indentstack = source->indentstack->next;
|
||||
free(indent);
|
||||
}
|
||||
|
||||
if (source->definehash) free(source->definehash);
|
||||
|
||||
free(source);
|
||||
|
||||
Game::sourceFiles[handle] = nullptr;
|
||||
}
|
||||
|
||||
void Menus::FreeMenu(Game::menuDef_t* menudef)
|
||||
{
|
||||
// Do i need to free expressions and strings?
|
||||
// Or does the game take care of it?
|
||||
// Seems like it does...
|
||||
|
||||
if (menudef->items)
|
||||
{
|
||||
// Seems like this is obsolete as well,
|
||||
// as the game handles the memory
|
||||
|
||||
//for (int i = 0; i < menudef->itemCount; i++)
|
||||
//{
|
||||
// Game::Menu_FreeItemMemory(menudef->items[i]);
|
||||
//}
|
||||
|
||||
free(menudef->items);
|
||||
}
|
||||
|
||||
free(menudef);
|
||||
}
|
||||
|
||||
void Menus::FreeMenuList(Game::MenuList* menuList)
|
||||
{
|
||||
if (menuList)
|
||||
{
|
||||
if (menuList->name)
|
||||
{
|
||||
free((void*)menuList->name);
|
||||
}
|
||||
|
||||
if (menuList->menus)
|
||||
{
|
||||
free(menuList->menus);
|
||||
}
|
||||
|
||||
free(menuList);
|
||||
}
|
||||
}
|
||||
|
||||
void Menus::RemoveMenu(Game::menuDef_t* menudef)
|
||||
{
|
||||
for (auto i = Menus::MenuList.begin(); i != Menus::MenuList.end(); i++)
|
||||
{
|
||||
if ((*i) == menudef)
|
||||
{
|
||||
Menus::FreeMenu(menudef);
|
||||
Menus::MenuList.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Menus::RemoveMenuList(Game::MenuList* menuList)
|
||||
{
|
||||
if (!menuList) return;
|
||||
|
||||
for (auto i = Menus::MenuListList.begin(); i != Menus::MenuListList.end(); i++)
|
||||
{
|
||||
if ((*i)->name == menuList->name)
|
||||
{
|
||||
for (auto j = 0; j < menuList->menuCount; j++)
|
||||
{
|
||||
Menus::RemoveMenu(menuList->menus[j]);
|
||||
}
|
||||
|
||||
Menus::FreeMenuList(menuList);
|
||||
Menus::MenuListList.erase(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Menus::FreeEverything()
|
||||
{
|
||||
for (auto menu : Menus::MenuList)
|
||||
{
|
||||
Menus::FreeMenu(menu);
|
||||
}
|
||||
|
||||
Menus::MenuList.clear();
|
||||
|
||||
for (auto menuList : Menus::MenuListList)
|
||||
{
|
||||
Menus::FreeMenuList(menuList);
|
||||
}
|
||||
|
||||
Menus::MenuListList.clear();
|
||||
}
|
||||
|
||||
Game::XAssetHeader Menus::MenuFileLoad(Game::XAssetType type, const char* filename)
|
||||
{
|
||||
Game::XAssetHeader header = { 0 };
|
||||
|
||||
// Check if we already loaded it
|
||||
for (auto menuList : Menus::MenuListList)
|
||||
{
|
||||
if (!_stricmp(menuList->name, filename))
|
||||
{
|
||||
// Free it, seems like the game deallocated it
|
||||
Menus::RemoveMenuList(menuList);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Game::MenuList* menuList = Game::DB_FindXAssetHeader(type, filename).menuList;
|
||||
header.menuList = menuList;
|
||||
|
||||
if (menuList)
|
||||
{
|
||||
// Parse scriptmenus!
|
||||
if (!strcmp(menuList->menus[0]->window.name, "default_menu") || Utils::EndsWith(filename, ".menu"))
|
||||
{
|
||||
if (FileSystem::File(filename).Exists())
|
||||
{
|
||||
header.menuList = Menus::LoadScriptMenu(filename);
|
||||
|
||||
// Reset, if we didn't find scriptmenus
|
||||
if (!header.menuList)
|
||||
{
|
||||
header.menuList = menuList;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
header.menuList = Menus::LoadMenuList(menuList);
|
||||
}
|
||||
}
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
void Menus::AddMenuListHook(Game::UiContext *dc, Game::MenuList *menuList, int close)
|
||||
{
|
||||
Game::MenuList* menus = Game::DB_FindXAssetHeader(Game::XAssetType::ASSET_TYPE_MENUFILE, "ui_mp/menus.txt").menuList;
|
||||
|
||||
Game::UI_AddMenuList(dc, menus, close);
|
||||
Game::UI_AddMenuList(dc, menuList, close);
|
||||
}
|
||||
|
||||
Game::menuDef_t* Menus::FindMenuByName(Game::UiContext* dc, const char* name)
|
||||
{
|
||||
for (int i = 0; i < dc->menuCount; i++)
|
||||
{
|
||||
Game::menuDef_t* menu = dc->Menus[i];
|
||||
if (menu && menu->window.name && !IsBadReadPtr(menu->window.name, 1)) // Sanity checks
|
||||
{
|
||||
if (!_strnicmp(name, menu->window.name, 0x7FFFFFFF))
|
||||
{
|
||||
return menu;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Remove menu from stack and free if custom menu
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Menus::Menus()
|
||||
{
|
||||
AssetHandler::OnFind(Game::XAssetType::ASSET_TYPE_MENUFILE, Menus::MenuFileLoad);
|
||||
//Utils::Hook(0x63FE80, Menus::MenuFileLoad, HOOK_JUMP).Install()->Quick();
|
||||
|
||||
// Custom Menus_FindByName
|
||||
Utils::Hook(0x487240, Menus::FindMenuByName, HOOK_JUMP).Install()->Quick();
|
||||
|
||||
// Load menus ingame
|
||||
Utils::Hook(0x41C178, Menus::AddMenuListHook, HOOK_CALL).Install()->Quick();
|
||||
|
||||
// disable the 2 new tokens in ItemParse_rect
|
||||
Utils::Hook::Set<BYTE>(0x640693, 0xEB);
|
||||
|
||||
// don't load ASSET_TYPE_MENU assets for every menu (might cause patch menus to fail)
|
||||
Utils::Hook::Nop(0x453406, 5);
|
||||
|
||||
//make Com_Error and similar go back to main_text instead of menu_xboxlive.
|
||||
strcpy((char*)0x6FC790, "main_text");
|
||||
|
||||
Command::Add("openmenu", [] (Command::Params params)
|
||||
{
|
||||
if (params.Length() != 2)
|
||||
{
|
||||
Logger::Print("USAGE: openmenu <menu name>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
Game::Menus_OpenByName(Game::uiContext, params[1]);
|
||||
});
|
||||
|
||||
Command::Add("reloadmenus", [] (Command::Params params)
|
||||
{
|
||||
// Close all menus
|
||||
Game::Menus_CloseAll(Game::uiContext);
|
||||
|
||||
// Free custom menus
|
||||
Menus::FreeEverything();
|
||||
|
||||
// Only disconnect if in-game, context is updated automatically!
|
||||
if (Game::CL_IsCgameInitialized())
|
||||
{
|
||||
Game::Cbuf_AddText(0, "disconnect\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reinitialize ui context
|
||||
((void(*)())0x401700)();
|
||||
|
||||
// Reopen main menu
|
||||
Game::Menus_OpenByName(Game::uiContext, "main_text");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Menus::~Menus()
|
||||
{
|
||||
Menus::FreeEverything();
|
||||
}
|
||||
}
|
47
src/Components/Modules/Menus.hpp
Normal file
47
src/Components/Modules/Menus.hpp
Normal file
@ -0,0 +1,47 @@
|
||||
#define MAX_SOURCEFILES 64
|
||||
|
||||
namespace Components
|
||||
{
|
||||
class Menus : public Component
|
||||
{
|
||||
public:
|
||||
Menus();
|
||||
~Menus();
|
||||
const char* GetName() { return "Menus"; };
|
||||
|
||||
static void FreeEverything();
|
||||
|
||||
private:
|
||||
static std::vector<Game::menuDef_t*> MenuList;
|
||||
static std::vector<Game::MenuList*> MenuListList;
|
||||
|
||||
static Game::XAssetHeader MenuFileLoad(Game::XAssetType type, const char* filename);
|
||||
static Game::MenuList* LoadMenuList(Game::MenuList* menuList);
|
||||
static Game::MenuList* LoadScriptMenu(const char* menu);
|
||||
static std::vector<Game::menuDef_t*> LoadMenu(Game::menuDef_t* menudef);
|
||||
static std::vector<Game::menuDef_t*> LoadMenu(std::string file);
|
||||
|
||||
static Game::script_t* LoadMenuScript(std::string name, std::string buffer);
|
||||
static int LoadMenuSource(std::string name, std::string buffer);
|
||||
|
||||
static int ReserveSourceHandle();
|
||||
static bool IsValidSourceHandle(int handle);
|
||||
|
||||
static Game::menuDef_t* ParseMenu(int handle);
|
||||
|
||||
static void FreeMenuSource(int handle);
|
||||
|
||||
static void FreeMenuList(Game::MenuList* menuList);
|
||||
static void FreeMenu(Game::menuDef_t* menudef);
|
||||
|
||||
static void RemoveMenu(Game::menuDef_t* menudef);
|
||||
static void RemoveMenuList(Game::MenuList* menuList);
|
||||
|
||||
static void AddMenuListHook(Game::UiContext *dc, Game::MenuList *menuList, int close);
|
||||
|
||||
static Game::menuDef_t* FindMenuByName(Game::UiContext* dc, const char* name);
|
||||
|
||||
// Ugly!
|
||||
static int KeywordHash(char* key);
|
||||
};
|
||||
}
|
45
src/Components/Modules/MusicalTalent.cpp
Normal file
45
src/Components/Modules/MusicalTalent.cpp
Normal file
@ -0,0 +1,45 @@
|
||||
#include "..\..\STDInclude.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
std::map<std::string, const char*> MusicalTalent::SoundAliasList;
|
||||
|
||||
void MusicalTalent::Replace(std::string sound, const char* file)
|
||||
{
|
||||
MusicalTalent::SoundAliasList[Utils::StrToLower(sound)] = file;
|
||||
}
|
||||
|
||||
Game::XAssetHeader MusicalTalent::ManipulateAliases(Game::XAssetType type, const char* filename)
|
||||
{
|
||||
Game::XAssetHeader header = { 0 };
|
||||
|
||||
if (MusicalTalent::SoundAliasList.find(Utils::StrToLower(filename)) != MusicalTalent::SoundAliasList.end())
|
||||
{
|
||||
Game::snd_alias_list_t* aliases = Game::DB_FindXAssetHeader(type, filename).aliasList;
|
||||
|
||||
if (aliases)
|
||||
{
|
||||
if (aliases->aliases->stream->type == 2)
|
||||
{
|
||||
aliases->aliases->stream->file = MusicalTalent::SoundAliasList[Utils::StrToLower(filename)];
|
||||
}
|
||||
|
||||
header.aliasList = aliases;
|
||||
}
|
||||
}
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
MusicalTalent::MusicalTalent()
|
||||
{
|
||||
AssetHandler::OnFind(Game::XAssetType::ASSET_TYPE_SOUND, MusicalTalent::ManipulateAliases);
|
||||
|
||||
MusicalTalent::Replace("music_mainmenu_mp", "hz_boneyard_intro_LR_1.mp3");
|
||||
}
|
||||
|
||||
MusicalTalent::~MusicalTalent()
|
||||
{
|
||||
MusicalTalent::SoundAliasList.clear();
|
||||
}
|
||||
}
|
16
src/Components/Modules/MusicalTalent.hpp
Normal file
16
src/Components/Modules/MusicalTalent.hpp
Normal file
@ -0,0 +1,16 @@
|
||||
namespace Components
|
||||
{
|
||||
class MusicalTalent : public Component
|
||||
{
|
||||
public:
|
||||
MusicalTalent();
|
||||
~MusicalTalent();
|
||||
const char* GetName() { return "MusicalTalent"; };
|
||||
|
||||
static void Replace(std::string sound, const char* file);
|
||||
|
||||
private:
|
||||
static std::map<std::string, const char*> SoundAliasList;
|
||||
static Game::XAssetHeader ManipulateAliases(Game::XAssetType type, const char* filename);
|
||||
};
|
||||
}
|
133
src/Components/Modules/Network.cpp
Normal file
133
src/Components/Modules/Network.cpp
Normal file
@ -0,0 +1,133 @@
|
||||
#include "..\..\STDInclude.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
std::string Network::SelectedPacket;
|
||||
std::map<std::string, Network::Callback> Network::PacketHandlers;
|
||||
|
||||
Network::Address::Address(std::string addrString)
|
||||
{
|
||||
Game::NET_StringToAdr(addrString.data(), &this->address);
|
||||
}
|
||||
bool Network::Address::operator==(const Network::Address &obj)
|
||||
{
|
||||
return Game::NET_CompareAdr(this->address, obj.address);
|
||||
}
|
||||
void Network::Address::SetPort(unsigned short port)
|
||||
{
|
||||
this->address.port = port;
|
||||
};
|
||||
unsigned short Network::Address::GetPort()
|
||||
{
|
||||
return this->address.port;
|
||||
}
|
||||
void Network::Address::SetIP(DWORD ip)
|
||||
{
|
||||
*(DWORD*)this->address.ip = ip;
|
||||
}
|
||||
DWORD Network::Address::GetIP()
|
||||
{
|
||||
return *(DWORD*)this->address.ip;
|
||||
}
|
||||
Game::netadr_t* Network::Address::Get()
|
||||
{
|
||||
return &this->address;
|
||||
}
|
||||
const char* Network::Address::GetString()
|
||||
{
|
||||
return Game::NET_AdrToString(this->address);
|
||||
}
|
||||
|
||||
void Network::Handle(std::string packet, Network::Callback callback)
|
||||
{
|
||||
Network::PacketHandlers[Utils::StrToLower(packet)] = callback;
|
||||
}
|
||||
|
||||
void Network::Send(Game::netsrc_t type, Address target, std::string data)
|
||||
{
|
||||
Game::OOBPrintT(type, *target.Get(), data.data());
|
||||
}
|
||||
|
||||
void Network::Send(Address target, std::string data)
|
||||
{
|
||||
Network::Send(Game::netsrc_t::NS_CLIENT, target, data);
|
||||
}
|
||||
|
||||
int Network::PacketInterceptionHandler(const char* packet)
|
||||
{
|
||||
// Check if custom handler exists
|
||||
for (auto i = Network::PacketHandlers.begin(); i != Network::PacketHandlers.end(); i++)
|
||||
{
|
||||
if (!_strnicmp(i->first.data(), packet, i->first.size()))
|
||||
{
|
||||
Network::SelectedPacket = i->first;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// No interception
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Network::DeployPacket(Game::netadr_t from, Game::msg_t* msg)
|
||||
{
|
||||
if (Network::PacketHandlers.find(Network::SelectedPacket) != Network::PacketHandlers.end())
|
||||
{
|
||||
size_t offset = Network::SelectedPacket.size() + 4 + 1;
|
||||
Network::PacketHandlers[Network::SelectedPacket](from, std::string(msg->data + offset, msg->cursize - offset));
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::Print("Error: Network packet intercepted, but handler is missing!\n");
|
||||
}
|
||||
}
|
||||
|
||||
void __declspec(naked) Network::DeployPacketStub()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
push ebp //C54
|
||||
// esp = C54h?
|
||||
mov eax, [esp + 0C54h + 14h]
|
||||
push eax
|
||||
mov eax, [esp + 0C58h + 10h]
|
||||
push eax
|
||||
mov eax, [esp + 0C5Ch + 0Ch]
|
||||
push eax
|
||||
mov eax, [esp + 0C60h + 08h]
|
||||
push eax
|
||||
mov eax, [esp + 0C64h + 04h]
|
||||
push eax
|
||||
call Network::DeployPacket
|
||||
add esp, 14h
|
||||
add esp, 4h
|
||||
mov al, 1
|
||||
//C50
|
||||
pop edi //C4C
|
||||
pop esi //C48
|
||||
pop ebp //C44
|
||||
pop ebx //C40
|
||||
add esp, 0C40h
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
Network::Network()
|
||||
{
|
||||
// maximum size in NET_OutOfBandPrint
|
||||
Utils::Hook::Set<DWORD>(0x4AEF08, 0x1FFFC);
|
||||
Utils::Hook::Set<DWORD>(0x4AEFA3, 0x1FFFC);
|
||||
|
||||
// Install interception handler
|
||||
Utils::Hook(0x5AA709, Network::PacketInterceptionHandler, HOOK_CALL).Install()->Quick();
|
||||
|
||||
// Install packet deploy hook
|
||||
Utils::Hook::Set<int>(0x5AA715, (DWORD)Network::DeployPacketStub - 0x5AA713 - 6);
|
||||
}
|
||||
|
||||
Network::~Network()
|
||||
{
|
||||
Network::SelectedPacket.clear();
|
||||
Network::PacketHandlers.clear();
|
||||
}
|
||||
}
|
48
src/Components/Modules/Network.hpp
Normal file
48
src/Components/Modules/Network.hpp
Normal file
@ -0,0 +1,48 @@
|
||||
namespace Components
|
||||
{
|
||||
class Network : public Component
|
||||
{
|
||||
public:
|
||||
class Address
|
||||
{
|
||||
public:
|
||||
Address() {};
|
||||
Address(std::string addrString);
|
||||
Address(Game::netadr_t addr) : address(addr) {}
|
||||
Address(Game::netadr_t* addr) : Address(*addr) {}
|
||||
Address(const Address& obj) { this->address = obj.address; };
|
||||
bool operator!=(const Address &obj) { return !(*this == obj); };
|
||||
bool operator==(const Address &obj);
|
||||
|
||||
void SetPort(unsigned short port);
|
||||
unsigned short GetPort();
|
||||
|
||||
void SetIP(DWORD ip);
|
||||
DWORD GetIP();
|
||||
|
||||
Game::netadr_t* Get();
|
||||
const char* GetString();
|
||||
|
||||
|
||||
private:
|
||||
Game::netadr_t address;
|
||||
};
|
||||
|
||||
typedef void(*Callback)(Address address, std::string data);
|
||||
|
||||
Network();
|
||||
~Network();
|
||||
const char* GetName() { return "Network"; };
|
||||
|
||||
static void Handle(std::string packet, Callback callback);
|
||||
static void Send(Address target, std::string data);
|
||||
static void Send(Game::netsrc_t type, Address target, std::string data);
|
||||
|
||||
private:
|
||||
static std::string SelectedPacket;
|
||||
static std::map<std::string, Callback> PacketHandlers;
|
||||
static int PacketInterceptionHandler(const char* packet);
|
||||
static void DeployPacket(Game::netadr_t from, Game::msg_t* msg);
|
||||
static void DeployPacketStub();
|
||||
};
|
||||
}
|
253
src/Components/Modules/Party.cpp
Normal file
253
src/Components/Modules/Party.cpp
Normal file
@ -0,0 +1,253 @@
|
||||
#include "..\..\STDInclude.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
Party::JoinContainer Party::Container;
|
||||
std::map<uint64_t, Network::Address> Party::LobbyMap;
|
||||
|
||||
SteamID Party::GenerateLobbyId()
|
||||
{
|
||||
SteamID id;
|
||||
|
||||
id.AccountID = Game::Com_Milliseconds();
|
||||
id.Universe = 1;
|
||||
id.AccountType = 8;
|
||||
id.AccountInstance = 0x40000;
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
void Party::Connect(Network::Address target)
|
||||
{
|
||||
Party::Container.Valid = true;
|
||||
Party::Container.JoinTime = Game::Com_Milliseconds();
|
||||
Party::Container.Target = target;
|
||||
Party::Container.Challenge = Utils::VA("%X", Party::Container.JoinTime);
|
||||
|
||||
Network::Send(Party::Container.Target, Utils::VA("getinfo %s\n", Party::Container.Challenge.data()));
|
||||
|
||||
Command::Execute("openmenu popup_reconnectingtoparty");
|
||||
}
|
||||
|
||||
const char* Party::GetLobbyInfo(SteamID lobby, std::string key)
|
||||
{
|
||||
if (Party::LobbyMap.find(lobby.Bits) != Party::LobbyMap.end())
|
||||
{
|
||||
Network::Address address = Party::LobbyMap[lobby.Bits];
|
||||
|
||||
if (key == "addr")
|
||||
{
|
||||
return Utils::VA("%d", address.Get()->ip[0] | (address.Get()->ip[1] << 8) | (address.Get()->ip[2] << 16) | (address.Get()->ip[3] << 24));
|
||||
}
|
||||
else if (key =="port")
|
||||
{
|
||||
return Utils::VA("%d", htons(address.GetPort()));
|
||||
}
|
||||
}
|
||||
|
||||
return "212";
|
||||
}
|
||||
|
||||
void Party::RemoveLobby(SteamID lobby)
|
||||
{
|
||||
if (Party::LobbyMap.find(lobby.Bits) != Party::LobbyMap.end())
|
||||
{
|
||||
Party::LobbyMap.erase(Party::LobbyMap.find(lobby.Bits));
|
||||
}
|
||||
}
|
||||
|
||||
void Party::ConnectError(std::string message)
|
||||
{
|
||||
Command::Execute("closemenu popup_reconnectingtoparty");
|
||||
Dvar::Var("partyend_reason").Set(message);
|
||||
Command::Execute("openmenu menu_xboxlive_partyended");
|
||||
}
|
||||
|
||||
Game::dvar_t* Party::RegisterMinPlayers(const char* name, int value, int min, int max, Game::dvar_flag flag, const char* description)
|
||||
{
|
||||
return Dvar::Register<int>(name, 1, 1, max, Game::dvar_flag::DVAR_FLAG_WRITEPROTECTED | flag, description).Get<Game::dvar_t*>();
|
||||
}
|
||||
|
||||
Party::Party()
|
||||
{
|
||||
// various changes to SV_DirectConnect-y stuff to allow non-party joinees
|
||||
Utils::Hook::Set<WORD>(0x460D96, 0x90E9);
|
||||
Utils::Hook::Set<BYTE>(0x460F0A, 0xEB);
|
||||
Utils::Hook::Set<BYTE>(0x401CA4, 0xEB);
|
||||
Utils::Hook::Set<BYTE>(0x401C15, 0xEB);
|
||||
|
||||
// disable configstring checksum matching (it's unreliable at most)
|
||||
Utils::Hook::Set<BYTE>(0x4A75A7, 0xEB); // SV_SpawnServer
|
||||
Utils::Hook::Set<BYTE>(0x5AC2CF, 0xEB); // CL_ParseGamestate
|
||||
Utils::Hook::Set<BYTE>(0x5AC2C3, 0xEB); // CL_ParseGamestate
|
||||
|
||||
// AnonymousAddRequest
|
||||
Utils::Hook::Set<BYTE>(0x5B5E18, 0xEB);
|
||||
Utils::Hook::Set<BYTE>(0x5B5E64, 0xEB);
|
||||
Utils::Hook::Nop(0x5B5E5C, 2);
|
||||
|
||||
// HandleClientHandshake
|
||||
Utils::Hook::Set<BYTE>(0x5B6EA5, 0xEB);
|
||||
Utils::Hook::Set<BYTE>(0x5B6EF3, 0xEB);
|
||||
Utils::Hook::Nop(0x5B6EEB, 2);
|
||||
|
||||
// Allow local connections
|
||||
Utils::Hook::Set<BYTE>(0x4D43DA, 0xEB);
|
||||
|
||||
// LobbyID mismatch
|
||||
Utils::Hook::Nop(0x4E50D6, 2);
|
||||
Utils::Hook::Set<BYTE>(0x4E50DA, 0xEB);
|
||||
|
||||
// causes 'does current Steam lobby match' calls in Steam_JoinLobby to be ignored
|
||||
Utils::Hook::Set<BYTE>(0x49D007, 0xEB);
|
||||
|
||||
// functions checking party heartbeat timeouts, cause random issues
|
||||
Utils::Hook::Nop(0x4E532D, 5);
|
||||
|
||||
// Steam_JoinLobby call causes migration
|
||||
Utils::Hook::Nop(0x5AF851, 5);
|
||||
Utils::Hook::Set<BYTE>(0x5AF85B, 0xEB);
|
||||
|
||||
// Allow xpartygo in public lobbies
|
||||
Utils::Hook::Set<BYTE>(0x5A969E, 0xEB);
|
||||
|
||||
// Patch party_minplayers to 1 and protect it
|
||||
Utils::Hook(0x4D5D51, Party::RegisterMinPlayers, HOOK_CALL).Install()->Quick();
|
||||
|
||||
Command::Add("connect", [] (Command::Params params)
|
||||
{
|
||||
if (params.Length() < 2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Party::Connect(Network::Address(params[1]));
|
||||
});
|
||||
|
||||
Renderer::OnFrame([] ()
|
||||
{
|
||||
if (!Party::Container.Valid) return;
|
||||
|
||||
if ((Game::Com_Milliseconds() - Party::Container.JoinTime) > 5000)
|
||||
{
|
||||
Party::Container.Valid = false;
|
||||
Party::ConnectError("Server connection timed out.");
|
||||
}
|
||||
});
|
||||
|
||||
// Basic info handler
|
||||
Network::Handle("getInfo", [] (Network::Address address, std::string data)
|
||||
{
|
||||
int clientCount = 0;
|
||||
|
||||
for (int i = 0; i < *Game::svs_numclients; i++)
|
||||
{
|
||||
if (Game::svs_clients[i].state >= 3)
|
||||
{
|
||||
clientCount++;
|
||||
}
|
||||
}
|
||||
|
||||
Utils::InfoString info;
|
||||
info.Set("challenge", data.substr(0, data.find_first_of("\n")).data());
|
||||
info.Set("gamename", "IW4");
|
||||
info.Set("hostname", Dvar::Var("sv_hostname").Get<const char*>());
|
||||
info.Set("mapname", Dvar::Var("mapname").Get<const char*>());
|
||||
info.Set("gametype", Dvar::Var("g_gametype").Get<const char*>());
|
||||
info.Set("fs_game", Dvar::Var("fs_game").Get<const char*>());
|
||||
info.Set("xuid", Utils::VA("%llX", Steam::SteamUser()->GetSteamID().Bits));
|
||||
info.Set("clients", Utils::VA("%i", clientCount));
|
||||
info.Set("sv_maxclients", Utils::VA("%i", *Game::svs_numclients));
|
||||
|
||||
// Set matchtype
|
||||
// 0 - No match, connecting not possible
|
||||
// 1 - Party, use Steam_JoinLobby to connect
|
||||
// 2 - Match, use CL_ConnectFromParty to connect
|
||||
|
||||
if (Dvar::Var("party_host").Get<bool>()) // Party hosting
|
||||
{
|
||||
info.Set("matchtype", "1");
|
||||
}
|
||||
else if (Dvar::Var("sv_running").Get<bool>()) // Match hosting
|
||||
{
|
||||
info.Set("matchtype", "2");
|
||||
}
|
||||
else
|
||||
{
|
||||
info.Set("matchtype", "0");
|
||||
}
|
||||
|
||||
Network::Send(address, Utils::VA("infoResponse\n%s\n", info.Build().data()));
|
||||
});
|
||||
|
||||
Network::Handle("infoResponse", [] (Network::Address address, std::string data)
|
||||
{
|
||||
Utils::InfoString info(data);
|
||||
|
||||
// Handle connection
|
||||
if (Party::Container.Valid)
|
||||
{
|
||||
if (Party::Container.Target == address)
|
||||
{
|
||||
// Invalidate handler for future packets
|
||||
Party::Container.Valid = false;
|
||||
|
||||
int matchType = atoi(info.Get("matchtype").data());
|
||||
|
||||
if (info.Get("challenge") != Party::Container.Challenge)
|
||||
{
|
||||
Party::ConnectError("Invalid join response: Challenge mismatch.");
|
||||
}
|
||||
else if (!matchType)
|
||||
{
|
||||
Party::ConnectError("Server is not hosting a match.");
|
||||
}
|
||||
// Connect
|
||||
else if (matchType == 1) // Party
|
||||
{
|
||||
SteamID id = Party::GenerateLobbyId();
|
||||
|
||||
Party::LobbyMap[id.Bits] = address;
|
||||
|
||||
Game::Steam_JoinLobby(id, 0);
|
||||
|
||||
// Callback not registered on first try
|
||||
// TODO: Fix :D
|
||||
if (Party::LobbyMap.size() <= 1) Game::Steam_JoinLobby(id, 0);
|
||||
}
|
||||
else if (matchType == 2) // Match
|
||||
{
|
||||
if (atoi(info.Get("clients").data()) >= atoi(info.Get("sv_maxclients").data()))
|
||||
{
|
||||
Party::ConnectError("@EXE_SERVERISFULL");
|
||||
}
|
||||
if (info.Get("mapname") == "" || info.Get("gametype") == "")
|
||||
{
|
||||
Party::ConnectError("Invalid map or gametype.");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Dvar::Var("xblive_privatematch").Set(1);
|
||||
Game::Menus_CloseAll(Game::uiContext);
|
||||
|
||||
char xnaddr[32];
|
||||
Game::CL_ConnectFromParty(0, xnaddr, *address.Get(), 0, 0, info.Get("mapname").data(), info.Get("gametype").data());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Party::ConnectError("Invalid join response: Unknown matchtype");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ServerList::Insert(address, info);
|
||||
});
|
||||
}
|
||||
|
||||
Party::~Party()
|
||||
{
|
||||
Party::LobbyMap.clear();
|
||||
}
|
||||
}
|
32
src/Components/Modules/Party.hpp
Normal file
32
src/Components/Modules/Party.hpp
Normal file
@ -0,0 +1,32 @@
|
||||
namespace Components
|
||||
{
|
||||
class Party : public Component
|
||||
{
|
||||
public:
|
||||
Party();
|
||||
~Party();
|
||||
const char* GetName() { return "Party"; };
|
||||
|
||||
static void Connect(Network::Address target);
|
||||
static const char* GetLobbyInfo(SteamID lobby, std::string key);
|
||||
static void RemoveLobby(SteamID lobby);
|
||||
|
||||
private:
|
||||
struct JoinContainer
|
||||
{
|
||||
Network::Address Target;
|
||||
std::string Challenge;
|
||||
DWORD JoinTime;
|
||||
bool Valid;
|
||||
};
|
||||
|
||||
static JoinContainer Container;
|
||||
static std::map<uint64_t, Network::Address> LobbyMap;
|
||||
|
||||
static SteamID GenerateLobbyId();
|
||||
|
||||
static Game::dvar_t* RegisterMinPlayers(const char* name, int value, int min, int max, Game::dvar_flag flag, const char* description);
|
||||
|
||||
static void ConnectError(std::string message);
|
||||
};
|
||||
}
|
90
src/Components/Modules/QuickPatch.cpp
Normal file
90
src/Components/Modules/QuickPatch.cpp
Normal file
@ -0,0 +1,90 @@
|
||||
#include "..\..\STDInclude.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
__int64* QuickPatch::GetStatsID()
|
||||
{
|
||||
static __int64 id = 0x110000100001337;
|
||||
return &id;
|
||||
}
|
||||
|
||||
QuickPatch::QuickPatch()
|
||||
{
|
||||
// remove system pre-init stuff (improper quit, disk full)
|
||||
Utils::Hook::Set<BYTE>(0x411350, 0xC3);
|
||||
|
||||
// remove STEAMSTART checking for DRM IPC
|
||||
Utils::Hook::Nop(0x451145, 5);
|
||||
Utils::Hook::Set<BYTE>(0x45114C, 0xEB);
|
||||
|
||||
// Apply new playlist
|
||||
char* playlist = "mp_playlists_dlc2";
|
||||
Utils::Hook::Set<char*>(0x494803, playlist);
|
||||
Utils::Hook::Set<char*>(0x4C6EC1, playlist);
|
||||
Utils::Hook::Set<char*>(0x4CF7F9, playlist);
|
||||
Utils::Hook::Set<char*>(0x4D6E63, playlist);
|
||||
Utils::Hook::Set<char*>(0x4D7358, playlist);
|
||||
Utils::Hook::Set<char*>(0x4D73C8, playlist);
|
||||
Utils::Hook::Set<char*>(0x4F4EA1, playlist);
|
||||
Utils::Hook::Set<char*>(0x4D47FB, "mp_playlists_dlc2.ff");
|
||||
Utils::Hook::Set<char*>(0x60B06E, "playlists.patch2");
|
||||
|
||||
// disable playlist download function
|
||||
Utils::Hook::Set<BYTE>(0x4D4790, 0xC3);
|
||||
|
||||
// disable playlist.ff loading function
|
||||
//Utils::Hook::Set<BYTE>(0x4D6E60, 0xC3);
|
||||
|
||||
// Load playlist, but don't delete it
|
||||
Utils::Hook::Nop(0x4D6EBB, 5);
|
||||
Utils::Hook::Nop(0x4D6E67, 5);
|
||||
Utils::Hook::Nop(0x4D6E71, 2);
|
||||
|
||||
// playlist dvar 'validity check'
|
||||
Utils::Hook::Set<BYTE>(0x4B1170, 0xC3);
|
||||
|
||||
//Got playlists is true
|
||||
//Utils::Hook::Set<bool>(0x1AD3680, true);
|
||||
|
||||
// LSP disabled
|
||||
Utils::Hook::Set<BYTE>(0x435950, 0xC3); // LSP HELLO
|
||||
Utils::Hook::Set<BYTE>(0x49C220, 0xC3); // We wanted to send a logging packet, but we haven't connected to LSP!
|
||||
Utils::Hook::Set<BYTE>(0x4BD900, 0xC3); // main LSP response func
|
||||
Utils::Hook::Set<BYTE>(0x682170, 0xC3); // Telling LSP that we're playing a private match
|
||||
|
||||
// Don't delete config files if corrupted
|
||||
Utils::Hook::Set<BYTE>(0x47DCB3, 0xEB);
|
||||
|
||||
// hopefully allow alt-tab during game, used at least in alt-enter handling
|
||||
Utils::Hook::Set<DWORD>(0x45ACE0, 0xC301B0);
|
||||
|
||||
// fs_basegame
|
||||
Utils::Hook::Set<char*>(0x6431D1, "data");
|
||||
|
||||
// remove limit on IWD file loading
|
||||
Utils::Hook::Set<BYTE>(0x642BF3, 0xEB);
|
||||
|
||||
// Disable UPNP
|
||||
Utils::Hook::Nop(0x60BE24, 5);
|
||||
|
||||
// disable the IWNet IP detection (default 'got ipdetect' flag to 1)
|
||||
Utils::Hook::Set<BYTE>(0x649D6F0, 1);
|
||||
|
||||
// Fix stats sleeping
|
||||
Utils::Hook::Set<BYTE>(0x6832BA, 0xEB);
|
||||
Utils::Hook::Set<BYTE>(0x4BD190, 0xC3);
|
||||
|
||||
// default sv_pure to 0
|
||||
Utils::Hook::Set<BYTE>(0x4D3A74, 0);
|
||||
|
||||
// Force debug logging
|
||||
Utils::Hook::Nop(0x4AA89F, 2);
|
||||
Utils::Hook::Nop(0x4AA8A1, 6);
|
||||
|
||||
// Patch stats steamid
|
||||
Utils::Hook::Nop(0x682EBF, 20);
|
||||
Utils::Hook::Nop(0x6830B1, 20);
|
||||
Utils::Hook(0x682EBF, QuickPatch::GetStatsID, HOOK_CALL).Install()->Quick();
|
||||
Utils::Hook(0x6830B1, QuickPatch::GetStatsID, HOOK_CALL).Install()->Quick();
|
||||
}
|
||||
}
|
12
src/Components/Modules/QuickPatch.hpp
Normal file
12
src/Components/Modules/QuickPatch.hpp
Normal file
@ -0,0 +1,12 @@
|
||||
namespace Components
|
||||
{
|
||||
class QuickPatch : public Component
|
||||
{
|
||||
public:
|
||||
QuickPatch();
|
||||
const char* GetName() { return "QuickPatch"; };
|
||||
|
||||
private:
|
||||
static _int64* GetStatsID();
|
||||
};
|
||||
}
|
24
src/Components/Modules/RawFiles.cpp
Normal file
24
src/Components/Modules/RawFiles.cpp
Normal file
@ -0,0 +1,24 @@
|
||||
#include "..\..\STDInclude.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
void* RawFiles::LoadModdableRawfileFunc(const char* filename)
|
||||
{
|
||||
return Game::LoadModdableRawfile(0, filename);
|
||||
}
|
||||
|
||||
RawFiles::RawFiles()
|
||||
{
|
||||
Utils::Hook(0x632155, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).Install()->Quick();
|
||||
Utils::Hook(0x5FA46C, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).Install()->Quick();
|
||||
Utils::Hook(0x5FA4D6, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).Install()->Quick();
|
||||
Utils::Hook(0x6321EF, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).Install()->Quick();
|
||||
Utils::Hook(0x630A88, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).Install()->Quick();
|
||||
Utils::Hook(0x59A6F8, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).Install()->Quick();
|
||||
Utils::Hook(0x57F1E6, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).Install()->Quick();
|
||||
Utils::Hook(0x57ED36, RawFiles::LoadModdableRawfileFunc, HOOK_CALL).Install()->Quick();
|
||||
|
||||
// remove fs_game check for moddable rawfiles - allows non-fs_game to modify rawfiles
|
||||
Utils::Hook::Nop(0x61AB76, 2);
|
||||
}
|
||||
}
|
11
src/Components/Modules/RawFiles.hpp
Normal file
11
src/Components/Modules/RawFiles.hpp
Normal file
@ -0,0 +1,11 @@
|
||||
namespace Components
|
||||
{
|
||||
class RawFiles : public Component
|
||||
{
|
||||
public:
|
||||
RawFiles();
|
||||
const char* GetName() { return "RawFiles"; };
|
||||
|
||||
static void* RawFiles::LoadModdableRawfileFunc(const char* filename);
|
||||
};
|
||||
}
|
41
src/Components/Modules/Renderer.cpp
Normal file
41
src/Components/Modules/Renderer.cpp
Normal file
@ -0,0 +1,41 @@
|
||||
#include "..\..\STDInclude.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
Utils::Hook Renderer::DrawFrameHook;
|
||||
std::vector<Renderer::Callback> Renderer::FrameCallbacks;
|
||||
|
||||
void __declspec(naked) Renderer::FrameHook()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
call Renderer::FrameHandler
|
||||
jmp Renderer::DrawFrameHook.Original
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::FrameHandler()
|
||||
{
|
||||
for (auto callback : Renderer::FrameCallbacks)
|
||||
{
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::OnFrame(Renderer::Callback callback)
|
||||
{
|
||||
Renderer::FrameCallbacks.push_back(callback);
|
||||
}
|
||||
|
||||
Renderer::Renderer()
|
||||
{
|
||||
// Frame hook
|
||||
Renderer::DrawFrameHook.Initialize(0x5ACB99, Renderer::FrameHook, HOOK_CALL)->Install();
|
||||
}
|
||||
|
||||
Renderer::~Renderer()
|
||||
{
|
||||
Renderer::DrawFrameHook.Uninstall();
|
||||
Renderer::FrameCallbacks.clear();
|
||||
}
|
||||
}
|
21
src/Components/Modules/Renderer.hpp
Normal file
21
src/Components/Modules/Renderer.hpp
Normal file
@ -0,0 +1,21 @@
|
||||
namespace Components
|
||||
{
|
||||
class Renderer : public Component
|
||||
{
|
||||
public:
|
||||
typedef void(*Callback)();
|
||||
|
||||
Renderer();
|
||||
~Renderer();
|
||||
const char* GetName() { return "Renderer"; };
|
||||
|
||||
static void OnFrame(Callback callback);
|
||||
|
||||
private:
|
||||
static void FrameHook();
|
||||
static void FrameHandler();
|
||||
|
||||
static std::vector<Callback> FrameCallbacks;
|
||||
static Utils::Hook DrawFrameHook;
|
||||
};
|
||||
}
|
272
src/Components/Modules/ServerList.cpp
Normal file
272
src/Components/Modules/ServerList.cpp
Normal file
@ -0,0 +1,272 @@
|
||||
#include "..\..\STDInclude.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
unsigned int ServerList::CurrentServer = 0;
|
||||
ServerList::Container ServerList::RefreshContainer;
|
||||
std::vector<ServerList::ServerInfo> ServerList::OnlineList;
|
||||
|
||||
int ServerList::GetServerCount()
|
||||
{
|
||||
return ServerList::OnlineList.size();
|
||||
}
|
||||
|
||||
const char* ServerList::GetServerText(int index, int column)
|
||||
{
|
||||
if ((unsigned int)index >= ServerList::OnlineList.size()) return "";
|
||||
|
||||
ServerList::ServerInfo* Server = &ServerList::OnlineList[index];
|
||||
|
||||
switch (column)
|
||||
{
|
||||
case Column::Password:
|
||||
{
|
||||
return (Server->Password ? "X" : "");
|
||||
}
|
||||
|
||||
case Column::Hostname:
|
||||
{
|
||||
return Server->Hostname.data();
|
||||
}
|
||||
|
||||
case Column::Mapname:
|
||||
{
|
||||
return Game::UI_LocalizeMapName(Server->Mapname.data());
|
||||
}
|
||||
|
||||
case Column::Players:
|
||||
{
|
||||
return Utils::VA("%i (%i)", Server->Clients, Server->MaxClients);
|
||||
}
|
||||
|
||||
case Column::Gametype:
|
||||
{
|
||||
if (Server->Mod != "")
|
||||
{
|
||||
return (Server->Mod.data() + 5);
|
||||
}
|
||||
|
||||
return Game::UI_LocalizeGameType(Server->Gametype.data());
|
||||
}
|
||||
|
||||
case Column::Ping:
|
||||
{
|
||||
return Utils::VA("%i", Server->Ping);
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
void ServerList::SelectServer(int index)
|
||||
{
|
||||
ServerList::CurrentServer = (unsigned int)index;
|
||||
}
|
||||
|
||||
void ServerList::Refresh()
|
||||
{
|
||||
ServerList::OnlineList.clear();
|
||||
|
||||
ServerList::RefreshContainer.Mutex.lock();
|
||||
ServerList::RefreshContainer.Servers.clear();
|
||||
ServerList::RefreshContainer.Mutex.unlock();
|
||||
|
||||
ServerList::RefreshContainer.SendCount = 0;
|
||||
ServerList::RefreshContainer.SentCount = 0;
|
||||
|
||||
ServerList::RefreshContainer.AwatingList = true;
|
||||
ServerList::RefreshContainer.AwaitTime = Game::Com_Milliseconds();
|
||||
|
||||
int masterPort = Dvar::Var("masterPort").Get<int>();
|
||||
const char* masterServerName = Dvar::Var("masterServerName").Get<const char*>();
|
||||
|
||||
ServerList::RefreshContainer.Host = Network::Address(Utils::VA("%s:%u", masterServerName, masterPort));
|
||||
|
||||
Logger::Print("Sending serverlist request to master: %s:%u\n", masterServerName, masterPort);
|
||||
|
||||
Network::Send(ServerList::RefreshContainer.Host, "getservers IW4 145 full empty");
|
||||
//Network::Send(ServerList::RefreshContainer.Host, "getservers 0 full empty\n");
|
||||
}
|
||||
|
||||
void ServerList::Insert(Network::Address address, Utils::InfoString info)
|
||||
{
|
||||
ServerList::RefreshContainer.Mutex.lock();
|
||||
|
||||
for (auto i = ServerList::RefreshContainer.Servers.begin(); i != ServerList::RefreshContainer.Servers.end(); i++)
|
||||
{
|
||||
// Our desired server
|
||||
if (i->Target == address && i->Sent)
|
||||
{
|
||||
// Challenge did not match
|
||||
if (i->Challenge != info.Get("challenge"))
|
||||
{
|
||||
// Shall we remove the server from the queue?
|
||||
// Better not, it might send a second response with the correct challenge.
|
||||
// This might happen when users refresh twice (or more often) in a short period of time
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: Implement deeper check like version and game
|
||||
ServerInfo server;
|
||||
server.Hostname = info.Get("hostname");
|
||||
server.Mapname = info.Get("mapname");
|
||||
server.Gametype = info.Get("gametype");
|
||||
server.Mod = info.Get("fs_game");
|
||||
server.MatchType = atoi(info.Get("matchtype").data());
|
||||
server.Clients = atoi(info.Get("clients").data());
|
||||
server.MaxClients = atoi(info.Get("sv_maxclients").data());
|
||||
server.Password = 0; // No info yet
|
||||
server.Ping = (Game::Com_Milliseconds() - i->SendTime);
|
||||
server.Addr = address;
|
||||
|
||||
// Check if already inserted and remove
|
||||
for (auto j = ServerList::OnlineList.begin(); j != ServerList::OnlineList.end(); j++)
|
||||
{
|
||||
if (j->Addr == address)
|
||||
{
|
||||
ServerList::OnlineList.erase(j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ServerList::OnlineList.push_back(server);
|
||||
|
||||
ServerList::RefreshContainer.Servers.erase(i);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ServerList::RefreshContainer.Mutex.unlock();
|
||||
}
|
||||
|
||||
void ServerList::Frame()
|
||||
{
|
||||
ServerList::RefreshContainer.Mutex.lock();
|
||||
|
||||
if (ServerList::RefreshContainer.AwatingList)
|
||||
{
|
||||
// Check if we haven't got a response within 10 seconds
|
||||
if (Game::Com_Milliseconds() - ServerList::RefreshContainer.AwaitTime > 5000)
|
||||
{
|
||||
ServerList::RefreshContainer.AwatingList = false;
|
||||
|
||||
Logger::Print("We haven't received a response from the master within %d seconds!\n", (Game::Com_Milliseconds() - ServerList::RefreshContainer.AwaitTime) / 1000);
|
||||
}
|
||||
}
|
||||
|
||||
// Send requests to 10 servers each frame
|
||||
int SendServers = 10;
|
||||
|
||||
for (unsigned int i = 0; i < ServerList::RefreshContainer.Servers.size(); i++)
|
||||
{
|
||||
ServerList::Container::ServerContainer* server = &ServerList::RefreshContainer.Servers[i];
|
||||
if (server->Sent) continue;
|
||||
|
||||
// Found server we can send a request to
|
||||
server->Sent = true;
|
||||
SendServers--;
|
||||
|
||||
server->SendTime = Game::Com_Milliseconds();
|
||||
server->Challenge = Utils::VA("%d", server->SendTime);
|
||||
|
||||
ServerList::RefreshContainer.SentCount++;
|
||||
|
||||
Network::Send(server->Target, Utils::VA("getinfo %s\n", server->Challenge.data()));
|
||||
|
||||
// Display in the menu, like in COD4
|
||||
//Logger::Print("Sent %d/%d\n", ServerList::RefreshContainer.SentCount, ServerList::RefreshContainer.SendCount);
|
||||
|
||||
if (SendServers <= 0) break;
|
||||
}
|
||||
|
||||
ServerList::RefreshContainer.Mutex.unlock();
|
||||
}
|
||||
|
||||
ServerList::ServerList()
|
||||
{
|
||||
ServerList::OnlineList.clear();
|
||||
|
||||
Network::Handle("getServersResponse", [] (Network::Address address, std::string data)
|
||||
{
|
||||
if (ServerList::RefreshContainer.Host != address) return; // Only parse from host we sent to
|
||||
|
||||
ServerList::RefreshContainer.AwatingList = false;
|
||||
|
||||
ServerList::RefreshContainer.Mutex.lock();
|
||||
|
||||
int offset = 0;
|
||||
int count = ServerList::RefreshContainer.Servers.size();
|
||||
ServerList::MasterEntry* entry = nullptr;
|
||||
|
||||
// Find first entry
|
||||
do
|
||||
{
|
||||
entry = (ServerList::MasterEntry*)(data.data() + offset++);
|
||||
}
|
||||
while (!entry->HasSeparator() && !entry->IsEndToken());
|
||||
|
||||
for (int i = 0; !entry[i].IsEndToken() && entry[i].HasSeparator(); i++)
|
||||
{
|
||||
Network::Address serverAddr = address;
|
||||
serverAddr.SetIP(entry[i].IP);
|
||||
serverAddr.SetPort(entry[i].Port);
|
||||
serverAddr.Get()->type = Game::NA_IP;
|
||||
|
||||
ServerList::Container::ServerContainer container;
|
||||
container.Sent = false;
|
||||
container.Target = serverAddr;
|
||||
|
||||
bool alreadyInserted = false;
|
||||
for (auto &server : ServerList::RefreshContainer.Servers)
|
||||
{
|
||||
if (server.Target == container.Target)
|
||||
{
|
||||
alreadyInserted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!alreadyInserted)
|
||||
{
|
||||
ServerList::RefreshContainer.Servers.push_back(container);
|
||||
ServerList::RefreshContainer.SendCount++;
|
||||
}
|
||||
}
|
||||
|
||||
Logger::Print("Parsed %d servers from master\n", ServerList::RefreshContainer.Servers.size() - count);
|
||||
|
||||
ServerList::RefreshContainer.Mutex.unlock();
|
||||
});
|
||||
|
||||
// Set default masterServerName + port and save it
|
||||
Utils::Hook::Set<const char*>(0x60AD92, "localhost");
|
||||
Utils::Hook::Set<BYTE>(0x60AD90, Game::dvar_flag::DVAR_FLAG_SAVED); // masterServerName
|
||||
Utils::Hook::Set<BYTE>(0x60ADC6, Game::dvar_flag::DVAR_FLAG_SAVED); // masterPort
|
||||
|
||||
// Add server list feeder
|
||||
UIFeeder::Add(2.0f, ServerList::GetServerCount, ServerList::GetServerText, ServerList::SelectServer);
|
||||
|
||||
// Add required UIScripts
|
||||
UIScript::Add("RefreshServers", ServerList::Refresh);
|
||||
UIScript::Add("JoinServer", [] ()
|
||||
{
|
||||
if (ServerList::OnlineList.size() > ServerList::CurrentServer)
|
||||
{
|
||||
Party::Connect(ServerList::OnlineList[ServerList::CurrentServer].Addr);
|
||||
}
|
||||
});
|
||||
UIScript::Add("ServerSort", [] (UIScript::Token token)
|
||||
{
|
||||
Logger::Print("Server list sorting by token: %d\n", token.Get<int>());
|
||||
});
|
||||
|
||||
// Add frame callback
|
||||
Renderer::OnFrame(ServerList::Frame);
|
||||
}
|
||||
|
||||
ServerList::~ServerList()
|
||||
{
|
||||
ServerList::OnlineList.clear();
|
||||
}
|
||||
}
|
94
src/Components/Modules/ServerList.hpp
Normal file
94
src/Components/Modules/ServerList.hpp
Normal file
@ -0,0 +1,94 @@
|
||||
namespace Components
|
||||
{
|
||||
class ServerList : public Component
|
||||
{
|
||||
public:
|
||||
struct ServerInfo
|
||||
{
|
||||
Network::Address Addr;
|
||||
bool Visible;
|
||||
std::string Hostname;
|
||||
std::string Mapname;
|
||||
std::string Gametype;
|
||||
std::string Mod;
|
||||
int Clients;
|
||||
int MaxClients;
|
||||
bool Password;
|
||||
int Ping;
|
||||
int MatchType;
|
||||
bool Hardcore;
|
||||
};
|
||||
|
||||
ServerList();
|
||||
~ServerList();
|
||||
const char* GetName() { return "ServerList"; };
|
||||
|
||||
static void Refresh();
|
||||
static void Insert(Network::Address address, Utils::InfoString info);
|
||||
|
||||
private:
|
||||
enum Column
|
||||
{
|
||||
Password,
|
||||
Hostname,
|
||||
Mapname,
|
||||
Players,
|
||||
Gametype,
|
||||
Ping,
|
||||
};
|
||||
|
||||
#pragma pack(push, 1)
|
||||
union MasterEntry
|
||||
{
|
||||
char Token[7];
|
||||
struct
|
||||
{
|
||||
uint32_t IP;
|
||||
uint16_t Port;
|
||||
};
|
||||
|
||||
bool IsEndToken()
|
||||
{
|
||||
// End of transmission or file token
|
||||
return (Token[0] == 'E' && Token[1] == 'O' && (Token[2] == 'T' || Token[2] == 'F'));
|
||||
}
|
||||
|
||||
bool HasSeparator()
|
||||
{
|
||||
return (Token[6] == '\\');
|
||||
}
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
struct Container
|
||||
{
|
||||
struct ServerContainer
|
||||
{
|
||||
bool Sent;
|
||||
int SendTime;
|
||||
std::string Challenge;
|
||||
Network::Address Target;
|
||||
};
|
||||
|
||||
bool AwatingList;
|
||||
int AwaitTime;
|
||||
|
||||
int SentCount;
|
||||
int SendCount;
|
||||
|
||||
Network::Address Host;
|
||||
std::vector<ServerContainer> Servers;
|
||||
std::mutex Mutex;
|
||||
};
|
||||
|
||||
static int GetServerCount();
|
||||
static const char* GetServerText(int index, int column);
|
||||
static void SelectServer(int index);
|
||||
|
||||
static void Frame();
|
||||
|
||||
static unsigned int CurrentServer;
|
||||
static Container RefreshContainer;
|
||||
static std::vector<ServerInfo> OnlineList;
|
||||
};
|
||||
}
|
23
src/Components/Modules/Singleton.cpp
Normal file
23
src/Components/Modules/Singleton.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
#include "..\..\STDInclude.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
bool Singleton::FirstInstance = true;
|
||||
|
||||
bool Singleton::IsFirstInstance()
|
||||
{
|
||||
return Singleton::FirstInstance;
|
||||
}
|
||||
|
||||
Singleton::Singleton()
|
||||
{
|
||||
if (Dedicated::IsDedicated()) return;
|
||||
|
||||
Singleton::FirstInstance = (CreateMutex(NULL, FALSE, "iw4x_mutex") && GetLastError() != ERROR_ALREADY_EXISTS);
|
||||
|
||||
if (!Singleton::FirstInstance && MessageBoxA(0, "Do you want to start a second instance?", "Game already running", MB_ICONEXCLAMATION | MB_YESNO) == IDNO)
|
||||
{
|
||||
ExitProcess(0);
|
||||
}
|
||||
}
|
||||
}
|
14
src/Components/Modules/Singleton.hpp
Normal file
14
src/Components/Modules/Singleton.hpp
Normal file
@ -0,0 +1,14 @@
|
||||
namespace Components
|
||||
{
|
||||
class Singleton : public Component
|
||||
{
|
||||
public:
|
||||
Singleton();
|
||||
const char* GetName() { return "Singleton"; };
|
||||
|
||||
static bool IsFirstInstance();
|
||||
|
||||
private:
|
||||
static bool FirstInstance;
|
||||
};
|
||||
}
|
285
src/Components/Modules/UIFeeder.cpp
Normal file
285
src/Components/Modules/UIFeeder.cpp
Normal file
@ -0,0 +1,285 @@
|
||||
#include "..\..\STDInclude.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
UIFeeder::Container UIFeeder::Current;
|
||||
std::map<float, UIFeeder::Callbacks> UIFeeder::Feeders;
|
||||
|
||||
void UIFeeder::Add(float feeder, UIFeeder::GetItemCount_t itemCountCb, UIFeeder::GetItemText_t itemTextCb, UIFeeder::Select_t selectCb)
|
||||
{
|
||||
UIFeeder::Feeders[feeder] = { itemCountCb, itemTextCb, selectCb };
|
||||
}
|
||||
|
||||
const char* UIFeeder::GetItemText()
|
||||
{
|
||||
if (UIFeeder::Feeders.find(UIFeeder::Current.Feeder) != UIFeeder::Feeders.end())
|
||||
{
|
||||
return UIFeeder::Feeders[UIFeeder::Current.Feeder].GetItemText(UIFeeder::Current.Index, UIFeeder::Current.Column);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int UIFeeder::GetItemCount()
|
||||
{
|
||||
if (UIFeeder::Feeders.find(UIFeeder::Current.Feeder) != UIFeeder::Feeders.end())
|
||||
{
|
||||
return UIFeeder::Feeders[UIFeeder::Current.Feeder].GetItemCount();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool UIFeeder::SetItemSelection()
|
||||
{
|
||||
if (UIFeeder::Feeders.find(UIFeeder::Current.Feeder) != UIFeeder::Feeders.end())
|
||||
{
|
||||
UIFeeder::Feeders[UIFeeder::Current.Feeder].Select(UIFeeder::Current.Index);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UIFeeder::CheckFeeder()
|
||||
{
|
||||
if (UIFeeder::Current.Feeder == 15.0f) return false;
|
||||
return (UIFeeder::Feeders.find(UIFeeder::Current.Feeder) != UIFeeder::Feeders.end());
|
||||
}
|
||||
|
||||
void __declspec(naked) UIFeeder::SetItemSelectionStub()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov eax, [esp + 08h]
|
||||
mov UIFeeder::Current.Feeder, eax
|
||||
|
||||
mov eax, [esp + 0Ch]
|
||||
mov UIFeeder::Current.Index, eax
|
||||
|
||||
call UIFeeder::SetItemSelection
|
||||
|
||||
test al, al
|
||||
jz continue
|
||||
|
||||
retn
|
||||
|
||||
continue:
|
||||
fld ds : 739FD0h
|
||||
|
||||
mov eax, 4C25D6h
|
||||
jmp eax
|
||||
}
|
||||
}
|
||||
|
||||
void __declspec(naked) UIFeeder::GetItemTextStub()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov eax, [esp + 0Ch]
|
||||
mov UIFeeder::Current.Feeder, eax
|
||||
|
||||
mov eax, [esp + 10h]
|
||||
mov UIFeeder::Current.Index, eax
|
||||
|
||||
mov eax, [esp + 14h]
|
||||
mov UIFeeder::Current.Column, eax
|
||||
|
||||
call UIFeeder::GetItemText
|
||||
|
||||
test eax, eax
|
||||
jz continue
|
||||
|
||||
push ebx
|
||||
mov ebx, [esp + 4 + 28h]
|
||||
mov dword ptr[ebx], 0
|
||||
pop ebx
|
||||
retn
|
||||
|
||||
continue:
|
||||
push ecx
|
||||
fld ds:739FD0h
|
||||
|
||||
mov eax, 4CE9E7h
|
||||
jmp eax
|
||||
}
|
||||
}
|
||||
|
||||
void __declspec(naked) UIFeeder::GetItemCountStub()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov eax, [esp + 8h]
|
||||
mov UIFeeder::Current.Feeder, eax
|
||||
|
||||
call UIFeeder::GetItemCount
|
||||
|
||||
test eax, eax
|
||||
jz continue
|
||||
|
||||
retn
|
||||
|
||||
continue:
|
||||
push ecx
|
||||
fld ds:739FD0h
|
||||
|
||||
mov eax, 41A0D7h
|
||||
jmp eax;
|
||||
}
|
||||
}
|
||||
|
||||
void __declspec(naked) UIFeeder::HandleKeyStub()
|
||||
{
|
||||
static int NextClickTime = 0;
|
||||
|
||||
__asm
|
||||
{
|
||||
mov ebx, ebp
|
||||
mov eax, [ebp + 12Ch]
|
||||
mov UIFeeder::Current.Feeder, eax
|
||||
|
||||
push ebx
|
||||
call UIFeeder::CheckFeeder
|
||||
pop ebx
|
||||
|
||||
test al, al
|
||||
jz continueOriginal
|
||||
|
||||
// Get current milliseconds
|
||||
call Game::Com_Milliseconds
|
||||
|
||||
// Check if allowed to click
|
||||
cmp eax, NextClickTime
|
||||
jl continueOriginal
|
||||
|
||||
// Set next allowed click time to current time + 300ms
|
||||
add eax, 300
|
||||
mov NextClickTime, eax
|
||||
|
||||
// Get item cursor position ptr
|
||||
mov ecx, ebx
|
||||
add ecx, Game::itemDef_t::cursorPos
|
||||
|
||||
// Get item listbox ptr
|
||||
mov edx, ebx
|
||||
add edx, Game::itemDef_t::typeData
|
||||
|
||||
// Get listbox cursor pos
|
||||
mov edx, [edx]
|
||||
add edx, Game::listBoxDef_s::startPos
|
||||
mov edx, [edx]
|
||||
|
||||
// Resolve item cursor pos pointer
|
||||
mov ebx, [ecx]
|
||||
|
||||
// Check if item cursor pos equals listbox cursor pos
|
||||
cmp ebx, edx
|
||||
je returnSafe
|
||||
|
||||
// Update indices if not
|
||||
mov [ecx], edx
|
||||
mov UIFeeder::Current.Index, edx
|
||||
|
||||
call UIFeeder::SetItemSelection
|
||||
|
||||
returnSafe:
|
||||
retn
|
||||
|
||||
continueOriginal:
|
||||
mov eax, 635570h
|
||||
jmp eax
|
||||
}
|
||||
}
|
||||
|
||||
void __declspec(naked) UIFeeder::MouseEnterStub()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov eax, [edi + 12Ch]
|
||||
mov UIFeeder::Current.Feeder, eax
|
||||
|
||||
call UIFeeder::CheckFeeder
|
||||
|
||||
test al, al
|
||||
jnz continue
|
||||
|
||||
mov[edi + 130h], esi
|
||||
|
||||
continue:
|
||||
mov eax, 639D75h
|
||||
jmp eax
|
||||
}
|
||||
}
|
||||
|
||||
void __declspec(naked) UIFeeder::MouseSelectStub()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov eax, [esp + 08h]
|
||||
mov UIFeeder::Current.Feeder, eax
|
||||
|
||||
call UIFeeder::CheckFeeder
|
||||
|
||||
test al, al
|
||||
jnz continue
|
||||
|
||||
mov eax, 4C25D0h
|
||||
jmp eax
|
||||
|
||||
continue:
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
void __declspec(naked) UIFeeder::PlaySoundStub()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov eax, [edi + 12Ch]
|
||||
mov UIFeeder::Current.Feeder, eax
|
||||
|
||||
call UIFeeder::CheckFeeder
|
||||
|
||||
test al, al
|
||||
jnz continue
|
||||
|
||||
mov eax, 685E10h
|
||||
jmp eax
|
||||
|
||||
continue:
|
||||
retn
|
||||
}
|
||||
}
|
||||
|
||||
UIFeeder::UIFeeder()
|
||||
{
|
||||
// Get feeder item count
|
||||
Utils::Hook(0x41A0D0, UIFeeder::GetItemCountStub, HOOK_JUMP).Install()->Quick();
|
||||
|
||||
// Get feeder item text
|
||||
Utils::Hook(0x4CE9E0, UIFeeder::GetItemTextStub, HOOK_JUMP).Install()->Quick();
|
||||
|
||||
// Select feeder item
|
||||
Utils::Hook(0x4C25D0, UIFeeder::SetItemSelectionStub, HOOK_JUMP).Install()->Quick();
|
||||
|
||||
// Mouse enter check
|
||||
Utils::Hook(0x639D6E, UIFeeder::MouseEnterStub, HOOK_JUMP).Install()->Quick();
|
||||
|
||||
// Handle key event
|
||||
Utils::Hook(0x63C5BC, UIFeeder::HandleKeyStub, HOOK_CALL).Install()->Quick();
|
||||
|
||||
// Mouse select check
|
||||
Utils::Hook(0x639D31, UIFeeder::MouseSelectStub, HOOK_CALL).Install()->Quick();
|
||||
|
||||
// Play mouse over sound check
|
||||
Utils::Hook(0x639D66, UIFeeder::PlaySoundStub, HOOK_CALL).Install()->Quick();
|
||||
|
||||
// some thing overwriting feeder 2's data
|
||||
Utils::Hook::Set<BYTE>(0x4A06A9, 0xEB);
|
||||
}
|
||||
|
||||
UIFeeder::~UIFeeder()
|
||||
{
|
||||
UIFeeder::Feeders.clear();
|
||||
}
|
||||
}
|
51
src/Components/Modules/UIFeeder.hpp
Normal file
51
src/Components/Modules/UIFeeder.hpp
Normal file
@ -0,0 +1,51 @@
|
||||
namespace Components
|
||||
{
|
||||
class UIFeeder : public Component
|
||||
{
|
||||
public:
|
||||
typedef int(__cdecl * GetItemCount_t)();
|
||||
typedef const char* (__cdecl * GetItemText_t)(int index, int column);
|
||||
typedef void(__cdecl * Select_t)(int index);
|
||||
|
||||
struct Callbacks
|
||||
{
|
||||
GetItemCount_t GetItemCount;
|
||||
GetItemText_t GetItemText;
|
||||
Select_t Select;
|
||||
};
|
||||
|
||||
UIFeeder();
|
||||
~UIFeeder();
|
||||
const char* GetName() { return "UIFeeder"; };
|
||||
|
||||
static void Add(float feeder, GetItemCount_t itemCountCb, GetItemText_t itemTextCb, Select_t selectCb);
|
||||
|
||||
private:
|
||||
struct Container
|
||||
{
|
||||
float Feeder;
|
||||
int Index;
|
||||
int Column;
|
||||
};
|
||||
|
||||
static Container Current;
|
||||
|
||||
static void GetItemCountStub();
|
||||
static int GetItemCount();
|
||||
|
||||
static void GetItemTextStub();
|
||||
static const char* GetItemText();
|
||||
|
||||
static void SetItemSelectionStub();
|
||||
static bool SetItemSelection();
|
||||
|
||||
static bool CheckFeeder();
|
||||
|
||||
static void MouseEnterStub();
|
||||
static void MouseSelectStub();
|
||||
static void HandleKeyStub();
|
||||
static void PlaySoundStub();
|
||||
|
||||
static std::map<float, Callbacks> Feeders;
|
||||
};
|
||||
}
|
110
src/Components/Modules/UIScript.cpp
Normal file
110
src/Components/Modules/UIScript.cpp
Normal file
@ -0,0 +1,110 @@
|
||||
#include "..\..\STDInclude.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
std::map<std::string, UIScript::Callback> UIScript::UIScripts;
|
||||
|
||||
template<> int UIScript::Token::Get()
|
||||
{
|
||||
if (this->IsValid())
|
||||
{
|
||||
return atoi(this->token);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<> char* UIScript::Token::Get()
|
||||
{
|
||||
if (this->IsValid())
|
||||
{
|
||||
return this->token;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
template<> const char* UIScript::Token::Get()
|
||||
{
|
||||
return this->Get<char*>();
|
||||
}
|
||||
|
||||
template<> std::string UIScript::Token::Get()
|
||||
{
|
||||
return this->Get<const char*>();
|
||||
}
|
||||
|
||||
bool UIScript::Token::IsValid()
|
||||
{
|
||||
return (token && token[0]);
|
||||
}
|
||||
|
||||
void UIScript::Token::Parse(const char** args)
|
||||
{
|
||||
if (args)
|
||||
{
|
||||
this->token = Game::Com_ParseExt(args);
|
||||
}
|
||||
}
|
||||
|
||||
void UIScript::Add(std::string name, UIScript::Callback callback)
|
||||
{
|
||||
UIScript::UIScripts[name] = callback;
|
||||
}
|
||||
|
||||
void UIScript::Add(std::string name, UIScript::CallbackRaw callback)
|
||||
{
|
||||
UIScript::Add(name, reinterpret_cast<UIScript::Callback>(callback));
|
||||
}
|
||||
|
||||
bool UIScript::RunMenuScript(const char* name, const char** args)
|
||||
{
|
||||
if (UIScript::UIScripts.find(name) != UIScript::UIScripts.end())
|
||||
{
|
||||
UIScript::UIScripts[name](UIScript::Token(args));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void __declspec(naked) UIScript::RunMenuScriptStub()
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov eax, esp
|
||||
add eax, 8h
|
||||
mov edx, eax // UIScript name
|
||||
mov eax, [esp + 0C10h] // UIScript args
|
||||
|
||||
push eax
|
||||
push edx
|
||||
call UIScript::RunMenuScript
|
||||
add esp, 8h
|
||||
|
||||
test al, al
|
||||
jz continue
|
||||
|
||||
// if returned
|
||||
pop edi
|
||||
pop esi
|
||||
add esp, 0C00h
|
||||
retn
|
||||
|
||||
continue:
|
||||
mov eax, 45ED00h
|
||||
jmp eax
|
||||
}
|
||||
}
|
||||
|
||||
UIScript::UIScript()
|
||||
{
|
||||
// Install handler
|
||||
Utils::Hook::Set<int>(0x45EC5B, (DWORD)UIScript::RunMenuScriptStub - 0x45EC59 - 6);
|
||||
}
|
||||
|
||||
UIScript::~UIScript()
|
||||
{
|
||||
UIScript::UIScripts.clear();
|
||||
}
|
||||
}
|
39
src/Components/Modules/UIScript.hpp
Normal file
39
src/Components/Modules/UIScript.hpp
Normal file
@ -0,0 +1,39 @@
|
||||
namespace Components
|
||||
{
|
||||
class UIScript : public Component
|
||||
{
|
||||
public:
|
||||
UIScript();
|
||||
~UIScript();
|
||||
const char* GetName() { return "UIScript"; };
|
||||
|
||||
class Token
|
||||
{
|
||||
public:
|
||||
Token(const char** args) : token(0) { this->Parse(args); };
|
||||
Token(const Token &obj) { this->token = obj.token; };
|
||||
|
||||
template<typename T> T Get();
|
||||
bool IsValid();
|
||||
|
||||
|
||||
private:
|
||||
char* token;
|
||||
|
||||
void Parse(const char** args);
|
||||
};
|
||||
|
||||
typedef void(*Callback)(Token token);
|
||||
typedef void(*CallbackRaw)();
|
||||
|
||||
static void Add(std::string name, Callback callback);
|
||||
static void Add(std::string name, CallbackRaw callback);
|
||||
|
||||
private:
|
||||
|
||||
static bool RunMenuScript(const char* name, const char** args);
|
||||
static void RunMenuScriptStub();
|
||||
|
||||
static std::map<std::string, Callback> UIScripts;
|
||||
};
|
||||
}
|
27
src/Components/Modules/Window.cpp
Normal file
27
src/Components/Modules/Window.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
#include "..\..\STDInclude.hpp"
|
||||
|
||||
namespace Components
|
||||
{
|
||||
Dvar::Var Window::NoBorder;
|
||||
|
||||
void __declspec(naked) Window::StyleHookStub()
|
||||
{
|
||||
if (Window::NoBorder.Get<bool>())
|
||||
{
|
||||
__asm mov ebp, WS_VISIBLE | WS_POPUP
|
||||
}
|
||||
else
|
||||
{
|
||||
__asm mov ebp, WS_VISIBLE | WS_SYSMENU | WS_CAPTION
|
||||
}
|
||||
|
||||
__asm retn
|
||||
}
|
||||
|
||||
Window::Window()
|
||||
{
|
||||
// Borderless window
|
||||
Window::NoBorder = Dvar::Register<bool>("r_noborder", true, Game::dvar_flag::DVAR_FLAG_SAVED, "Do not use a border in windowed mode");
|
||||
Utils::Hook(0x507643, Window::StyleHookStub, HOOK_CALL).Install()->Quick();
|
||||
}
|
||||
}
|
12
src/Components/Modules/Window.hpp
Normal file
12
src/Components/Modules/Window.hpp
Normal file
@ -0,0 +1,12 @@
|
||||
namespace Components
|
||||
{
|
||||
class Window : public Component
|
||||
{
|
||||
public:
|
||||
Window();
|
||||
const char* GetName() { return "Window"; };
|
||||
|
||||
static Dvar::Var NoBorder;
|
||||
static void Window::StyleHookStub();
|
||||
};
|
||||
}
|
180
src/Game/Functions.cpp
Normal file
180
src/Game/Functions.cpp
Normal file
@ -0,0 +1,180 @@
|
||||
#include "..\STDInclude.hpp"
|
||||
|
||||
namespace Game
|
||||
{
|
||||
Cbuf_AddText_t Cbuf_AddText = (Cbuf_AddText_t)0x404B20;
|
||||
|
||||
CL_IsCgameInitialized_t CL_IsCgameInitialized = (CL_IsCgameInitialized_t)0x43EB20;
|
||||
CL_ConnectFromParty_t CL_ConnectFromParty = (CL_ConnectFromParty_t)0x433D30;
|
||||
|
||||
Cmd_AddCommand_t Cmd_AddCommand = (Cmd_AddCommand_t)0x470090;
|
||||
Cmd_ExecuteSingleCommand_t Cmd_ExecuteSingleCommand = (Cmd_ExecuteSingleCommand_t)0x609540;
|
||||
|
||||
Com_Error_t Com_Error = (Com_Error_t)0x4B22D0;
|
||||
Com_Printf_t Com_Printf = (Com_Printf_t)0x402500;
|
||||
Com_Milliseconds_t Com_Milliseconds = (Com_Milliseconds_t)0x42A660;
|
||||
Com_ParseExt_t Com_ParseExt = (Com_ParseExt_t)0x474D60;
|
||||
|
||||
DB_FindXAssetHeader_t DB_FindXAssetHeader = (DB_FindXAssetHeader_t)0x407930;
|
||||
DB_GetXAssetNameHandler_t* DB_GetXAssetNameHandlers = (DB_GetXAssetNameHandler_t*)0x799328;
|
||||
DB_GetXAssetSizeHandler_t* DB_GetXAssetSizeHandlers = (DB_GetXAssetSizeHandler_t*)0x799488;
|
||||
DB_LoadXAssets_t DB_LoadXAssets = (DB_LoadXAssets_t)0x4E5930;
|
||||
|
||||
Dvar_RegisterBool_t Dvar_RegisterBool = (Dvar_RegisterBool_t)0x4CE1A0;
|
||||
Dvar_RegisterFloat_t Dvar_RegisterFloat = (Dvar_RegisterFloat_t)0x648440;
|
||||
Dvar_RegisterFloat2_t Dvar_RegisterFloat2 = (Dvar_RegisterFloat2_t)0x4F6070;
|
||||
Dvar_RegisterFloat3_t Dvar_RegisterFloat3 = (Dvar_RegisterFloat3_t)0x4EF8E0;
|
||||
Dvar_RegisterFloat4_t Dvar_RegisterFloat4 = (Dvar_RegisterFloat4_t)0x4F28E0;
|
||||
Dvar_RegisterInt_t Dvar_RegisterInt = (Dvar_RegisterInt_t)0x479830;
|
||||
Dvar_RegisterEnum_t Dvar_RegisterEnum = (Dvar_RegisterEnum_t)0x412E40;
|
||||
Dvar_RegisterString_t Dvar_RegisterString = (Dvar_RegisterString_t)0x4FC7E0;
|
||||
Dvar_RegisterColor_t Dvar_RegisterColor = (Dvar_RegisterColor_t)0x471500;
|
||||
|
||||
Dvar_FindVar_t Dvar_FindVar = (Dvar_FindVar_t)0x4D5390;
|
||||
Dvar_SetCommand_t Dvar_SetCommand = (Dvar_SetCommand_t)0x4EE430;
|
||||
|
||||
Field_Clear_t Field_Clear = (Field_Clear_t)0x437EB0;
|
||||
|
||||
FreeMemory_t FreeMemory = (FreeMemory_t)0x4D6640;
|
||||
|
||||
FS_FileExists_t FS_FileExists = (FS_FileExists_t)0x4DEFA0;
|
||||
FS_FreeFile_t FS_FreeFile = (FS_FreeFile_t)0x4416B0;
|
||||
FS_ReadFile_t FS_ReadFile = (FS_ReadFile_t)0x4F4B90;
|
||||
FS_ListFiles_t FS_ListFiles = (FS_ListFiles_t)0x441BB0;
|
||||
FS_FreeFileList_t FS_FreeFileList = (FS_FreeFileList_t)0x4A5DE0;
|
||||
FS_FOpenFileAppend_t FS_FOpenFileAppend = (FS_FOpenFileAppend_t)0x410BB0;
|
||||
FS_FOpenFileAppend_t FS_FOpenFileWrite = (FS_FOpenFileAppend_t)0x4BA530;
|
||||
FS_FOpenFileRead_t FS_FOpenFileRead = (FS_FOpenFileRead_t)0x46CBF0;
|
||||
FS_FCloseFile_t FS_FCloseFile = (FS_FCloseFile_t)0x462000;
|
||||
FS_WriteFile_t FS_WriteFile = (FS_WriteFile_t)0x426450;
|
||||
FS_Write_t FS_Write = (FS_Write_t)0x4C06E0;
|
||||
FS_Read_t FS_Read = (FS_Read_t)0x4A04C0;
|
||||
FS_Seek_t FS_Seek = (FS_Seek_t)0x4A63D0;
|
||||
FS_FTell_t FS_FTell = (FS_FTell_t)0x4E6760;
|
||||
FS_Remove_t FS_Remove = (FS_Remove_t)0x4660F0;
|
||||
FS_Restart_t FS_Restart = (FS_Restart_t)0x461A50;
|
||||
FS_BuildPathToFile_t FS_BuildPathToFile = (FS_BuildPathToFile_t)0x4702C0;
|
||||
|
||||
Menus_CloseAll_t Menus_CloseAll = (Menus_CloseAll_t)0x4BA5B0;
|
||||
Menus_OpenByName_t Menus_OpenByName = (Menus_OpenByName_t)0x4CCE60;
|
||||
|
||||
NET_AdrToString_t NET_AdrToString = (NET_AdrToString_t)0x469880;
|
||||
NET_CompareAdr_t NET_CompareAdr = (NET_CompareAdr_t)0x4D0AA0;
|
||||
NET_StringToAdr_t NET_StringToAdr = (NET_StringToAdr_t)0x409010;
|
||||
|
||||
Live_MPAcceptInvite_t Live_MPAcceptInvite = (Live_MPAcceptInvite_t)0x420A6D;
|
||||
|
||||
LoadInitialFF_t LoadInitialFF = (LoadInitialFF_t)0x506AC0;
|
||||
LoadModdableRawfile_t LoadModdableRawfile = (LoadModdableRawfile_t)0x61ABC0;
|
||||
|
||||
LocalizeString_t LocalizeString = (LocalizeString_t)0x4FB010;
|
||||
LocalizeMapString_t LocalizeMapString = (LocalizeMapString_t)0x44BB30;
|
||||
|
||||
sendOOB_t OOBPrint = (sendOOB_t)0x4AEF00;
|
||||
|
||||
PC_ReadToken_t PC_ReadToken = (PC_ReadToken_t)0x4ACCD0;
|
||||
PC_ReadTokenHandle_t PC_ReadTokenHandle = (PC_ReadTokenHandle_t)0x4D2060;
|
||||
PC_SourceError_t PC_SourceError = (PC_SourceError_t)0x467A00;
|
||||
|
||||
PartyHost_GetMemberAddressBySlot_t PartyHost_GetMemberAddressBySlot = (PartyHost_GetMemberAddressBySlot_t)0x44E100;
|
||||
|
||||
Script_Alloc_t Script_Alloc = (Script_Alloc_t)0x422E70;
|
||||
Script_SetupTokens_t Script_SetupTokens = (Script_SetupTokens_t)0x4E6950;
|
||||
Script_CleanString_t Script_CleanString = (Script_CleanString_t)0x498220;
|
||||
|
||||
SetConsole_t SetConsole = (SetConsole_t)0x44F060;
|
||||
|
||||
Steam_JoinLobby_t Steam_JoinLobby = (Steam_JoinLobby_t)0x49CF70;
|
||||
|
||||
UI_AddMenuList_t UI_AddMenuList = (UI_AddMenuList_t)0x4533C0;
|
||||
|
||||
Win_GetLanguage_t Win_GetLanguage = (Win_GetLanguage_t)0x45CBA0;
|
||||
|
||||
void** DB_XAssetPool = (void**)0x7998A8;
|
||||
unsigned int* g_poolSize = (unsigned int*)0x7995E8;
|
||||
|
||||
DWORD* cmd_id = (DWORD*)0x1AAC5D0;
|
||||
DWORD* cmd_argc = (DWORD*)0x1AAC614;
|
||||
char*** cmd_argv = (char***)0x1AAC634;
|
||||
|
||||
source_t **sourceFiles = (source_t **)0x7C4A98;
|
||||
keywordHash_t **menuParseKeywordHash = (keywordHash_t **)0x63AE928;
|
||||
|
||||
int* svs_numclients = (int*)0x31D938C;
|
||||
client_t* svs_clients = (client_t*)0x31D9390;
|
||||
|
||||
UiContext *uiContext = (UiContext *)0x62E2858;
|
||||
|
||||
int* arenaCount = (int*)0x62E6930;
|
||||
mapArena_t* arenas = (mapArena_t*)0x62E6934;
|
||||
|
||||
int* gameTypeCount = (int*)0x62E50A0;
|
||||
gameTypeName_t* gameTypes = (gameTypeName_t*)0x62E50A4;
|
||||
|
||||
XBlock** g_streamBlocks = (XBlock**)0x16E554C;
|
||||
|
||||
void* ReallocateAssetPool(XAssetType type, unsigned int newSize)
|
||||
{
|
||||
int elSize = DB_GetXAssetSizeHandlers[type]();
|
||||
void* poolEntry = new char[newSize * elSize];
|
||||
DB_XAssetPool[type] = poolEntry;
|
||||
g_poolSize[type] = newSize;
|
||||
return poolEntry;
|
||||
}
|
||||
|
||||
void Menu_FreeItemMemory(Game::itemDef_t* item)
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov edi, item
|
||||
mov eax, 63D880h
|
||||
call eax
|
||||
}
|
||||
}
|
||||
|
||||
void OOBPrintT(int type, netadr_t netadr, const char* message)
|
||||
{
|
||||
int* adr = (int*)&netadr;
|
||||
|
||||
OOBPrint(type, *adr, *(adr + 1), *(adr + 2), 0xFFFFFFFF, *(adr + 4), message);
|
||||
}
|
||||
|
||||
const char* UI_LocalizeMapName(const char* mapName)
|
||||
{
|
||||
for (int i = 0; i < *arenaCount; i++)
|
||||
{
|
||||
if (!_stricmp(arenas[i].mapName, mapName))
|
||||
{
|
||||
char* uiName = &arenas[i].uiName[0];
|
||||
if ((uiName[0] == 'M' && uiName[1] == 'P') || (uiName[0] == 'P' && uiName[1] == 'A')) // MPUI/PATCH
|
||||
{
|
||||
char* name = LocalizeMapString(uiName);
|
||||
return name;
|
||||
}
|
||||
|
||||
return uiName;
|
||||
}
|
||||
}
|
||||
|
||||
return mapName;
|
||||
}
|
||||
|
||||
const char* UI_LocalizeGameType(const char* gameType)
|
||||
{
|
||||
if (gameType == 0 || *gameType == '\0')
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
for (int i = 0; i < *gameTypeCount; i++)
|
||||
{
|
||||
if (!_stricmp(gameTypes[i].gameType, gameType))
|
||||
{
|
||||
char* name = LocalizeMapString(gameTypes[i].uiName);
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
return gameType;
|
||||
}
|
||||
}
|
224
src/Game/Functions.hpp
Normal file
224
src/Game/Functions.hpp
Normal file
@ -0,0 +1,224 @@
|
||||
namespace Game
|
||||
{
|
||||
typedef void(__cdecl * Cbuf_AddText_t)(int a1, const char* cmd);
|
||||
extern Cbuf_AddText_t Cbuf_AddText;
|
||||
|
||||
typedef int(__cdecl * CL_IsCgameInitialized_t)();
|
||||
extern CL_IsCgameInitialized_t CL_IsCgameInitialized;
|
||||
|
||||
typedef void(__cdecl * CL_ConnectFromParty_t)(int controller, void*, netadr_t adr, int, int, const char*, const char*);
|
||||
extern CL_ConnectFromParty_t CL_ConnectFromParty;
|
||||
|
||||
typedef void(__cdecl * Cmd_AddCommand_t)(const char* name, void(*callback), cmd_function_t* data, char);
|
||||
extern Cmd_AddCommand_t Cmd_AddCommand;
|
||||
|
||||
typedef void(__cdecl * Cmd_ExecuteSingleCommand_t)(int controller, int a2, const char* cmd);
|
||||
extern Cmd_ExecuteSingleCommand_t Cmd_ExecuteSingleCommand;
|
||||
|
||||
typedef void(__cdecl * Com_Error_t)(int type, char* message, ...);
|
||||
extern Com_Error_t Com_Error;
|
||||
|
||||
typedef void(__cdecl * Com_Printf_t)(int, const char*, ...);
|
||||
extern Com_Printf_t Com_Printf;
|
||||
|
||||
typedef int(__cdecl * Com_Milliseconds_t)(void);
|
||||
extern Com_Milliseconds_t Com_Milliseconds;
|
||||
|
||||
typedef char* (__cdecl * Com_ParseExt_t)(const char**);
|
||||
extern Com_ParseExt_t Com_ParseExt;
|
||||
|
||||
typedef XAssetHeader (__cdecl * DB_FindXAssetHeader_t)(XAssetType type, const char* filename);
|
||||
extern DB_FindXAssetHeader_t DB_FindXAssetHeader;
|
||||
|
||||
typedef const char* (__cdecl * DB_GetXAssetNameHandler_t)(Game::XAssetHeader* asset);
|
||||
extern DB_GetXAssetNameHandler_t* DB_GetXAssetNameHandlers;
|
||||
|
||||
typedef int(__cdecl * DB_GetXAssetSizeHandler_t)();
|
||||
extern DB_GetXAssetSizeHandler_t* DB_GetXAssetSizeHandlers;
|
||||
|
||||
typedef void(*DB_LoadXAssets_t)(XZoneInfo *zoneInfo, unsigned int zoneCount, int sync);
|
||||
extern DB_LoadXAssets_t DB_LoadXAssets;
|
||||
|
||||
typedef dvar_t* (__cdecl * Dvar_RegisterBool_t)(const char* name, bool default, int flags, const char* description);
|
||||
extern Dvar_RegisterBool_t Dvar_RegisterBool;
|
||||
|
||||
typedef dvar_t* (__cdecl * Dvar_RegisterFloat_t)(const char* name, float default, float min, float max, int flags, const char* description);
|
||||
extern Dvar_RegisterFloat_t Dvar_RegisterFloat;
|
||||
|
||||
typedef dvar_t* (__cdecl * Dvar_RegisterFloat2_t)(const char* name, float defx, float defy, float min, float max, int flags, const char* description);
|
||||
extern Dvar_RegisterFloat2_t Dvar_RegisterFloat2;
|
||||
|
||||
typedef dvar_t* (__cdecl * Dvar_RegisterFloat3_t)(const char* name, float defx, float defy, float defz, float min, float max, int flags, const char* description);
|
||||
extern Dvar_RegisterFloat3_t Dvar_RegisterFloat3;
|
||||
|
||||
typedef dvar_t* (__cdecl * Dvar_RegisterFloat4_t)(const char* name, float defx, float defy, float defz, float defw, float min, float max, int flags, const char* description);
|
||||
extern Dvar_RegisterFloat4_t Dvar_RegisterFloat4;
|
||||
|
||||
typedef dvar_t* (__cdecl * Dvar_RegisterInt_t)(const char* name, int default, int min, int max, int flags, const char* description);
|
||||
extern Dvar_RegisterInt_t Dvar_RegisterInt;
|
||||
|
||||
typedef dvar_t* (__cdecl * Dvar_RegisterEnum_t)(const char* name, char** enumValues, int default, int flags, const char* description);
|
||||
extern Dvar_RegisterEnum_t Dvar_RegisterEnum;
|
||||
|
||||
typedef dvar_t* (__cdecl * Dvar_RegisterString_t)(const char* name, const char* default, int, const char*);
|
||||
extern Dvar_RegisterString_t Dvar_RegisterString;
|
||||
|
||||
typedef dvar_t* (__cdecl * Dvar_RegisterColor_t)(const char* name, float r, float g, float b, float a, int flags, const char* description);
|
||||
extern Dvar_RegisterColor_t Dvar_RegisterColor;
|
||||
|
||||
typedef dvar_t* (__cdecl * Dvar_FindVar_t)(const char *dvarName);
|
||||
extern Dvar_FindVar_t Dvar_FindVar;
|
||||
|
||||
typedef dvar_t* (__cdecl * Dvar_SetCommand_t)(const char* name, const char* value);
|
||||
extern Dvar_SetCommand_t Dvar_SetCommand;
|
||||
|
||||
typedef void(__cdecl * Field_Clear_t)(void* field);
|
||||
extern Field_Clear_t Field_Clear;
|
||||
|
||||
typedef void(__cdecl * FreeMemory_t)(void* buffer);
|
||||
extern FreeMemory_t FreeMemory;
|
||||
|
||||
typedef void(__cdecl * FS_FreeFile_t)(void* buffer);
|
||||
extern FS_FreeFile_t FS_FreeFile;
|
||||
|
||||
typedef int(__cdecl * FS_ReadFile_t)(const char* path, char** buffer);
|
||||
extern FS_ReadFile_t FS_ReadFile;
|
||||
|
||||
typedef char** (__cdecl * FS_ListFiles_t)(const char *path, const char *extension, FsListBehavior_e behavior, int *numfiles, int allocTrackType);
|
||||
extern FS_ListFiles_t FS_ListFiles;
|
||||
|
||||
typedef void(__cdecl * FS_FreeFileList_t)(char** list);
|
||||
extern FS_FreeFileList_t FS_FreeFileList;
|
||||
|
||||
typedef int(__cdecl * FS_FOpenFileAppend_t)(char* file);
|
||||
extern FS_FOpenFileAppend_t FS_FOpenFileAppend;
|
||||
extern FS_FOpenFileAppend_t FS_FOpenFileWrite;
|
||||
|
||||
typedef int(__cdecl * FS_FOpenFileRead_t)(const char* file, int* fh, int uniqueFile);
|
||||
extern FS_FOpenFileRead_t FS_FOpenFileRead;
|
||||
|
||||
typedef int(__cdecl * FS_FCloseFile_t)(int fh);
|
||||
extern FS_FCloseFile_t FS_FCloseFile;
|
||||
|
||||
typedef bool(__cdecl * FS_FileExists_t)(const char* file);
|
||||
extern FS_FileExists_t FS_FileExists;
|
||||
|
||||
typedef bool(__cdecl * FS_WriteFile_t)(char* filename, char* folder, void* buffer, int size);
|
||||
extern FS_WriteFile_t FS_WriteFile;
|
||||
|
||||
typedef int(__cdecl * FS_Write_t)(void* buffer, size_t size, int file);
|
||||
extern FS_Write_t FS_Write;
|
||||
|
||||
typedef int(__cdecl * FS_Read_t)(void* buffer, size_t size, int file);
|
||||
extern FS_Read_t FS_Read;
|
||||
|
||||
typedef int(__cdecl * FS_Seek_t)(int fileHandle, int seekPosition, int seekOrigin);
|
||||
extern FS_Seek_t FS_Seek;
|
||||
|
||||
typedef int(__cdecl * FS_FTell_t)(int fileHandle);
|
||||
extern FS_FTell_t FS_FTell;
|
||||
|
||||
typedef int(__cdecl * FS_Remove_t)(char *);
|
||||
extern FS_Remove_t FS_Remove;
|
||||
|
||||
typedef int(__cdecl * FS_Restart_t)(int a1, int a2);
|
||||
extern FS_Restart_t FS_Restart;
|
||||
|
||||
typedef int(__cdecl * FS_BuildPathToFile_t)(const char*, const char*, const char*, char**);
|
||||
extern FS_BuildPathToFile_t FS_BuildPathToFile;
|
||||
|
||||
typedef void(__cdecl * Menus_CloseAll_t)(UiContext *dc);
|
||||
extern Menus_CloseAll_t Menus_CloseAll;
|
||||
|
||||
typedef int(__cdecl * Menus_OpenByName_t)(UiContext *dc, const char *p);
|
||||
extern Menus_OpenByName_t Menus_OpenByName;
|
||||
|
||||
typedef const char* (__cdecl * NET_AdrToString_t)(netadr_t adr);
|
||||
extern NET_AdrToString_t NET_AdrToString;
|
||||
|
||||
typedef bool(__cdecl * NET_CompareAdr_t)(netadr_t, netadr_t);
|
||||
extern NET_CompareAdr_t NET_CompareAdr;
|
||||
|
||||
typedef bool(__cdecl * NET_StringToAdr_t)(const char*, netadr_t*);
|
||||
extern NET_StringToAdr_t NET_StringToAdr;
|
||||
|
||||
typedef void(__cdecl * Live_MPAcceptInvite_t)(_XSESSION_INFO *hostInfo, const int controllerIndex, bool fromGameInvite);
|
||||
extern Live_MPAcceptInvite_t Live_MPAcceptInvite;
|
||||
|
||||
typedef void(*LoadInitialFF_t)(void);
|
||||
extern LoadInitialFF_t LoadInitialFF;
|
||||
|
||||
typedef void* (__cdecl * LoadModdableRawfile_t)(int a1, const char* filename);
|
||||
extern LoadModdableRawfile_t LoadModdableRawfile;
|
||||
|
||||
typedef char* (__cdecl * LocalizeString_t)(char*, char*);
|
||||
extern LocalizeString_t LocalizeString;
|
||||
|
||||
typedef char* (__cdecl * LocalizeMapString_t)(char*);
|
||||
extern LocalizeMapString_t LocalizeMapString;
|
||||
|
||||
typedef void(__cdecl* sendOOB_t)(int, int, int, int, int, int, const char*);
|
||||
extern sendOOB_t OOBPrint;
|
||||
|
||||
typedef int(__cdecl * PC_ReadToken_t)(source_t*, token_t*);
|
||||
extern PC_ReadToken_t PC_ReadToken;
|
||||
|
||||
typedef int(__cdecl * PC_ReadTokenHandle_t)(int handle, pc_token_s *pc_token);
|
||||
extern PC_ReadTokenHandle_t PC_ReadTokenHandle;
|
||||
|
||||
typedef void(__cdecl * PC_SourceError_t)(int, const char*, ...);
|
||||
extern PC_SourceError_t PC_SourceError;
|
||||
|
||||
typedef netadr_t *(__cdecl * PartyHost_GetMemberAddressBySlot_t)(int unk, void *party, const int slot);
|
||||
extern PartyHost_GetMemberAddressBySlot_t PartyHost_GetMemberAddressBySlot;
|
||||
|
||||
typedef script_t* (__cdecl * Script_Alloc_t)(int length);
|
||||
extern Script_Alloc_t Script_Alloc;
|
||||
|
||||
typedef void(__cdecl * Script_SetupTokens_t)(script_t* script, void* tokens);
|
||||
extern Script_SetupTokens_t Script_SetupTokens;
|
||||
|
||||
typedef int(__cdecl * Script_CleanString_t)(char* buffer);
|
||||
extern Script_CleanString_t Script_CleanString;
|
||||
|
||||
typedef void(__cdecl * SetConsole_t)(const char* cvar, const char* value);
|
||||
extern SetConsole_t SetConsole;
|
||||
|
||||
typedef void(__cdecl * Steam_JoinLobby_t)(SteamID, char);
|
||||
extern Steam_JoinLobby_t Steam_JoinLobby;
|
||||
|
||||
typedef void(__cdecl * UI_AddMenuList_t)(UiContext *dc, MenuList *menuList, int close);
|
||||
extern UI_AddMenuList_t UI_AddMenuList;
|
||||
|
||||
typedef const char * (__cdecl * Win_GetLanguage_t)();
|
||||
extern Win_GetLanguage_t Win_GetLanguage;
|
||||
|
||||
extern void** DB_XAssetPool;
|
||||
extern unsigned int* g_poolSize;
|
||||
|
||||
extern DWORD* cmd_id;
|
||||
extern DWORD* cmd_argc;
|
||||
extern char*** cmd_argv;
|
||||
|
||||
extern int* svs_numclients;
|
||||
extern client_t* svs_clients;
|
||||
|
||||
extern source_t **sourceFiles;
|
||||
extern keywordHash_t **menuParseKeywordHash;
|
||||
|
||||
extern UiContext *uiContext;
|
||||
|
||||
extern int* arenaCount;
|
||||
extern mapArena_t* arenas;
|
||||
|
||||
extern int* gameTypeCount;
|
||||
extern gameTypeName_t* gameTypes;
|
||||
|
||||
extern XBlock** g_streamBlocks;
|
||||
|
||||
void* ReallocateAssetPool(XAssetType type, unsigned int newSize);
|
||||
void Menu_FreeItemMemory(Game::itemDef_t* item);
|
||||
void OOBPrintT(int type, netadr_t netadr, const char* message);
|
||||
const char* UI_LocalizeMapName(const char* mapName);
|
||||
const char* UI_LocalizeGameType(const char* gameType);
|
||||
}
|
944
src/Game/Structs.hpp
Normal file
944
src/Game/Structs.hpp
Normal file
@ -0,0 +1,944 @@
|
||||
namespace Game
|
||||
{
|
||||
typedef enum
|
||||
{
|
||||
ASSET_TYPE_PHYSPRESET = 0,
|
||||
ASSET_TYPE_PHYS_COLLMAP = 1,
|
||||
ASSET_TYPE_XANIM = 2,
|
||||
ASSET_TYPE_XMODELSURFS = 3,
|
||||
ASSET_TYPE_XMODEL = 4,
|
||||
ASSET_TYPE_MATERIAL = 5,
|
||||
ASSET_TYPE_PIXELSHADER = 6,
|
||||
ASSET_TYPE_VERTEXSHADER = 7,
|
||||
ASSET_TYPE_VERTEXDECL = 8,
|
||||
ASSET_TYPE_TECHSET = 9,
|
||||
ASSET_TYPE_IMAGE = 10,
|
||||
ASSET_TYPE_SOUND = 11,
|
||||
ASSET_TYPE_SNDCURVE = 12,
|
||||
ASSET_TYPE_LOADED_SOUND = 13,
|
||||
ASSET_TYPE_COL_MAP_SP = 14,
|
||||
ASSET_TYPE_COL_MAP_MP = 15,
|
||||
ASSET_TYPE_COM_MAP = 16,
|
||||
ASSET_TYPE_GAME_MAP_SP = 17,
|
||||
ASSET_TYPE_GAME_MAP_MP = 18,
|
||||
ASSET_TYPE_MAP_ENTS = 19,
|
||||
ASSET_TYPE_FX_MAP = 20,
|
||||
ASSET_TYPE_GFX_MAP = 21,
|
||||
ASSET_TYPE_LIGHTDEF = 22,
|
||||
ASSET_TYPE_UI_MAP = 23,
|
||||
ASSET_TYPE_FONT = 24,
|
||||
ASSET_TYPE_MENUFILE = 25,
|
||||
ASSET_TYPE_MENU = 26,
|
||||
ASSET_TYPE_LOCALIZE = 27,
|
||||
ASSET_TYPE_WEAPON = 28,
|
||||
ASSET_TYPE_SNDDRIVERGLOBALS = 29,
|
||||
ASSET_TYPE_FX = 30,
|
||||
ASSET_TYPE_IMPACTFX = 31,
|
||||
ASSET_TYPE_AITYPE = 32,
|
||||
ASSET_TYPE_MPTYPE = 33,
|
||||
ASSET_TYPE_CHARACTER = 34,
|
||||
ASSET_TYPE_XMODELALIAS = 35,
|
||||
ASSET_TYPE_RAWFILE = 36,
|
||||
ASSET_TYPE_STRINGTABLE = 37,
|
||||
ASSET_TYPE_LEADERBOARDDEF = 38,
|
||||
ASSET_TYPE_STRUCTUREDDATADEF = 39,
|
||||
ASSET_TYPE_TRACER = 40,
|
||||
ASSET_TYPE_VEHICLE = 41,
|
||||
ASSET_TYPE_ADDON_MAP_ENTS = 42,
|
||||
ASSET_TYPE_MAX = 43
|
||||
} XAssetType;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DVAR_FLAG_NONE = 0x0, //no flags
|
||||
DVAR_FLAG_SAVED = 0x1, //saves in config_mp.cfg for clients
|
||||
DVAR_FLAG_LATCHED = 0x2, //no changing apart from initial value (although it might apply on a map reload, I think)
|
||||
DVAR_FLAG_CHEAT = 0x4, //cheat
|
||||
DVAR_FLAG_REPLICATED = 0x8, //on change, this is sent to all clients (if you are host)
|
||||
DVAR_FLAG_UNKNOWN10 = 0x10, //unknown
|
||||
DVAR_FLAG_UNKNOWN20 = 0x20, //unknown
|
||||
DVAR_FLAG_UNKNOWN40 = 0x40, //unknown
|
||||
DVAR_FLAG_UNKNOWN80 = 0x80, //unknown
|
||||
DVAR_FLAG_USERCREATED = 0x100, //a 'set' type command created it
|
||||
DVAR_FLAG_USERINFO = 0x200, //userinfo?
|
||||
DVAR_FLAG_SERVERINFO = 0x400, //in the getstatus oob
|
||||
DVAR_FLAG_WRITEPROTECTED = 0x800, //write protected
|
||||
DVAR_FLAG_UNKNOWN1000 = 0x1000, //unknown
|
||||
DVAR_FLAG_READONLY = 0x2000, //read only (same as 0x800?)
|
||||
DVAR_FLAG_UNKNOWN4000 = 0x4000, //unknown
|
||||
DVAR_FLAG_UNKNOWN8000 = 0x8000, //unknown
|
||||
DVAR_FLAG_UNKNOWN10000 = 0x10000, //unknown
|
||||
DVAR_FLAG_DEDISAVED = 0x1000000, //unknown
|
||||
DVAR_FLAG_NONEXISTENT = 0xFFFFFFFF //no such dvar
|
||||
} dvar_flag;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DVAR_TYPE_BOOL = 0,
|
||||
DVAR_TYPE_FLOAT = 1,
|
||||
DVAR_TYPE_FLOAT_2 = 2,
|
||||
DVAR_TYPE_FLOAT_3 = 3,
|
||||
DVAR_TYPE_FLOAT_4 = 4,
|
||||
DVAR_TYPE_INT = 5,
|
||||
DVAR_TYPE_ENUM = 6,
|
||||
DVAR_TYPE_STRING = 7,
|
||||
DVAR_TYPE_COLOR = 8,
|
||||
//DVAR_TYPE_INT64 = 9 only in Tx
|
||||
} dvar_type;
|
||||
// 67/72 bytes figured out
|
||||
union dvar_value_t {
|
||||
char* string;
|
||||
int integer;
|
||||
float value;
|
||||
bool boolean;
|
||||
float vec2[2];
|
||||
float vec3[3];
|
||||
float vec4[4];
|
||||
BYTE color[4]; //to get float: multiply by 0.003921568859368563 - BaberZz
|
||||
//__int64 integer64; only in Tx
|
||||
};
|
||||
union dvar_maxmin_t {
|
||||
int i;
|
||||
float f;
|
||||
};
|
||||
typedef struct dvar_t
|
||||
{
|
||||
//startbyte:endbyte
|
||||
const char* name; //0:3
|
||||
const char* description; //4:7
|
||||
unsigned int flags; //8:11
|
||||
char type; //12:12
|
||||
char pad2[3]; //13:15
|
||||
dvar_value_t current; //16:31
|
||||
dvar_value_t latched; //32:47
|
||||
dvar_value_t default; //48:64
|
||||
dvar_maxmin_t min; //65:67
|
||||
dvar_maxmin_t max; //68:72 woooo
|
||||
} dvar_t;
|
||||
|
||||
typedef struct cmd_function_s
|
||||
{
|
||||
char pad[24];
|
||||
} cmd_function_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char type;
|
||||
char pad[3];
|
||||
const char* folder;
|
||||
const char* file;
|
||||
} StreamFile;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char pad[20];
|
||||
StreamFile* stream;
|
||||
char pad2[76];
|
||||
} snd_alias_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char* name;
|
||||
snd_alias_t* aliases;
|
||||
int numAliases;
|
||||
} snd_alias_list_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *name;
|
||||
int allocFlags;
|
||||
int freeFlags;
|
||||
} XZoneInfo;
|
||||
|
||||
|
||||
|
||||
typedef float vec_t;
|
||||
typedef vec_t vec4_t[4];
|
||||
struct expression_s;
|
||||
struct statement_s;
|
||||
struct menuDef_t;
|
||||
enum operationEnum;
|
||||
|
||||
struct Material
|
||||
{
|
||||
const char *name;
|
||||
};
|
||||
|
||||
struct keyname_t
|
||||
{
|
||||
const char *name;
|
||||
int keynum;
|
||||
};
|
||||
|
||||
struct ItemFloatExpressionEntry
|
||||
{
|
||||
int target;
|
||||
const char *s1;
|
||||
const char *s2;
|
||||
};
|
||||
|
||||
#define ITEM_TYPE_TEXT 0 // simple text
|
||||
#define ITEM_TYPE_BUTTON 1 // button, basically text with a border
|
||||
#define ITEM_TYPE_RADIOBUTTON 2 // toggle button, may be grouped
|
||||
#define ITEM_TYPE_CHECKBOX 3 // check box
|
||||
#define ITEM_TYPE_EDITFIELD 4 // editable text, associated with a dvar
|
||||
#define ITEM_TYPE_COMBO 5 // drop down list
|
||||
#define ITEM_TYPE_LISTBOX 6 // scrollable list
|
||||
#define ITEM_TYPE_MODEL 7 // model
|
||||
#define ITEM_TYPE_OWNERDRAW 8 // owner draw, name specs what it is
|
||||
#define ITEM_TYPE_NUMERICFIELD 9 // editable text, associated with a dvar
|
||||
#define ITEM_TYPE_SLIDER 10 // mouse speed, volume, etc.
|
||||
#define ITEM_TYPE_YESNO 11 // yes no dvar setting
|
||||
#define ITEM_TYPE_MULTI 12 // multiple list setting, enumerated
|
||||
#define ITEM_TYPE_DVARENUM 13 // multiple list setting, enumerated from a dvar
|
||||
#define ITEM_TYPE_BIND 14 // bind
|
||||
#define ITEM_TYPE_MENUMODEL 15 // special menu model
|
||||
#define ITEM_TYPE_VALIDFILEFIELD 16 // text must be valid for use in a dos filename
|
||||
#define ITEM_TYPE_DECIMALFIELD 17 // editable text, associated with a dvar, which allows decimal input
|
||||
#define ITEM_TYPE_UPREDITFIELD 18 // editable text, associated with a dvar
|
||||
#define ITEM_TYPE_GAME_MESSAGE_WINDOW 19 // game message window
|
||||
#define ITEM_TYPE_NEWSTICKER 20 // horizontal scrollbox
|
||||
#define ITEM_TYPE_TEXTSCROLL 21 // vertical scrollbox
|
||||
#define ITEM_TYPE_EMAILFIELD 22
|
||||
#define ITEM_TYPE_PASSWORDFIELD 23
|
||||
|
||||
struct MenuEventHandlerSet;
|
||||
struct Statement_s;
|
||||
|
||||
struct UIFunctionList
|
||||
{
|
||||
int totalFunctions;
|
||||
Statement_s **functions;
|
||||
};
|
||||
|
||||
struct StaticDvar
|
||||
{
|
||||
/*dvar_t*/
|
||||
void *dvar;
|
||||
char *dvarName;
|
||||
};
|
||||
|
||||
struct StaticDvarList
|
||||
{
|
||||
int numStaticDvars;
|
||||
StaticDvar **staticDvars;
|
||||
};
|
||||
|
||||
struct StringList
|
||||
{
|
||||
int totalStrings;
|
||||
const char **strings;
|
||||
};
|
||||
|
||||
struct ExpressionSupportingData
|
||||
{
|
||||
UIFunctionList uifunctions;
|
||||
StaticDvarList staticDvarList;
|
||||
StringList uiStrings;
|
||||
};
|
||||
|
||||
enum expDataType : int
|
||||
{
|
||||
VAL_INT = 0x0,
|
||||
VAL_FLOAT = 0x1,
|
||||
VAL_STRING = 0x2,
|
||||
VAL_FUNCTION = 0x3,
|
||||
};
|
||||
|
||||
struct ExpressionString
|
||||
{
|
||||
const char *string;
|
||||
};
|
||||
|
||||
union operandInternalDataUnion
|
||||
{
|
||||
int intVal;
|
||||
float floatVal;
|
||||
ExpressionString stringVal;
|
||||
Statement_s *function;
|
||||
};
|
||||
|
||||
struct Operand
|
||||
{
|
||||
expDataType dataType;
|
||||
operandInternalDataUnion internals;
|
||||
};
|
||||
|
||||
union entryInternalData
|
||||
{
|
||||
operationEnum op;
|
||||
Operand operand;
|
||||
};
|
||||
|
||||
/* expressionEntry->type */
|
||||
#define OPERATOR 0
|
||||
#define OPERAND 1
|
||||
|
||||
struct expressionEntry // 0xC
|
||||
{
|
||||
int type;
|
||||
entryInternalData data;
|
||||
};
|
||||
|
||||
struct Statement_s // 0x18
|
||||
{
|
||||
int numEntries;
|
||||
expressionEntry *entries;
|
||||
ExpressionSupportingData *supportingData;
|
||||
char unknown[0xC]; // ?
|
||||
};
|
||||
|
||||
struct SetLocalVarData
|
||||
{
|
||||
const char *localVarName;
|
||||
Statement_s *expression;
|
||||
};
|
||||
|
||||
struct ConditionalScript
|
||||
{
|
||||
MenuEventHandlerSet *eventHandlerSet;
|
||||
Statement_s *eventExpression; // loads this first
|
||||
};
|
||||
|
||||
union EventData
|
||||
{
|
||||
const char *unconditionalScript;
|
||||
ConditionalScript *conditionalScript;
|
||||
MenuEventHandlerSet *elseScript;
|
||||
SetLocalVarData *setLocalVarData;
|
||||
};
|
||||
|
||||
enum EventType
|
||||
{
|
||||
EVENT_UNCONDITIONAL = 0x0,
|
||||
EVENT_IF = 0x1,
|
||||
EVENT_ELSE = 0x2,
|
||||
EVENT_SET_LOCAL_VAR_BOOL = 0x3,
|
||||
EVENT_SET_LOCAL_VAR_INT = 0x4,
|
||||
EVENT_SET_LOCAL_VAR_FLOAT = 0x5,
|
||||
EVENT_SET_LOCAL_VAR_STRING = 0x6,
|
||||
EVENT_COUNT = 0x7,
|
||||
};
|
||||
|
||||
struct MenuEventHandler
|
||||
{
|
||||
EventData eventData;
|
||||
EventType eventType;
|
||||
};
|
||||
|
||||
struct MenuEventHandlerSet
|
||||
{
|
||||
int eventHandlerCount;
|
||||
MenuEventHandler **eventHandlers;
|
||||
};
|
||||
|
||||
struct ItemKeyHandler
|
||||
{
|
||||
int key;
|
||||
MenuEventHandlerSet *action;
|
||||
ItemKeyHandler *next;
|
||||
};
|
||||
|
||||
#pragma pack(push, 4)
|
||||
struct rectDef_s
|
||||
{
|
||||
float x;
|
||||
float y;
|
||||
float w;
|
||||
float h;
|
||||
char horzAlign;
|
||||
char vertAlign;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
/* windowDef_t->dynamicFlags */
|
||||
// 0x1
|
||||
#define WINDOWDYNAMIC_HASFOCUS 0x00000002
|
||||
#define WINDOWDYNAMIC_VISIBLE 0x00000004
|
||||
#define WINDOWDYNAMIC_FADEOUT 0x00000010
|
||||
#define WINDOWDYNAMIC_FADEIN 0x00000020
|
||||
// 0x40
|
||||
// 0x80
|
||||
#define WINDOWDYNAMIC_CLOSED 0x00000800
|
||||
// 0x2000
|
||||
#define WINDOWDYNAMIC_BACKCOLOR 0x00008000
|
||||
#define WINDOWDYNAMIC_FORECOLOR 0x00010000
|
||||
|
||||
/* windowDef_t->staticFlags */
|
||||
#define WINDOWSTATIC_DECORATION 0x00100000
|
||||
#define WINDOWSTATIC_HORIZONTALSCROLL 0x00200000
|
||||
#define WINDOWSTATIC_SCREENSPACE 0x00400000
|
||||
#define WINDOWSTATIC_AUTOWRAPPED 0x00800000
|
||||
#define WINDOWSTATIC_POPUP 0x01000000
|
||||
#define WINDOWSTATIC_OUTOFBOUNDSCLICK 0x02000000
|
||||
#define WINDOWSTATIC_LEGACYSPLITSCREENSCALE 0x04000000
|
||||
#define WINDOWSTATIC_HIDDENDURINGFLASH 0x10000000
|
||||
#define WINDOWSTATIC_HIDDENDURINGSCOPE 0x20000000
|
||||
#define WINDOWSTATIC_HIDDENDURINGUI 0x40000000
|
||||
#define WINDOWSTATIC_TEXTONLYFOCUS 0x80000000
|
||||
|
||||
struct windowDef_t // 0xA4
|
||||
{
|
||||
const char *name; // 0x00
|
||||
rectDef_s rect;
|
||||
rectDef_s rectClient;
|
||||
char *group; // 0x2C
|
||||
int style; // 0x30
|
||||
int border; // 0x34
|
||||
int ownerDraw; // 0x38
|
||||
int ownerDrawFlags; // 0x3C
|
||||
float borderSize; // 0x40
|
||||
int staticFlags; // 0x44
|
||||
int dynamicFlags; // 0x48
|
||||
int nextTime; // 0x4C
|
||||
float foreColor[4]; // 0x50
|
||||
float backColor[4]; // 0x60
|
||||
float borderColor[4];// 0x70
|
||||
float outlineColor[4];// 0x80
|
||||
float disableColor[4];// 0x90
|
||||
Material *background; // 0xA0
|
||||
};
|
||||
|
||||
enum ItemFloatExpressionTarget
|
||||
{
|
||||
ITEM_FLOATEXP_TGT_RECT_X = 0x0,
|
||||
ITEM_FLOATEXP_TGT_RECT_Y = 0x1,
|
||||
ITEM_FLOATEXP_TGT_RECT_W = 0x2,
|
||||
ITEM_FLOATEXP_TGT_RECT_H = 0x3,
|
||||
ITEM_FLOATEXP_TGT_FORECOLOR_R = 0x4,
|
||||
ITEM_FLOATEXP_TGT_FORECOLOR_G = 0x5,
|
||||
ITEM_FLOATEXP_TGT_FORECOLOR_B = 0x6,
|
||||
ITEM_FLOATEXP_TGT_FORECOLOR_RGB = 0x7,
|
||||
ITEM_FLOATEXP_TGT_FORECOLOR_A = 0x8,
|
||||
ITEM_FLOATEXP_TGT_GLOWCOLOR_R = 0x9,
|
||||
ITEM_FLOATEXP_TGT_GLOWCOLOR_G = 0xA,
|
||||
ITEM_FLOATEXP_TGT_GLOWCOLOR_B = 0xB,
|
||||
ITEM_FLOATEXP_TGT_GLOWCOLOR_RGB = 0xC,
|
||||
ITEM_FLOATEXP_TGT_GLOWCOLOR_A = 0xD,
|
||||
ITEM_FLOATEXP_TGT_BACKCOLOR_R = 0xE,
|
||||
ITEM_FLOATEXP_TGT_BACKCOLOR_G = 0xF,
|
||||
ITEM_FLOATEXP_TGT_BACKCOLOR_B = 0x10,
|
||||
ITEM_FLOATEXP_TGT_BACKCOLOR_RGB = 0x11,
|
||||
ITEM_FLOATEXP_TGT_BACKCOLOR_A = 0x12,
|
||||
ITEM_FLOATEXP_TGT__COUNT = 0x13,
|
||||
};
|
||||
|
||||
struct ItemFloatExpression
|
||||
{
|
||||
ItemFloatExpressionTarget target;
|
||||
Statement_s *expression;
|
||||
};
|
||||
|
||||
struct editFieldDef_s
|
||||
{
|
||||
float minVal;
|
||||
float maxVal;
|
||||
float defVal;
|
||||
float range;
|
||||
int maxChars;
|
||||
int maxCharsGotoNext;
|
||||
int maxPaintChars;
|
||||
int paintOffset;
|
||||
};
|
||||
|
||||
struct multiDef_s // 0x188
|
||||
{
|
||||
const char *dvarList[32];
|
||||
const char *dvarStr[32];
|
||||
float dvarValue[32];
|
||||
int count;
|
||||
int strDef;
|
||||
};
|
||||
|
||||
struct columnInfo_s
|
||||
{
|
||||
int xpos;
|
||||
int width;
|
||||
int maxChars;
|
||||
int alignment;
|
||||
};
|
||||
|
||||
struct listBoxDef_s // 0x144
|
||||
{
|
||||
// somethings not right here
|
||||
int startPos[2];
|
||||
int endPos[2];
|
||||
float elementWidth;
|
||||
float elementHeight;
|
||||
int elementStyle;
|
||||
int numColumns;
|
||||
columnInfo_s columnInfo[16];
|
||||
MenuEventHandlerSet *doubleClick; // 0xC8
|
||||
int notselectable;
|
||||
int noscrollbars;
|
||||
int usepaging;
|
||||
float selectBorder[4];
|
||||
Material *selectIcon;
|
||||
};
|
||||
|
||||
struct newsTickerDef_s
|
||||
{
|
||||
int feedId;
|
||||
int speed;
|
||||
int spacing;
|
||||
};
|
||||
|
||||
struct textScrollDef_s
|
||||
{
|
||||
int startTime;
|
||||
};
|
||||
|
||||
union itemDefData_t
|
||||
{
|
||||
listBoxDef_s *listBox;
|
||||
editFieldDef_s *editField;
|
||||
newsTickerDef_s *ticker;
|
||||
multiDef_s *multiDef;
|
||||
const char *enumDvarName;
|
||||
textScrollDef_s *scroll;
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct itemDef_t
|
||||
{
|
||||
windowDef_t window;
|
||||
rectDef_s textRect;
|
||||
int type;
|
||||
int dataType;
|
||||
int alignment;
|
||||
int fontEnum;
|
||||
int textAlignMode;
|
||||
float textAlignX;
|
||||
float textAlignY;
|
||||
float textScale;
|
||||
int textStyle;
|
||||
int gameMsgWindowIndex;
|
||||
int gameMsgWindowMode;
|
||||
const char *text;
|
||||
int textSaveGameInfo;
|
||||
int parent;
|
||||
MenuEventHandlerSet *mouseEnterText;
|
||||
MenuEventHandlerSet *mouseExitText;
|
||||
MenuEventHandlerSet *mouseEnter;
|
||||
MenuEventHandlerSet *mouseExit;
|
||||
MenuEventHandlerSet *action;
|
||||
MenuEventHandlerSet *accept;
|
||||
MenuEventHandlerSet *onFocus;
|
||||
MenuEventHandlerSet *leaveFocus;
|
||||
const char *dvar;
|
||||
const char *dvarTest;
|
||||
ItemKeyHandler *onKey;
|
||||
const char *enableDvar;
|
||||
const char *localVar;
|
||||
int dvarFlags;
|
||||
const char *focusSound;
|
||||
float special;
|
||||
int cursorPos;
|
||||
itemDefData_t typeData;
|
||||
int imageTrack;
|
||||
int floatExpressionCount;
|
||||
ItemFloatExpression *floatExpressions;
|
||||
Statement_s *visibleExp;
|
||||
Statement_s *disabledExp;
|
||||
Statement_s *textExp;
|
||||
Statement_s *materialExp;
|
||||
float glowColor[4];
|
||||
bool decayActive;
|
||||
int fxBirthTime;
|
||||
int fxLetterTime;
|
||||
int fxDecayStartTime;
|
||||
int fxDecayDuration;
|
||||
int lastSoundPlayedTime;
|
||||
};
|
||||
|
||||
struct menuTransition // 0x18
|
||||
{
|
||||
int transitionType;
|
||||
int startTime;
|
||||
float startVal;
|
||||
float endVal;
|
||||
float time;
|
||||
int endTriggerType;
|
||||
};
|
||||
|
||||
struct menuDef_t
|
||||
{
|
||||
windowDef_t window;
|
||||
int font;
|
||||
int fullscreen;
|
||||
int itemCount;
|
||||
int fontIndex;
|
||||
int cursorItems;
|
||||
int fadeCycle;
|
||||
float fadeClamp;
|
||||
float fadeAmount;
|
||||
float fadeInAmount;
|
||||
float blurRadius;
|
||||
MenuEventHandlerSet *onOpen;
|
||||
MenuEventHandlerSet *onRequestClose;
|
||||
MenuEventHandlerSet *onClose;
|
||||
MenuEventHandlerSet *onEsc;
|
||||
ItemKeyHandler *onKey;
|
||||
Statement_s *visibleExp;
|
||||
const char *allowedBinding;
|
||||
const char *soundLoop;
|
||||
int imageTrack;
|
||||
float focusColor[4];
|
||||
Statement_s *rectXExp;
|
||||
Statement_s *rectYExp;
|
||||
Statement_s *rectHExp;
|
||||
Statement_s *rectWExp;
|
||||
Statement_s *openSoundExp;
|
||||
Statement_s *closeSoundExp;
|
||||
itemDef_t **items;
|
||||
char unknown[112];
|
||||
ExpressionSupportingData *expressionData;
|
||||
};
|
||||
|
||||
struct MenuList
|
||||
{
|
||||
const char *name;
|
||||
int menuCount;
|
||||
menuDef_t **menus;
|
||||
};
|
||||
|
||||
enum FsListBehavior_e
|
||||
{
|
||||
FS_LIST_PURE_ONLY = 0x0,
|
||||
FS_LIST_ALL = 0x1,
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NA_BOT,
|
||||
NA_BAD, // an address lookup failed
|
||||
NA_LOOPBACK,
|
||||
NA_BROADCAST,
|
||||
NA_IP,
|
||||
NA_IP6, // custom type
|
||||
} netadrtype_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
NS_CLIENT,
|
||||
NS_SERVER
|
||||
} netsrc_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
netadrtype_t type;
|
||||
BYTE ip[4];
|
||||
unsigned short port;
|
||||
BYTE ipx[10];
|
||||
} netadr_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int unknown1;
|
||||
int unknown2;
|
||||
char* data;
|
||||
int unknown3;
|
||||
int maxsize; // 16
|
||||
int cursize;
|
||||
int unknown4;
|
||||
int readcount; // 28
|
||||
} msg_t;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct client_s
|
||||
{
|
||||
// 0
|
||||
int state;
|
||||
// 4
|
||||
char pad[36];
|
||||
// 40
|
||||
netadr_t adr;
|
||||
// 60
|
||||
char pad1[1568];
|
||||
// 1628
|
||||
char connectInfoString[1024];
|
||||
// 2652
|
||||
char pad2[133192];
|
||||
// 135844
|
||||
char name[16];
|
||||
// 135860
|
||||
char pad3[12];
|
||||
// 135872
|
||||
int snapNum;
|
||||
// 135876
|
||||
int pad4;
|
||||
// 135880
|
||||
short ping;
|
||||
// 135882
|
||||
//char pad5[142390];
|
||||
char pad5[133158];
|
||||
// 269040
|
||||
int isBot;
|
||||
// 269044
|
||||
char pad6[9228];
|
||||
// 278272
|
||||
__int64 steamid;
|
||||
// 278280
|
||||
char pad7[403592];
|
||||
} client_t;
|
||||
#pragma pack(pop)
|
||||
|
||||
// Q3TA precompiler code
|
||||
|
||||
//undef if binary numbers of the form 0b... or 0B... are not allowed
|
||||
#define BINARYNUMBERS
|
||||
//undef if not using the token.intvalue and token.floatvalue
|
||||
#define NUMBERVALUE
|
||||
//use dollar sign also as punctuation
|
||||
#define DOLLAR
|
||||
|
||||
//maximum token length
|
||||
#define MAX_TOKEN 1024
|
||||
|
||||
//punctuation
|
||||
typedef struct punctuation_s
|
||||
{
|
||||
char *p; //punctuation character(s)
|
||||
int n; //punctuation indication
|
||||
struct punctuation_s *next; //next punctuation
|
||||
} punctuation_t;
|
||||
|
||||
//token
|
||||
typedef struct token_s
|
||||
{
|
||||
char string[MAX_TOKEN]; //available token
|
||||
int type; //last read token type
|
||||
int subtype; //last read token sub type
|
||||
#ifdef NUMBERVALUE
|
||||
unsigned long int intvalue; //integer value
|
||||
long double floatvalue; //floating point value
|
||||
#endif //NUMBERVALUE
|
||||
char *whitespace_p; //start of white space before token
|
||||
char *endwhitespace_p; //start of white space before token
|
||||
int line; //line the token was on
|
||||
int linescrossed; //lines crossed in white space
|
||||
struct token_s *next; //next token in chain
|
||||
} token_t;
|
||||
|
||||
//script file
|
||||
typedef struct script_s
|
||||
{
|
||||
char filename[64]; //file name of the script
|
||||
char *buffer; //buffer containing the script
|
||||
char *script_p; //current pointer in the script
|
||||
char *end_p; //pointer to the end of the script
|
||||
char *lastscript_p; //script pointer before reading token
|
||||
char *whitespace_p; //begin of the white space
|
||||
char *endwhitespace_p; //end of the white space
|
||||
int length; //length of the script in bytes
|
||||
int line; //current line in script
|
||||
int lastline; //line before reading token
|
||||
int tokenavailable; //set by UnreadLastToken
|
||||
int flags; //several script flags
|
||||
punctuation_t *punctuations; //the punctuations used in the script
|
||||
punctuation_t **punctuationtable;
|
||||
token_t token; //available token
|
||||
struct script_s *next; //next script in a chain
|
||||
} script_t;
|
||||
|
||||
//macro definitions
|
||||
typedef struct define_s
|
||||
{
|
||||
char *name; //define name
|
||||
int flags; //define flags
|
||||
int builtin; // > 0 if builtin define
|
||||
int numparms; //number of define parameters
|
||||
token_t *parms; //define parameters
|
||||
token_t *tokens; //macro tokens (possibly containing parm tokens)
|
||||
struct define_s *next; //next defined macro in a list
|
||||
struct define_s *hashnext; //next define in the hash chain
|
||||
} define_t;
|
||||
|
||||
//indents
|
||||
//used for conditional compilation directives:
|
||||
//#if, #else, #elif, #ifdef, #ifndef
|
||||
typedef struct indent_s
|
||||
{
|
||||
int type; //indent type
|
||||
int skip; //true if skipping current indent
|
||||
script_t *script; //script the indent was in
|
||||
struct indent_s *next; //next indent on the indent stack
|
||||
} indent_t;
|
||||
|
||||
//source file
|
||||
typedef struct source_s
|
||||
{
|
||||
char filename[64]; //file name of the script
|
||||
char includepath[64]; //path to include files
|
||||
punctuation_t *punctuations; //punctuations to use
|
||||
script_t *scriptstack; //stack with scripts of the source
|
||||
token_t *tokens; //tokens to read first
|
||||
define_t *defines; //list with macro definitions
|
||||
define_t **definehash; //hash chain with defines
|
||||
indent_t *indentstack; //stack with indents
|
||||
int skip; // > 0 if skipping conditional code
|
||||
token_t token; //last read token
|
||||
} source_t;
|
||||
|
||||
#define MAX_TOKENLENGTH 1024
|
||||
|
||||
typedef struct pc_token_s
|
||||
{
|
||||
int type;
|
||||
int subtype;
|
||||
int intvalue;
|
||||
float floatvalue;
|
||||
char string[MAX_TOKENLENGTH];
|
||||
} pc_token_t;
|
||||
|
||||
//token types
|
||||
#define TT_STRING 1 // string
|
||||
#define TT_LITERAL 2 // literal
|
||||
#define TT_NUMBER 3 // number
|
||||
#define TT_NAME 4 // name
|
||||
#define TT_PUNCTUATION 5 // punctuation
|
||||
|
||||
//typedef int menuDef_t;
|
||||
//typedef int itemDef_t;
|
||||
|
||||
#define KEYWORDHASH_SIZE 512
|
||||
|
||||
typedef struct keywordHash_s
|
||||
{
|
||||
char *keyword;
|
||||
bool(*func)(itemDef_t *item, int handle);
|
||||
//struct keywordHash_s *next;
|
||||
} keywordHash_t;
|
||||
|
||||
enum UILocalVarType
|
||||
{
|
||||
UILOCALVAR_INT = 0x0,
|
||||
UILOCALVAR_FLOAT = 0x1,
|
||||
UILOCALVAR_STRING = 0x2,
|
||||
};
|
||||
|
||||
struct UILocalVar
|
||||
{
|
||||
UILocalVarType type;
|
||||
const char *name;
|
||||
union
|
||||
{
|
||||
int integer;
|
||||
float value;
|
||||
const char *string;
|
||||
};
|
||||
};
|
||||
|
||||
struct UILocalVarContext
|
||||
{
|
||||
UILocalVar table[256];
|
||||
};
|
||||
|
||||
struct UiContext
|
||||
{
|
||||
// int localClientNum;
|
||||
// float bias;
|
||||
// int realTime;
|
||||
// int frameTime;
|
||||
// int cursorx;
|
||||
// int cursory;
|
||||
// int debug;
|
||||
// int screenWidth;
|
||||
// int screenHeight;
|
||||
// float screenAspect;
|
||||
// float FPS;
|
||||
// float blurRadiusOut;
|
||||
char pad[56];
|
||||
menuDef_t *Menus[512];
|
||||
char pad2[512];
|
||||
int menuCount;
|
||||
// Unsure if below is correct
|
||||
menuDef_t *menuStack[16];
|
||||
int openMenuCount;
|
||||
UILocalVarContext localVars;
|
||||
};
|
||||
|
||||
struct localizedEntry_s
|
||||
{
|
||||
const char* value;
|
||||
const char* name;
|
||||
};
|
||||
|
||||
struct MapEnts
|
||||
{
|
||||
const char* name;
|
||||
const char* entitystring;
|
||||
};
|
||||
|
||||
union XAssetHeader
|
||||
{
|
||||
void *data;
|
||||
MenuList *menuList;
|
||||
menuDef_t *menu;
|
||||
Material *material;
|
||||
snd_alias_list_t *aliasList;
|
||||
localizedEntry_s *localize;
|
||||
MapEnts* mapEnts;
|
||||
};
|
||||
|
||||
struct XAsset
|
||||
{
|
||||
XAssetType type;
|
||||
XAssetHeader header;
|
||||
};
|
||||
|
||||
struct XBlock
|
||||
{
|
||||
char *data;
|
||||
unsigned int size;
|
||||
};
|
||||
|
||||
struct XAssetEntry
|
||||
{
|
||||
XAsset asset;
|
||||
char zoneIndex;
|
||||
bool inuse;
|
||||
unsigned __int16 nextHash;
|
||||
unsigned __int16 nextOverride;
|
||||
unsigned __int16 usageFrame;
|
||||
};
|
||||
|
||||
struct XNKID
|
||||
{
|
||||
char ab[8];
|
||||
};
|
||||
|
||||
struct XNADDR
|
||||
{
|
||||
in_addr ina;
|
||||
in_addr inaOnline;
|
||||
unsigned __int16 wPortOnline;
|
||||
char abEnet[6];
|
||||
char abOnline[20];
|
||||
};
|
||||
|
||||
struct XNKEY
|
||||
{
|
||||
char ab[16];
|
||||
};
|
||||
|
||||
struct _XSESSION_INFO
|
||||
{
|
||||
XNKID sessionID;
|
||||
XNADDR hostAddress;
|
||||
XNKEY keyExchangeKey;
|
||||
};
|
||||
|
||||
struct mapArena_t
|
||||
{
|
||||
char uiName[32];
|
||||
char mapName[16];
|
||||
char pad[2768];
|
||||
};
|
||||
|
||||
struct gameTypeName_t
|
||||
{
|
||||
char gameType[12];
|
||||
char uiName[32];
|
||||
};
|
||||
}
|
29
src/Main.cpp
Normal file
29
src/Main.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
#include "STDInclude.hpp"
|
||||
|
||||
|
||||
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
|
||||
{
|
||||
static Utils::Hook EntryPointHook;
|
||||
|
||||
if (ul_reason_for_call == DLL_PROCESS_ATTACH)
|
||||
{
|
||||
FreeConsole();
|
||||
|
||||
DWORD oldProtect;
|
||||
VirtualProtect(GetModuleHandle(NULL), 0x6C73000, PAGE_EXECUTE_READWRITE, &oldProtect);
|
||||
|
||||
EntryPointHook.Initialize(0x6BAC0F, [] ()
|
||||
{
|
||||
EntryPointHook.Uninstall();
|
||||
Components::Loader::Initialize();
|
||||
__asm jmp EntryPointHook.Place
|
||||
|
||||
})->Install();
|
||||
}
|
||||
else if (ul_reason_for_call == DLL_PROCESS_DETACH)
|
||||
{
|
||||
Components::Loader::Uninitialize();
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
34
src/STDInclude.hpp
Normal file
34
src/STDInclude.hpp
Normal file
@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <wincrypt.h>
|
||||
#include <time.h>
|
||||
#include <timeapi.h>
|
||||
#include <WinSock2.h>
|
||||
|
||||
#pragma comment(lib, "Winmm.lib")
|
||||
#pragma comment(lib, "Crypt32.lib")
|
||||
#pragma comment(lib, "Ws2_32.lib")
|
||||
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sstream>
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
#include <regex>
|
||||
|
||||
#include "Utils\Utils.hpp"
|
||||
#include "Utils\Hooking.hpp"
|
||||
|
||||
#include "Steam\Steam.hpp"
|
||||
|
||||
#include "Game\Structs.hpp"
|
||||
#include "Game\Functions.hpp"
|
||||
|
||||
#include "Components\Loader.hpp"
|
120
src/Steam/Interfaces/SteamFriends.cpp
Normal file
120
src/Steam/Interfaces/SteamFriends.cpp
Normal file
@ -0,0 +1,120 @@
|
||||
#include "..\..\STDInclude.hpp"
|
||||
|
||||
using namespace Components;
|
||||
|
||||
namespace Steam
|
||||
{
|
||||
const char *Friends::GetPersonaName()
|
||||
{
|
||||
return Dvar::Var("name").Get<const char*>();
|
||||
}
|
||||
|
||||
void Friends::SetPersonaName(const char *pchPersonaName)
|
||||
{
|
||||
Dvar::Var("name").Set(pchPersonaName);
|
||||
}
|
||||
|
||||
int Friends::GetPersonaState()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int Friends::GetFriendCount(int eFriendFlags)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
SteamID Friends::GetFriendByIndex(int iFriend, int iFriendFlags)
|
||||
{
|
||||
return SteamID();
|
||||
}
|
||||
|
||||
int Friends::GetFriendRelationship(SteamID steamIDFriend)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Friends::GetFriendPersonaState(SteamID steamIDFriend)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *Friends::GetFriendPersonaName(SteamID steamIDFriend)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
int Friends::GetFriendAvatar(SteamID steamIDFriend, int eAvatarSize)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Friends::GetFriendGamePlayed(SteamID steamIDFriend, void *pFriendGameInfo)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *Friends::GetFriendPersonaNameHistory(SteamID steamIDFriend, int iPersonaName)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
bool Friends::HasFriend(SteamID steamIDFriend, int eFriendFlags)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int Friends::GetClanCount()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
SteamID Friends::GetClanByIndex(int iClan)
|
||||
{
|
||||
return SteamID();
|
||||
}
|
||||
|
||||
const char *Friends::GetClanName(SteamID steamIDClan)
|
||||
{
|
||||
return "3arc";
|
||||
}
|
||||
|
||||
int Friends::GetFriendCountFromSource(SteamID steamIDSource)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
SteamID Friends::GetFriendFromSourceByIndex(SteamID steamIDSource, int iFriend)
|
||||
{
|
||||
return SteamID();
|
||||
}
|
||||
|
||||
bool Friends::IsUserInSource(SteamID steamIDUser, SteamID steamIDSource)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void Friends::SetInGameVoiceSpeaking(SteamID steamIDUser, bool bSpeaking)
|
||||
{
|
||||
}
|
||||
|
||||
void Friends::ActivateGameOverlay(const char *pchDialog)
|
||||
{
|
||||
}
|
||||
|
||||
void Friends::ActivateGameOverlayToUser(const char *pchDialog, SteamID steamID)
|
||||
{
|
||||
}
|
||||
|
||||
void Friends::ActivateGameOverlayToWebPage(const char *pchURL)
|
||||
{
|
||||
}
|
||||
|
||||
void Friends::ActivateGameOverlayToStore(unsigned int nAppID)
|
||||
{
|
||||
}
|
||||
|
||||
void Friends::SetPlayedWith(SteamID steamIDUserPlayedWith)
|
||||
{
|
||||
}
|
||||
}
|
31
src/Steam/Interfaces/SteamFriends.hpp
Normal file
31
src/Steam/Interfaces/SteamFriends.hpp
Normal file
@ -0,0 +1,31 @@
|
||||
namespace Steam
|
||||
{
|
||||
class Friends
|
||||
{
|
||||
public:
|
||||
virtual const char *GetPersonaName();
|
||||
virtual void SetPersonaName(const char *pchPersonaName);
|
||||
virtual int GetPersonaState();
|
||||
virtual int GetFriendCount(int eFriendFlags);
|
||||
virtual SteamID GetFriendByIndex(int iFriend, int iFriendFlags);
|
||||
virtual int GetFriendRelationship(SteamID steamIDFriend);
|
||||
virtual int GetFriendPersonaState(SteamID steamIDFriend);
|
||||
virtual const char *GetFriendPersonaName(SteamID steamIDFriend);
|
||||
virtual int GetFriendAvatar(SteamID steamIDFriend, int eAvatarSize);
|
||||
virtual bool GetFriendGamePlayed(SteamID steamIDFriend, void *pFriendGameInfo);
|
||||
virtual const char *GetFriendPersonaNameHistory(SteamID steamIDFriend, int iPersonaName);
|
||||
virtual bool HasFriend(SteamID steamIDFriend, int eFriendFlags);
|
||||
virtual int GetClanCount();
|
||||
virtual SteamID GetClanByIndex(int iClan);
|
||||
virtual const char *GetClanName(SteamID steamIDClan);
|
||||
virtual int GetFriendCountFromSource(SteamID steamIDSource);
|
||||
virtual SteamID GetFriendFromSourceByIndex(SteamID steamIDSource, int iFriend);
|
||||
virtual bool IsUserInSource(SteamID steamIDUser, SteamID steamIDSource);
|
||||
virtual void SetInGameVoiceSpeaking(SteamID steamIDUser, bool bSpeaking);
|
||||
virtual void ActivateGameOverlay(const char *pchDialog);
|
||||
virtual void ActivateGameOverlayToUser(const char *pchDialog, SteamID steamID);
|
||||
virtual void ActivateGameOverlayToWebPage(const char *pchURL);
|
||||
virtual void ActivateGameOverlayToStore(unsigned int nAppID);
|
||||
virtual void SetPlayedWith(SteamID steamIDUserPlayedWith);
|
||||
};
|
||||
}
|
91
src/Steam/Interfaces/SteamGameServer.cpp
Normal file
91
src/Steam/Interfaces/SteamGameServer.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
#include "..\..\STDInclude.hpp"
|
||||
|
||||
namespace Steam
|
||||
{
|
||||
void GameServer::LogOn()
|
||||
{
|
||||
}
|
||||
|
||||
void GameServer::LogOff()
|
||||
{
|
||||
}
|
||||
|
||||
bool GameServer::LoggedOn()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GameServer::Secure()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
SteamID GameServer::GetSteamID()
|
||||
{
|
||||
return SteamID();
|
||||
}
|
||||
|
||||
bool GameServer::SendUserConnectAndAuthenticate(unsigned int unIPClient, const void *pvAuthBlob, unsigned int cubAuthBlobSize, SteamID *pSteamIDUser)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
SteamID GameServer::CreateUnauthenticatedUserConnection()
|
||||
{
|
||||
return SteamID();
|
||||
}
|
||||
|
||||
void GameServer::SendUserDisconnect(SteamID steamIDUser)
|
||||
{
|
||||
}
|
||||
|
||||
bool GameServer::UpdateUserData(SteamID steamIDUser, const char *pchPlayerName, unsigned int uScore)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool GameServer::SetServerType(unsigned int unServerFlags, unsigned int unGameIP, unsigned short unGamePort, unsigned short unSpectatorPort, unsigned short usQueryPort, const char *pchGameDir, const char *pchVersion, bool bLANMode)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void GameServer::UpdateServerStatus(int cPlayers, int cPlayersMax, int cBotPlayers, const char *pchServerName, const char *pSpectatorServerName, const char *pchMapName)
|
||||
{
|
||||
}
|
||||
|
||||
void GameServer::UpdateSpectatorPort(unsigned short unSpectatorPort)
|
||||
{
|
||||
}
|
||||
|
||||
void GameServer::SetGameType(const char *pchGameType)
|
||||
{
|
||||
}
|
||||
|
||||
bool GameServer::GetUserAchievementStatus(SteamID steamID, const char *pchAchievementName)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void GameServer::GetGameplayStats()
|
||||
{
|
||||
}
|
||||
|
||||
bool GameServer::RequestUserGroupStatus(SteamID steamIDUser, SteamID steamIDGroup)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int GameServer::GetPublicIP()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GameServer::SetGameData(const char *pchGameData)
|
||||
{
|
||||
}
|
||||
|
||||
int GameServer::UserHasLicenseForApp(SteamID steamID, unsigned int appID)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
26
src/Steam/Interfaces/SteamGameServer.hpp
Normal file
26
src/Steam/Interfaces/SteamGameServer.hpp
Normal file
@ -0,0 +1,26 @@
|
||||
namespace Steam
|
||||
{
|
||||
class GameServer
|
||||
{
|
||||
public:
|
||||
virtual void LogOn();
|
||||
virtual void LogOff();
|
||||
virtual bool LoggedOn();
|
||||
virtual bool Secure();
|
||||
virtual SteamID GetSteamID();
|
||||
virtual bool SendUserConnectAndAuthenticate(unsigned int unIPClient, const void *pvAuthBlob, unsigned int cubAuthBlobSize, SteamID *pSteamIDUser);
|
||||
virtual SteamID CreateUnauthenticatedUserConnection();
|
||||
virtual void SendUserDisconnect(SteamID steamIDUser);
|
||||
virtual bool UpdateUserData(SteamID steamIDUser, const char *pchPlayerName, unsigned int uScore);
|
||||
virtual bool SetServerType(unsigned int unServerFlags, unsigned int unGameIP, unsigned short unGamePort, unsigned short unSpectatorPort, unsigned short usQueryPort, const char *pchGameDir, const char *pchVersion, bool bLANMode);
|
||||
virtual void UpdateServerStatus(int cPlayers, int cPlayersMax, int cBotPlayers, const char *pchServerName, const char *pSpectatorServerName, const char *pchMapName);
|
||||
virtual void UpdateSpectatorPort(unsigned short unSpectatorPort);
|
||||
virtual void SetGameType(const char *pchGameType);
|
||||
virtual bool GetUserAchievementStatus(SteamID steamID, const char *pchAchievementName);
|
||||
virtual void GetGameplayStats();
|
||||
virtual bool RequestUserGroupStatus(SteamID steamIDUser, SteamID steamIDGroup);
|
||||
virtual unsigned int GetPublicIP();
|
||||
virtual void SetGameData(const char *pchGameData);
|
||||
virtual int UserHasLicenseForApp(SteamID steamID, unsigned int appID);
|
||||
};
|
||||
}
|
67
src/Steam/Interfaces/SteamMasterServerUpdater.cpp
Normal file
67
src/Steam/Interfaces/SteamMasterServerUpdater.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
#include "..\..\STDInclude.hpp"
|
||||
|
||||
namespace Steam
|
||||
{
|
||||
void MasterServerUpdater::SetActive(bool bActive)
|
||||
{
|
||||
}
|
||||
|
||||
void MasterServerUpdater::SetHeartbeatInterval(int iHeartbeatInterval)
|
||||
{
|
||||
}
|
||||
|
||||
bool MasterServerUpdater::HandleIncomingPacket(const void *pData, int cbData, unsigned int srcIP, unsigned short srcPort)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int MasterServerUpdater::GetNextOutgoingPacket(void *pOut, int cbMaxOut, unsigned int *pNetAdr, unsigned short *pPort)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void MasterServerUpdater::SetBasicServerData(unsigned short nProtocolVersion, bool bDedicatedServer, const char *pRegionName, const char *pProductName, unsigned short nMaxReportedClients, bool bPasswordProtected, const char *pGameDescription)
|
||||
{
|
||||
}
|
||||
|
||||
void MasterServerUpdater::ClearAllKeyValues()
|
||||
{
|
||||
}
|
||||
|
||||
void MasterServerUpdater::SetKeyValue(const char *pKey, const char *pValue)
|
||||
{
|
||||
}
|
||||
|
||||
void MasterServerUpdater::NotifyShutdown()
|
||||
{
|
||||
}
|
||||
|
||||
bool MasterServerUpdater::WasRestartRequested()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void MasterServerUpdater::ForceHeartbeat()
|
||||
{
|
||||
}
|
||||
|
||||
bool MasterServerUpdater::AddMasterServer(const char *pServerAddress)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MasterServerUpdater::RemoveMasterServer(const char *pServerAddress)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int MasterServerUpdater::GetNumMasterServers()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int MasterServerUpdater::GetMasterServerAddress(int iServer, char *pOut, int outBufferSize)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
21
src/Steam/Interfaces/SteamMasterServerUpdater.hpp
Normal file
21
src/Steam/Interfaces/SteamMasterServerUpdater.hpp
Normal file
@ -0,0 +1,21 @@
|
||||
namespace Steam
|
||||
{
|
||||
class MasterServerUpdater
|
||||
{
|
||||
public:
|
||||
virtual void SetActive(bool bActive);
|
||||
virtual void SetHeartbeatInterval(int iHeartbeatInterval);
|
||||
virtual bool HandleIncomingPacket(const void *pData, int cbData, unsigned int srcIP, unsigned short srcPort);
|
||||
virtual int GetNextOutgoingPacket(void *pOut, int cbMaxOut, unsigned int *pNetAdr, unsigned short *pPort);
|
||||
virtual void SetBasicServerData(unsigned short nProtocolVersion, bool bDedicatedServer, const char *pRegionName, const char *pProductName, unsigned short nMaxReportedClients, bool bPasswordProtected, const char *pGameDescription);
|
||||
virtual void ClearAllKeyValues();
|
||||
virtual void SetKeyValue(const char *pKey, const char *pValue);
|
||||
virtual void NotifyShutdown();
|
||||
virtual bool WasRestartRequested();
|
||||
virtual void ForceHeartbeat();
|
||||
virtual bool AddMasterServer(const char *pServerAddress);
|
||||
virtual bool RemoveMasterServer(const char *pServerAddress);
|
||||
virtual int GetNumMasterServers();
|
||||
virtual int GetMasterServerAddress(int iServer, char *pOut, int outBufferSize);
|
||||
};
|
||||
}
|
193
src/Steam/Interfaces/SteamMatchmaking.cpp
Normal file
193
src/Steam/Interfaces/SteamMatchmaking.cpp
Normal file
@ -0,0 +1,193 @@
|
||||
#include "..\..\STDInclude.hpp"
|
||||
|
||||
namespace Steam
|
||||
{
|
||||
int Matchmaking::GetFavoriteGameCount()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Matchmaking::GetFavoriteGame(int iGame, unsigned int *pnAppID, unsigned int *pnIP, unsigned short *pnConnPort, unsigned short *pnQueryPort, unsigned int *punFlags, unsigned int *pRTime32LastPlayedOnServer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int Matchmaking::AddFavoriteGame(unsigned int nAppID, unsigned int nIP, unsigned short nConnPort, unsigned short nQueryPort, unsigned int unFlags, unsigned int rTime32LastPlayedOnServer)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Matchmaking::RemoveFavoriteGame(unsigned int nAppID, unsigned int nIP, unsigned short nConnPort, unsigned short nQueryPort, unsigned int unFlags)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned __int64 Matchmaking::RequestLobbyList()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Matchmaking::AddRequestLobbyListStringFilter(const char *pchKeyToMatch, const char *pchValueToMatch, int eComparisonType)
|
||||
{
|
||||
}
|
||||
|
||||
void Matchmaking::AddRequestLobbyListNumericalFilter(const char *pchKeyToMatch, int nValueToMatch, int eComparisonType)
|
||||
{
|
||||
}
|
||||
|
||||
void Matchmaking::AddRequestLobbyListNearValueFilter(const char *pchKeyToMatch, int nValueToBeCloseTo)
|
||||
{
|
||||
}
|
||||
|
||||
void Matchmaking::AddRequestLobbyListFilterSlotsAvailable(int nSlotsAvailable)
|
||||
{
|
||||
}
|
||||
|
||||
SteamID Matchmaking::GetLobbyByIndex(int iLobby)
|
||||
{
|
||||
return SteamID();
|
||||
}
|
||||
|
||||
unsigned __int64 Matchmaking::CreateLobby(int eLobbyType, int cMaxMembers)
|
||||
{
|
||||
uint64_t result = Callbacks::RegisterCall();
|
||||
LobbyCreated* retvals = new LobbyCreated;
|
||||
SteamID id;
|
||||
|
||||
id.AccountID = 1337132;
|
||||
id.Universe = 1;
|
||||
id.AccountType = 8;
|
||||
id.AccountInstance = 0x40000;
|
||||
|
||||
retvals->m_eResult = 1;
|
||||
retvals->m_ulSteamIDLobby = id;
|
||||
|
||||
Callbacks::ReturnCall(retvals, sizeof(LobbyCreated), LobbyCreated::CallbackID, result);
|
||||
|
||||
Matchmaking::JoinLobby(id);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned __int64 Matchmaking::JoinLobby(SteamID steamIDLobby)
|
||||
{
|
||||
uint64_t result = Callbacks::RegisterCall();
|
||||
LobbyEnter* retvals = new LobbyEnter;
|
||||
retvals->m_bLocked = false;
|
||||
retvals->m_EChatRoomEnterResponse = 1;
|
||||
retvals->m_rgfChatPermissions = 0xFFFFFFFF;
|
||||
retvals->m_ulSteamIDLobby = steamIDLobby;
|
||||
|
||||
Callbacks::ReturnCall(retvals, sizeof(LobbyEnter), LobbyEnter::CallbackID, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Matchmaking::LeaveLobby(SteamID steamIDLobby)
|
||||
{
|
||||
Components::Party::RemoveLobby(steamIDLobby);
|
||||
}
|
||||
|
||||
bool Matchmaking::InviteUserToLobby(SteamID steamIDLobby, SteamID steamIDInvitee)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int Matchmaking::GetNumLobbyMembers(SteamID steamIDLobby)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
SteamID Matchmaking::GetLobbyMemberByIndex(SteamID steamIDLobby, int iMember)
|
||||
{
|
||||
return SteamUser()->GetSteamID();
|
||||
}
|
||||
|
||||
const char *Matchmaking::GetLobbyData(SteamID steamIDLobby, const char *pchKey)
|
||||
{
|
||||
return Components::Party::GetLobbyInfo(steamIDLobby, pchKey);
|
||||
}
|
||||
|
||||
bool Matchmaking::SetLobbyData(SteamID steamIDLobby, const char *pchKey, const char *pchValue)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int Matchmaking::GetLobbyDataCount(SteamID steamIDLobby)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Matchmaking::GetLobbyDataByIndex(SteamID steamIDLobby, int iLobbyData, char *pchKey, int cchKeyBufferSize, char *pchValue, int cchValueBufferSize)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Matchmaking::DeleteLobbyData(SteamID steamIDLobby, const char *pchKey)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *Matchmaking::GetLobbyMemberData(SteamID steamIDLobby, SteamID steamIDUser, const char *pchKey)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
void Matchmaking::SetLobbyMemberData(SteamID steamIDLobby, const char *pchKey, const char *pchValue)
|
||||
{
|
||||
}
|
||||
|
||||
bool Matchmaking::SendLobbyChatMsg(SteamID steamIDLobby, const void *pvMsgBody, int cubMsgBody)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int Matchmaking::GetLobbyChatEntry(SteamID steamIDLobby, int iChatID, SteamID *pSteamIDUser, void *pvData, int cubData, int *peChatEntryType)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Matchmaking::RequestLobbyData(SteamID steamIDLobby)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void Matchmaking::SetLobbyGameServer(SteamID steamIDLobby, unsigned int unGameServerIP, unsigned short unGameServerPort, SteamID steamIDGameServer)
|
||||
{
|
||||
}
|
||||
|
||||
bool Matchmaking::GetLobbyGameServer(SteamID steamIDLobby, unsigned int *punGameServerIP, unsigned short *punGameServerPort, SteamID *psteamIDGameServer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Matchmaking::SetLobbyMemberLimit(SteamID steamIDLobby, int cMaxMembers)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int Matchmaking::GetLobbyMemberLimit(SteamID steamIDLobby)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Matchmaking::SetLobbyType(SteamID steamIDLobby, int eLobbyType)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Matchmaking::SetLobbyJoinable(SteamID steamIDLobby, bool bLobbyJoinable)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
SteamID Matchmaking::GetLobbyOwner(SteamID steamIDLobby)
|
||||
{
|
||||
return SteamUser()->GetSteamID();
|
||||
}
|
||||
|
||||
bool Matchmaking::SetLobbyOwner(SteamID steamIDLobby, SteamID steamIDNewOwner)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
60
src/Steam/Interfaces/SteamMatchmaking.hpp
Normal file
60
src/Steam/Interfaces/SteamMatchmaking.hpp
Normal file
@ -0,0 +1,60 @@
|
||||
namespace Steam
|
||||
{
|
||||
struct LobbyCreated
|
||||
{
|
||||
enum { CallbackID = 513 };
|
||||
|
||||
int m_eResult;
|
||||
int m_pad;
|
||||
SteamID m_ulSteamIDLobby;
|
||||
};
|
||||
|
||||
struct LobbyEnter
|
||||
{
|
||||
enum { CallbackID = 504 };
|
||||
|
||||
SteamID m_ulSteamIDLobby;
|
||||
int m_rgfChatPermissions;
|
||||
bool m_bLocked;
|
||||
int m_EChatRoomEnterResponse;
|
||||
};
|
||||
|
||||
class Matchmaking
|
||||
{
|
||||
public:
|
||||
virtual int GetFavoriteGameCount();
|
||||
virtual bool GetFavoriteGame(int iGame, unsigned int *pnAppID, unsigned int *pnIP, unsigned short *pnConnPort, unsigned short *pnQueryPort, unsigned int *punFlags, unsigned int *pRTime32LastPlayedOnServer);
|
||||
virtual int AddFavoriteGame(unsigned int nAppID, unsigned int nIP, unsigned short nConnPort, unsigned short nQueryPort, unsigned int unFlags, unsigned int rTime32LastPlayedOnServer);
|
||||
virtual bool RemoveFavoriteGame(unsigned int nAppID, unsigned int nIP, unsigned short nConnPort, unsigned short nQueryPort, unsigned int unFlags);
|
||||
virtual unsigned __int64 RequestLobbyList();
|
||||
virtual void AddRequestLobbyListStringFilter(const char *pchKeyToMatch, const char *pchValueToMatch, int eComparisonType);
|
||||
virtual void AddRequestLobbyListNumericalFilter(const char *pchKeyToMatch, int nValueToMatch, int eComparisonType);
|
||||
virtual void AddRequestLobbyListNearValueFilter(const char *pchKeyToMatch, int nValueToBeCloseTo);
|
||||
virtual void AddRequestLobbyListFilterSlotsAvailable(int nSlotsAvailable);
|
||||
virtual SteamID GetLobbyByIndex(int iLobby);
|
||||
virtual unsigned __int64 CreateLobby(int eLobbyType, int cMaxMembers);
|
||||
virtual unsigned __int64 JoinLobby(SteamID steamIDLobby);
|
||||
virtual void LeaveLobby(SteamID steamIDLobby);
|
||||
virtual bool InviteUserToLobby(SteamID steamIDLobby, SteamID steamIDInvitee);
|
||||
virtual int GetNumLobbyMembers(SteamID steamIDLobby);
|
||||
virtual SteamID GetLobbyMemberByIndex(SteamID steamIDLobby, int iMember);
|
||||
virtual const char *GetLobbyData(SteamID steamIDLobby, const char *pchKey);
|
||||
virtual bool SetLobbyData(SteamID steamIDLobby, const char *pchKey, const char *pchValue);
|
||||
virtual int GetLobbyDataCount(SteamID steamIDLobby);
|
||||
virtual bool GetLobbyDataByIndex(SteamID steamIDLobby, int iLobbyData, char *pchKey, int cchKeyBufferSize, char *pchValue, int cchValueBufferSize);
|
||||
virtual bool DeleteLobbyData(SteamID steamIDLobby, const char *pchKey);
|
||||
virtual const char *GetLobbyMemberData(SteamID steamIDLobby, SteamID steamIDUser, const char *pchKey);
|
||||
virtual void SetLobbyMemberData(SteamID steamIDLobby, const char *pchKey, const char *pchValue);
|
||||
virtual bool SendLobbyChatMsg(SteamID steamIDLobby, const void *pvMsgBody, int cubMsgBody);
|
||||
virtual int GetLobbyChatEntry(SteamID steamIDLobby, int iChatID, SteamID *pSteamIDUser, void *pvData, int cubData, int *peChatEntryType);
|
||||
virtual bool RequestLobbyData(SteamID steamIDLobby);
|
||||
virtual void SetLobbyGameServer(SteamID steamIDLobby, unsigned int unGameServerIP, unsigned short unGameServerPort, SteamID steamIDGameServer);
|
||||
virtual bool GetLobbyGameServer(SteamID steamIDLobby, unsigned int *punGameServerIP, unsigned short *punGameServerPort, SteamID *psteamIDGameServer);
|
||||
virtual bool SetLobbyMemberLimit(SteamID steamIDLobby, int cMaxMembers);
|
||||
virtual int GetLobbyMemberLimit(SteamID steamIDLobby);
|
||||
virtual bool SetLobbyType(SteamID steamIDLobby, int eLobbyType);
|
||||
virtual bool SetLobbyJoinable(SteamID steamIDLobby, bool bLobbyJoinable);
|
||||
virtual SteamID GetLobbyOwner(SteamID steamIDLobby);
|
||||
virtual bool SetLobbyOwner(SteamID steamIDLobby, SteamID steamIDNewOwner);
|
||||
};
|
||||
}
|
104
src/Steam/Interfaces/SteamNetworking.cpp
Normal file
104
src/Steam/Interfaces/SteamNetworking.cpp
Normal file
@ -0,0 +1,104 @@
|
||||
#include "..\..\STDInclude.hpp"
|
||||
|
||||
namespace Steam
|
||||
{
|
||||
bool Networking::SendP2PPacket(SteamID steamIDRemote, const void *pubData, unsigned int cubData, int eP2PSendType)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Networking::IsP2PPacketAvailable(unsigned int *pcubMsgSize)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Networking::ReadP2PPacket(void *pubDest, unsigned int cubDest, unsigned int *pcubMsgSize, SteamID *psteamIDRemote)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Networking::AcceptP2PSessionWithUser(SteamID steamIDRemote)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Networking::CloseP2PSessionWithUser(SteamID steamIDRemote)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Networking::GetP2PSessionState(SteamID steamIDRemote, void *pConnectionState)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int Networking::CreateListenSocket(int nVirtualP2PPort, unsigned int nIP, unsigned short nPort, bool bAllowUseOfPacketRelay)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned int Networking::CreateP2PConnectionSocket(SteamID steamIDTarget, int nVirtualPort, int nTimeoutSec, bool bAllowUseOfPacketRelay)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned int Networking::CreateConnectionSocket(unsigned int nIP, unsigned short nPort, int nTimeoutSec)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool Networking::DestroySocket(unsigned int hSocket, bool bNotifyRemoteEnd)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Networking::DestroyListenSocket(unsigned int hSocket, bool bNotifyRemoteEnd)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Networking::SendDataOnSocket(unsigned int hSocket, void *pubData, unsigned int cubData, bool bReliable)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Networking::IsDataAvailableOnSocket(unsigned int hSocket, unsigned int *pcubMsgSize)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Networking::RetrieveDataFromSocket(unsigned int hSocket, void *pubDest, unsigned int cubDest, unsigned int *pcubMsgSize)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Networking::IsDataAvailable(unsigned int hListenSocket, unsigned int *pcubMsgSize, unsigned int *phSocket)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Networking::RetrieveData(unsigned int hListenSocket, void *pubDest, unsigned int cubDest, unsigned int *pcubMsgSize, unsigned int *phSocket)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Networking::GetSocketInfo(unsigned int hSocket, SteamID *pSteamIDRemote, int *peSocketStatus, unsigned int *punIPRemote, unsigned short *punPortRemote)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Networking::GetListenSocketInfo(unsigned int hListenSocket, unsigned int *pnIP, unsigned short *pnPort)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int Networking::GetSocketConnectionType(unsigned int hSocket)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Networking::GetMaxPacketSize(unsigned int hSocket)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
27
src/Steam/Interfaces/SteamNetworking.hpp
Normal file
27
src/Steam/Interfaces/SteamNetworking.hpp
Normal file
@ -0,0 +1,27 @@
|
||||
namespace Steam
|
||||
{
|
||||
class Networking
|
||||
{
|
||||
public:
|
||||
virtual bool SendP2PPacket(SteamID steamIDRemote, const void *pubData, unsigned int cubData, int eP2PSendType);
|
||||
virtual bool IsP2PPacketAvailable(unsigned int *pcubMsgSize);
|
||||
virtual bool ReadP2PPacket(void *pubDest, unsigned int cubDest, unsigned int *pcubMsgSize, SteamID *psteamIDRemote);
|
||||
virtual bool AcceptP2PSessionWithUser(SteamID steamIDRemote);
|
||||
virtual bool CloseP2PSessionWithUser(SteamID steamIDRemote);
|
||||
virtual bool GetP2PSessionState(SteamID steamIDRemote, void *pConnectionState);
|
||||
virtual unsigned int CreateListenSocket(int nVirtualP2PPort, unsigned int nIP, unsigned short nPort, bool bAllowUseOfPacketRelay);
|
||||
virtual unsigned int CreateP2PConnectionSocket(SteamID steamIDTarget, int nVirtualPort, int nTimeoutSec, bool bAllowUseOfPacketRelay);
|
||||
virtual unsigned int CreateConnectionSocket(unsigned int nIP, unsigned short nPort, int nTimeoutSec);
|
||||
virtual bool DestroySocket(unsigned int hSocket, bool bNotifyRemoteEnd);
|
||||
virtual bool DestroyListenSocket(unsigned int hSocket, bool bNotifyRemoteEnd);
|
||||
virtual bool SendDataOnSocket(unsigned int hSocket, void *pubData, unsigned int cubData, bool bReliable);
|
||||
virtual bool IsDataAvailableOnSocket(unsigned int hSocket, unsigned int *pcubMsgSize);
|
||||
virtual bool RetrieveDataFromSocket(unsigned int hSocket, void *pubDest, unsigned int cubDest, unsigned int *pcubMsgSize);
|
||||
virtual bool IsDataAvailable(unsigned int hListenSocket, unsigned int *pcubMsgSize, unsigned int *phSocket);
|
||||
virtual bool RetrieveData(unsigned int hListenSocket, void *pubDest, unsigned int cubDest, unsigned int *pcubMsgSize, unsigned int *phSocket);
|
||||
virtual bool GetSocketInfo(unsigned int hSocket, SteamID *pSteamIDRemote, int *peSocketStatus, unsigned int *punIPRemote, unsigned short *punPortRemote);
|
||||
virtual bool GetListenSocketInfo(unsigned int hListenSocket, unsigned int *pnIP, unsigned short *pnPort);
|
||||
virtual int GetSocketConnectionType(unsigned int hSocket);
|
||||
virtual int GetMaxPacketSize(unsigned int hSocket);
|
||||
};
|
||||
}
|
43
src/Steam/Interfaces/SteamRemoteStorage.cpp
Normal file
43
src/Steam/Interfaces/SteamRemoteStorage.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
#include "..\..\STDInclude.hpp"
|
||||
|
||||
namespace Steam
|
||||
{
|
||||
bool RemoteStorage::FileWrite(const char *pchFile, const void *pvData, int cubData)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int RemoteStorage::GetFileSize(const char *pchFile)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int RemoteStorage::FileRead(const char *pchFile, void *pvData, int cubDataToRead)
|
||||
{
|
||||
OutputDebugStringA(pchFile);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool RemoteStorage::FileExists(const char *pchFile)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int RemoteStorage::GetFileCount()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *RemoteStorage::GetFileNameAndSize(int iFile, int *pnFileSizeInBytes)
|
||||
{
|
||||
*pnFileSizeInBytes = 0;
|
||||
return "";
|
||||
}
|
||||
|
||||
bool RemoteStorage::GetQuota(int *pnTotalBytes, int *puAvailableBytes)
|
||||
{
|
||||
*pnTotalBytes = 0x10000000;
|
||||
*puAvailableBytes = 0x10000000;
|
||||
return false;
|
||||
}
|
||||
}
|
14
src/Steam/Interfaces/SteamRemoteStorage.hpp
Normal file
14
src/Steam/Interfaces/SteamRemoteStorage.hpp
Normal file
@ -0,0 +1,14 @@
|
||||
namespace Steam
|
||||
{
|
||||
class RemoteStorage
|
||||
{
|
||||
public:
|
||||
virtual bool FileWrite(const char *pchFile, const void *pvData, int cubData);
|
||||
virtual int GetFileSize(const char *pchFile);
|
||||
virtual int FileRead(const char *pchFile, void *pvData, int cubDataToRead);
|
||||
virtual bool FileExists(const char *pchFile);
|
||||
virtual int GetFileCount();
|
||||
virtual const char *GetFileNameAndSize(int iFile, int *pnFileSizeInBytes);
|
||||
virtual bool GetQuota(int *pnTotalBytes, int *puAvailableBytes);
|
||||
};
|
||||
}
|
106
src/Steam/Interfaces/SteamUser.cpp
Normal file
106
src/Steam/Interfaces/SteamUser.cpp
Normal file
@ -0,0 +1,106 @@
|
||||
#include "..\..\STDInclude.hpp"
|
||||
|
||||
namespace Steam
|
||||
{
|
||||
int User::GetHSteamUser()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool User::LoggedOn()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
SteamID User::GetSteamID()
|
||||
{
|
||||
static int subId = 0;
|
||||
|
||||
SteamID id;
|
||||
|
||||
if (!subId)
|
||||
{
|
||||
if (Components::Dedicated::IsDedicated()) // Dedi guid
|
||||
{
|
||||
subId = ~0xDED1CADE;
|
||||
}
|
||||
else if (Components::Singleton::IsFirstInstance()) // Hardware guid
|
||||
{
|
||||
DATA_BLOB Data[2];
|
||||
Data[0].pbData = (BYTE *)"AAAAAAAAAA";
|
||||
Data[0].cbData = 10;
|
||||
|
||||
CryptProtectData(&Data[0], NULL, NULL, NULL, NULL, CRYPTPROTECT_LOCAL_MACHINE, &Data[1]);
|
||||
|
||||
subId = ::Utils::OneAtATime((char*)Data[1].pbData, 52);
|
||||
}
|
||||
else // Random guid
|
||||
{
|
||||
subId = (Game::Com_Milliseconds() + timeGetTime());
|
||||
}
|
||||
}
|
||||
|
||||
id.Bits = 0x110000100000000 | subId;
|
||||
return id;
|
||||
}
|
||||
|
||||
int User::InitiateGameConnection(void *pAuthBlob, int cbMaxAuthBlob, SteamID steamIDGameServer, unsigned int unIPServer, unsigned short usPortServer, bool bSecure)
|
||||
{
|
||||
// TODO: Generate auth ticket!
|
||||
return 0;
|
||||
}
|
||||
|
||||
void User::TerminateGameConnection(unsigned int unIPServer, unsigned short usPortServer)
|
||||
{
|
||||
}
|
||||
|
||||
void User::TrackAppUsageEvent(SteamID gameID, int eAppUsageEvent, const char *pchExtraInfo)
|
||||
{
|
||||
}
|
||||
|
||||
bool User::GetUserDataFolder(char *pchBuffer, int cubBuffer)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void User::StartVoiceRecording()
|
||||
{
|
||||
}
|
||||
|
||||
void User::StopVoiceRecording()
|
||||
{
|
||||
}
|
||||
|
||||
int User::GetCompressedVoice(void *pDestBuffer, unsigned int cbDestBufferSize, unsigned int *nBytesWritten)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int User::DecompressVoice(void *pCompressed, unsigned int cbCompressed, void *pDestBuffer, unsigned int cbDestBufferSize, unsigned int *nBytesWritten)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int User::GetAuthSessionTicket(void *pTicket, int cbMaxTicket, unsigned int *pcbTicket)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int User::BeginAuthSession(const void *pAuthTicket, int cbAuthTicket, SteamID steamID)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void User::EndAuthSession(SteamID steamID)
|
||||
{
|
||||
}
|
||||
|
||||
void User::CancelAuthTicket(unsigned int hAuthTicket)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int User::UserHasLicenseForApp(SteamID steamID, unsigned int appID)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
24
src/Steam/Interfaces/SteamUser.hpp
Normal file
24
src/Steam/Interfaces/SteamUser.hpp
Normal file
@ -0,0 +1,24 @@
|
||||
namespace Steam
|
||||
{
|
||||
class User
|
||||
{
|
||||
public:
|
||||
virtual int GetHSteamUser();
|
||||
virtual bool LoggedOn();
|
||||
virtual SteamID GetSteamID();
|
||||
|
||||
virtual int InitiateGameConnection(void *pAuthBlob, int cbMaxAuthBlob, SteamID steamIDGameServer, unsigned int unIPServer, unsigned short usPortServer, bool bSecure);
|
||||
virtual void TerminateGameConnection(unsigned int unIPServer, unsigned short usPortServer);
|
||||
virtual void TrackAppUsageEvent(SteamID gameID, int eAppUsageEvent, const char *pchExtraInfo = "");
|
||||
virtual bool GetUserDataFolder(char *pchBuffer, int cubBuffer);
|
||||
virtual void StartVoiceRecording();
|
||||
virtual void StopVoiceRecording();
|
||||
virtual int GetCompressedVoice(void *pDestBuffer, unsigned int cbDestBufferSize, unsigned int *nBytesWritten);
|
||||
virtual int DecompressVoice(void *pCompressed, unsigned int cbCompressed, void *pDestBuffer, unsigned int cbDestBufferSize, unsigned int *nBytesWritten);
|
||||
virtual unsigned int GetAuthSessionTicket(void *pTicket, int cbMaxTicket, unsigned int *pcbTicket);
|
||||
virtual int BeginAuthSession(const void *pAuthTicket, int cbAuthTicket, SteamID steamID);
|
||||
virtual void EndAuthSession(SteamID steamID);
|
||||
virtual void CancelAuthTicket(unsigned int hAuthTicket);
|
||||
virtual unsigned int UserHasLicenseForApp(SteamID steamID, unsigned int appID);
|
||||
};
|
||||
}
|
96
src/Steam/Interfaces/SteamUtils.cpp
Normal file
96
src/Steam/Interfaces/SteamUtils.cpp
Normal file
@ -0,0 +1,96 @@
|
||||
#include "..\..\STDInclude.hpp"
|
||||
|
||||
namespace Steam
|
||||
{
|
||||
unsigned int Utils::GetSecondsSinceAppActive()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int Utils::GetSecondsSinceComputerActive()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Utils::GetConnectedUniverse()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned int Utils::GetServerRealTime()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* Utils::GetIPCountry()
|
||||
{
|
||||
return "US";
|
||||
}
|
||||
|
||||
bool Utils::GetImageSize(int iImage, unsigned int *pnWidth, unsigned int *pnHeight)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Utils::GetImageRGBA(int iImage, unsigned char *pubDest, int nDestBufferSize)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Utils::GetCSERIPPort(unsigned int *unIP, unsigned short *usPort)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned char Utils::GetCurrentBatteryPower()
|
||||
{
|
||||
return 255;
|
||||
}
|
||||
|
||||
unsigned int Utils::GetAppID()
|
||||
{
|
||||
return 10190;
|
||||
}
|
||||
|
||||
void Utils::SetOverlayNotificationPosition(int eNotificationPosition)
|
||||
{
|
||||
}
|
||||
|
||||
bool Utils::IsAPICallCompleted(unsigned __int64 hSteamAPICall, bool *pbFailed)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int Utils::GetAPICallFailureReason(unsigned __int64 hSteamAPICall)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool Utils::GetAPICallResult(unsigned __int64 hSteamAPICall, void *pCallback, int cubCallback, int iCallbackExpected, bool *pbFailed)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void Utils::RunFrame()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned int Utils::GetIPCCallCount()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Utils::SetWarningMessageHook(void(*pFunction)(int hpipe, const char *message))
|
||||
{
|
||||
}
|
||||
|
||||
bool Utils::IsOverlayEnabled()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Utils::BOverlayNeedsPresent()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
26
src/Steam/Interfaces/SteamUtils.hpp
Normal file
26
src/Steam/Interfaces/SteamUtils.hpp
Normal file
@ -0,0 +1,26 @@
|
||||
namespace Steam
|
||||
{
|
||||
class Utils
|
||||
{
|
||||
public:
|
||||
virtual unsigned int GetSecondsSinceAppActive();
|
||||
virtual unsigned int GetSecondsSinceComputerActive();
|
||||
virtual int GetConnectedUniverse();
|
||||
virtual unsigned int GetServerRealTime();
|
||||
virtual const char *GetIPCountry();
|
||||
virtual bool GetImageSize(int iImage, unsigned int *pnWidth, unsigned int *pnHeight);
|
||||
virtual bool GetImageRGBA(int iImage, unsigned char *pubDest, int nDestBufferSize);
|
||||
virtual bool GetCSERIPPort(unsigned int *unIP, unsigned short *usPort);
|
||||
virtual unsigned char GetCurrentBatteryPower();
|
||||
virtual unsigned int GetAppID();
|
||||
virtual void SetOverlayNotificationPosition(int eNotificationPosition);
|
||||
virtual bool IsAPICallCompleted(unsigned __int64 hSteamAPICall, bool *pbFailed);
|
||||
virtual int GetAPICallFailureReason(unsigned __int64 hSteamAPICall);
|
||||
virtual bool GetAPICallResult(unsigned __int64 hSteamAPICall, void *pCallback, int cubCallback, int iCallbackExpected, bool *pbFailed);
|
||||
virtual void RunFrame();
|
||||
virtual unsigned int GetIPCCallCount();
|
||||
virtual void SetWarningMessageHook(void(*pFunction)(int hpipe, const char *message));
|
||||
virtual bool IsOverlayEnabled();
|
||||
virtual bool BOverlayNeedsPresent();
|
||||
};
|
||||
}
|
166
src/Steam/Steam.cpp
Normal file
166
src/Steam/Steam.cpp
Normal file
@ -0,0 +1,166 @@
|
||||
#include "..\STDInclude.hpp"
|
||||
#include "Steam.hpp"
|
||||
|
||||
namespace Steam
|
||||
{
|
||||
uint64_t Callbacks::CallID = 0;
|
||||
std::map<uint64_t, bool> Callbacks::Calls;
|
||||
std::map<uint64_t, Callbacks::Base*> Callbacks::ResultHandlers;
|
||||
std::vector<Callbacks::Result> Callbacks::Results;
|
||||
std::vector<Callbacks::Base*> Callbacks::CallbackList;
|
||||
|
||||
uint64_t Callbacks::RegisterCall()
|
||||
{
|
||||
Callbacks::Calls[Callbacks::CallID] = false;
|
||||
return Callbacks::CallID++;
|
||||
}
|
||||
|
||||
void Callbacks::RegisterCallback(Callbacks::Base* handler, int callback)
|
||||
{
|
||||
handler->SetICallback(callback);
|
||||
Callbacks::CallbackList.push_back(handler);
|
||||
}
|
||||
|
||||
void Callbacks::RegisterCallResult(uint64_t call, Callbacks::Base* result)
|
||||
{
|
||||
Callbacks::ResultHandlers[call] = result;
|
||||
}
|
||||
|
||||
void Callbacks::ReturnCall(void* data, int size, int type, uint64_t call)
|
||||
{
|
||||
Callbacks::Result result;
|
||||
|
||||
Callbacks::Calls[call] = true;
|
||||
|
||||
result.call = call;
|
||||
result.data = data;
|
||||
result.size = size;
|
||||
result.type = type;
|
||||
|
||||
Callbacks::Results.push_back(result);
|
||||
}
|
||||
|
||||
void Callbacks::RunCallbacks()
|
||||
{
|
||||
for (auto result : Callbacks::Results)
|
||||
{
|
||||
if (Callbacks::ResultHandlers.find(result.call) != Callbacks::ResultHandlers.end())
|
||||
{
|
||||
Callbacks::ResultHandlers[result.call]->Run(result.data, false, result.call);
|
||||
}
|
||||
|
||||
for (auto callback : Callbacks::CallbackList)
|
||||
{
|
||||
if (callback && callback->GetICallback() == result.type)
|
||||
{
|
||||
callback->Run(result.data, false, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (result.data)
|
||||
{
|
||||
delete[] result.data;
|
||||
}
|
||||
}
|
||||
|
||||
Callbacks::Results.clear();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
bool SteamAPI_Init()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void SteamAPI_RegisterCallResult(Callbacks::Base* result, uint64_t call)
|
||||
{
|
||||
Callbacks::RegisterCallResult(call, result);
|
||||
}
|
||||
|
||||
void SteamAPI_RegisterCallback(Callbacks::Base* handler, int callback)
|
||||
{
|
||||
Callbacks::RegisterCallback(handler, callback);
|
||||
}
|
||||
|
||||
void SteamAPI_RunCallbacks()
|
||||
{
|
||||
Callbacks::RunCallbacks();
|
||||
}
|
||||
|
||||
void SteamAPI_Shutdown()
|
||||
{
|
||||
}
|
||||
|
||||
void SteamAPI_UnregisterCallResult()
|
||||
{
|
||||
}
|
||||
|
||||
void SteamAPI_UnregisterCallback()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool SteamGameServer_Init()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void SteamGameServer_RunCallbacks()
|
||||
{
|
||||
}
|
||||
|
||||
void SteamGameServer_Shutdown()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Steam::Friends* SteamFriends()
|
||||
{
|
||||
static Steam::Friends iFriends;
|
||||
return &iFriends;
|
||||
}
|
||||
|
||||
Steam::Matchmaking* SteamMatchmaking()
|
||||
{
|
||||
static Steam::Matchmaking iMatchmaking;
|
||||
return &iMatchmaking;
|
||||
}
|
||||
|
||||
Steam::GameServer* SteamGameServer()
|
||||
{
|
||||
static Steam::GameServer iGameServer;
|
||||
return &iGameServer;
|
||||
}
|
||||
|
||||
Steam::MasterServerUpdater* SteamMasterServerUpdater()
|
||||
{
|
||||
static Steam::MasterServerUpdater iMasterServerUpdater;
|
||||
return &iMasterServerUpdater;
|
||||
}
|
||||
|
||||
Steam::Networking* SteamNetworking()
|
||||
{
|
||||
static Steam::Networking iNetworking;
|
||||
return &iNetworking;
|
||||
}
|
||||
|
||||
Steam::RemoteStorage* SteamRemoteStorage()
|
||||
{
|
||||
static Steam::RemoteStorage iRemoteStorage;
|
||||
return &iRemoteStorage;
|
||||
}
|
||||
|
||||
Steam::User* SteamUser()
|
||||
{
|
||||
static Steam::User iUser;
|
||||
return &iUser;
|
||||
}
|
||||
|
||||
Steam::Utils* SteamUtils()
|
||||
{
|
||||
static Steam::Utils iUtils;
|
||||
return &iUtils;
|
||||
}
|
||||
}
|
||||
}
|
91
src/Steam/Steam.hpp
Normal file
91
src/Steam/Steam.hpp
Normal file
@ -0,0 +1,91 @@
|
||||
#pragma once
|
||||
|
||||
#define STEAM_EXPORT extern "C" __declspec(dllexport)
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
unsigned int AccountID : 32;
|
||||
unsigned int AccountInstance : 20;
|
||||
unsigned int AccountType : 4;
|
||||
int Universe : 8;
|
||||
};
|
||||
|
||||
unsigned long long Bits;
|
||||
} SteamID;
|
||||
|
||||
#include "Interfaces\SteamUser.hpp"
|
||||
#include "Interfaces\SteamUtils.hpp"
|
||||
#include "Interfaces\SteamFriends.hpp"
|
||||
#include "Interfaces\SteamGameServer.hpp"
|
||||
#include "Interfaces\SteamNetworking.hpp"
|
||||
#include "Interfaces\SteamMatchmaking.hpp"
|
||||
#include "Interfaces\SteamRemoteStorage.hpp"
|
||||
#include "Interfaces\SteamMasterServerUpdater.hpp"
|
||||
|
||||
namespace Steam
|
||||
{
|
||||
class Callbacks
|
||||
{
|
||||
public:
|
||||
class Base
|
||||
{
|
||||
public:
|
||||
Base() : Flags(0), Callback(0) {};
|
||||
|
||||
virtual void Run(void *pvParam) = 0;
|
||||
virtual void Run(void *pvParam, bool bIOFailure, uint64_t hSteamAPICall) = 0;
|
||||
virtual int GetCallbackSizeBytes() = 0;
|
||||
|
||||
int GetICallback() { return Callback; }
|
||||
void SetICallback(int iCallback) { Callback = iCallback; }
|
||||
|
||||
protected:
|
||||
unsigned char Flags;
|
||||
int Callback;
|
||||
};
|
||||
|
||||
struct Result
|
||||
{
|
||||
void* data;
|
||||
int size;
|
||||
int type;
|
||||
uint64_t call;
|
||||
};
|
||||
|
||||
static uint64_t RegisterCall();
|
||||
static void RegisterCallback(Base* handler, int callback);
|
||||
static void RegisterCallResult(uint64_t call, Base* result);
|
||||
static void ReturnCall(void* data, int size, int type, uint64_t call);
|
||||
static void RunCallbacks();
|
||||
|
||||
private:
|
||||
static uint64_t CallID;
|
||||
static std::map<uint64_t, bool> Calls;
|
||||
static std::map<uint64_t, Base*> ResultHandlers;
|
||||
static std::vector<Result> Results;
|
||||
static std::vector<Base*> CallbackList;
|
||||
};
|
||||
|
||||
STEAM_EXPORT bool SteamAPI_Init();
|
||||
STEAM_EXPORT void SteamAPI_RegisterCallResult(Callbacks::Base* result, uint64_t call);
|
||||
STEAM_EXPORT void SteamAPI_RegisterCallback(Callbacks::Base* handler, int callback);
|
||||
STEAM_EXPORT void SteamAPI_RunCallbacks();
|
||||
STEAM_EXPORT void SteamAPI_Shutdown();
|
||||
STEAM_EXPORT void SteamAPI_UnregisterCallResult();
|
||||
STEAM_EXPORT void SteamAPI_UnregisterCallback();
|
||||
|
||||
STEAM_EXPORT bool SteamGameServer_Init();
|
||||
STEAM_EXPORT void SteamGameServer_RunCallbacks();
|
||||
STEAM_EXPORT void SteamGameServer_Shutdown();
|
||||
|
||||
STEAM_EXPORT Steam::Friends* SteamFriends();
|
||||
STEAM_EXPORT Steam::Matchmaking* SteamMatchmaking();
|
||||
STEAM_EXPORT Steam::GameServer* SteamGameServer();
|
||||
STEAM_EXPORT Steam::MasterServerUpdater* SteamMasterServerUpdater();
|
||||
STEAM_EXPORT Steam::Networking* SteamNetworking();
|
||||
STEAM_EXPORT Steam::RemoteStorage* SteamRemoteStorage();
|
||||
STEAM_EXPORT Steam::User* SteamUser();
|
||||
STEAM_EXPORT Steam::Utils* SteamUtils();
|
||||
}
|
116
src/Utils/Hooking.cpp
Normal file
116
src/Utils/Hooking.cpp
Normal file
@ -0,0 +1,116 @@
|
||||
#include "..\STDInclude.hpp"
|
||||
|
||||
namespace Utils
|
||||
{
|
||||
Hook::~Hook()
|
||||
{
|
||||
if (Hook::Initialized)
|
||||
{
|
||||
Hook::Uninstall();
|
||||
}
|
||||
}
|
||||
|
||||
Hook* Hook::Initialize(DWORD place, void(*stub)(), bool useJump)
|
||||
{
|
||||
return Hook::Initialize(place, (void*)stub, useJump);
|
||||
}
|
||||
|
||||
Hook* Hook::Initialize(DWORD place, void* stub, bool useJump)
|
||||
{
|
||||
return Hook::Initialize((void*)place, stub, useJump);
|
||||
}
|
||||
|
||||
Hook* Hook::Initialize(void* place, void* stub, bool useJump)
|
||||
{
|
||||
if (Hook::Initialized) return this;
|
||||
Hook::Initialized = true;
|
||||
|
||||
Hook::UseJump = useJump;
|
||||
Hook::Place = place;
|
||||
Hook::Stub = stub;
|
||||
|
||||
Hook::Original = (char*)Hook::Place + 5 + *(DWORD*)((DWORD)Hook::Place + 1);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
Hook* Hook::Install()
|
||||
{
|
||||
Hook::StateMutex.lock();
|
||||
|
||||
if (!Hook::Initialized || Hook::Installed)
|
||||
{
|
||||
Hook::StateMutex.unlock();
|
||||
return this;
|
||||
}
|
||||
|
||||
Hook::Installed = true;
|
||||
|
||||
DWORD d;
|
||||
VirtualProtect(Hook::Place, sizeof(Hook::Buffer), PAGE_EXECUTE_READWRITE, &d);
|
||||
memcpy(Hook::Buffer, Hook::Place, sizeof(Hook::Buffer));
|
||||
|
||||
char* Code = (char*)Hook::Place;
|
||||
|
||||
*Code = (char)(Hook::UseJump ? 0xE9 : 0xE8);
|
||||
|
||||
*(size_t*)&Code[1] = (size_t)Hook::Stub - ((size_t)Hook::Place + 5);
|
||||
|
||||
VirtualProtect(Hook::Place, sizeof(Hook::Buffer), d, &d);
|
||||
|
||||
FlushInstructionCache(GetCurrentProcess(), Hook::Place, sizeof(Hook::Buffer));
|
||||
|
||||
Hook::StateMutex.unlock();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
void Hook::Quick()
|
||||
{
|
||||
if (Hook::Installed)
|
||||
{
|
||||
Hook::Installed = false;
|
||||
}
|
||||
}
|
||||
|
||||
Hook* Hook::Uninstall()
|
||||
{
|
||||
Hook::StateMutex.lock();
|
||||
|
||||
if (!Hook::Initialized || !Hook::Installed)
|
||||
{
|
||||
Hook::StateMutex.unlock();
|
||||
return this;
|
||||
}
|
||||
|
||||
Hook::Installed = false;
|
||||
|
||||
DWORD d;
|
||||
VirtualProtect(Hook::Place, sizeof(Hook::Buffer), PAGE_EXECUTE_READWRITE, &d);
|
||||
|
||||
memcpy(Hook::Place, Hook::Buffer, sizeof(Hook::Buffer));
|
||||
|
||||
VirtualProtect(Hook::Place, sizeof(Hook::Buffer), d, &d);
|
||||
|
||||
FlushInstructionCache(GetCurrentProcess(), Hook::Place, sizeof(Hook::Buffer));
|
||||
|
||||
Hook::StateMutex.unlock();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
void* Hook::GetAddress()
|
||||
{
|
||||
return Hook::Place;
|
||||
}
|
||||
|
||||
void Hook::Nop(void* place, size_t length)
|
||||
{
|
||||
memset(place, 0x90, length);
|
||||
}
|
||||
|
||||
void Hook::Nop(DWORD place, size_t length)
|
||||
{
|
||||
Nop((void*)place, length);
|
||||
}
|
||||
}
|
104
src/Utils/Hooking.hpp
Normal file
104
src/Utils/Hooking.hpp
Normal file
@ -0,0 +1,104 @@
|
||||
#pragma once
|
||||
|
||||
#define HOOK_JUMP true
|
||||
#define HOOK_CALL false
|
||||
|
||||
namespace Utils
|
||||
{
|
||||
class Hook
|
||||
{
|
||||
public:
|
||||
Hook() : Place(nullptr), Stub(nullptr), Initialized(false), Installed(false), UseJump(false) { ZeroMemory(Hook::Buffer, sizeof(Hook::Buffer)); }
|
||||
Hook(void* place, void* stub, bool useJump = true) : Hook() { Hook::Initialize(place, stub, useJump); }
|
||||
Hook(DWORD place, void* stub, bool useJump = true) : Hook((void*)place, stub, useJump) {}
|
||||
|
||||
~Hook();
|
||||
|
||||
Hook* Initialize(void* place, void* stub, bool useJump = true);
|
||||
Hook* Initialize(DWORD place, void* stub, bool useJump = true);
|
||||
Hook* Initialize(DWORD place, void(*stub)(), bool useJump = true); // For lambdas
|
||||
Hook* Install();
|
||||
Hook* Uninstall();
|
||||
|
||||
void* GetAddress();
|
||||
void Quick();
|
||||
|
||||
template <typename T> static T Call(DWORD function)
|
||||
{
|
||||
__asm
|
||||
{
|
||||
mov eax, function
|
||||
call eax
|
||||
}
|
||||
}
|
||||
|
||||
static void Nop(void* place, size_t length);
|
||||
static void Nop(DWORD place, size_t length);
|
||||
|
||||
template <typename T> static void Set(void* place, T value)
|
||||
{
|
||||
*(T*)place = value;
|
||||
FlushInstructionCache(GetCurrentProcess(), place, sizeof(T));
|
||||
}
|
||||
|
||||
template <typename T> static void Set(DWORD place, T value)
|
||||
{
|
||||
return Set<T>((void*)place, value);
|
||||
}
|
||||
|
||||
template <typename T> static void Xor(void* place, T value)
|
||||
{
|
||||
*(T*)place ^= value;
|
||||
FlushInstructionCache(GetCurrentProcess(), place, sizeof(T));
|
||||
}
|
||||
|
||||
template <typename T> static void Xor(DWORD place, T value)
|
||||
{
|
||||
return Xor<T>((void*)place, value);
|
||||
}
|
||||
|
||||
template <typename T> static void Or(void* place, T value)
|
||||
{
|
||||
*(T*)place |= value;
|
||||
FlushInstructionCache(GetCurrentProcess(), place, sizeof(T));
|
||||
}
|
||||
|
||||
template <typename T> static void Or(DWORD place, T value)
|
||||
{
|
||||
return Or<T>((void*)place, value);
|
||||
}
|
||||
|
||||
template <typename T> static void And(void* place, T value)
|
||||
{
|
||||
*(T*)place &= value;
|
||||
FlushInstructionCache(GetCurrentProcess(), place, sizeof(T));
|
||||
}
|
||||
|
||||
template <typename T> static void And(DWORD place, T value)
|
||||
{
|
||||
return And<T>((void*)place, value);
|
||||
}
|
||||
|
||||
template <typename T> static T Get(void* place)
|
||||
{
|
||||
return *(T*)place;
|
||||
}
|
||||
|
||||
template <typename T> static T Get(DWORD place)
|
||||
{
|
||||
return Get<T>((void*)place);
|
||||
}
|
||||
|
||||
private:
|
||||
bool Initialized;
|
||||
bool Installed;
|
||||
|
||||
void* Place;
|
||||
void* Stub;
|
||||
void* Original;
|
||||
char Buffer[5];
|
||||
bool UseJump;
|
||||
|
||||
std::mutex StateMutex;
|
||||
};
|
||||
}
|
137
src/Utils/Utils.cpp
Normal file
137
src/Utils/Utils.cpp
Normal file
@ -0,0 +1,137 @@
|
||||
#include "..\STDInclude.hpp"
|
||||
|
||||
#define VA_BUFFER_COUNT 4
|
||||
#define VA_BUFFER_SIZE 4096
|
||||
|
||||
namespace Utils
|
||||
{
|
||||
const char *VA(const char *fmt, ...)
|
||||
{
|
||||
static char g_vaBuffer[VA_BUFFER_COUNT][VA_BUFFER_SIZE];
|
||||
static int g_vaNextBufferIndex = 0;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
char* dest = g_vaBuffer[g_vaNextBufferIndex];
|
||||
vsprintf_s(g_vaBuffer[g_vaNextBufferIndex], fmt, ap);
|
||||
g_vaNextBufferIndex = (g_vaNextBufferIndex + 1) % VA_BUFFER_COUNT;
|
||||
va_end(ap);
|
||||
return dest;
|
||||
}
|
||||
|
||||
std::string StrToLower(std::string input)
|
||||
{
|
||||
std::transform(input.begin(), input.end(), input.begin(), ::tolower);
|
||||
return input;
|
||||
}
|
||||
|
||||
bool EndsWith(const char* heystack, const char* needle)
|
||||
{
|
||||
return (strstr(heystack, needle) == (heystack + strlen(heystack) - strlen(needle)));
|
||||
}
|
||||
|
||||
std::vector<std::string> Explode(const std::string& str, char delim)
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
std::istringstream iss(str);
|
||||
|
||||
for (std::string token; std::getline(iss, token, delim);)
|
||||
{
|
||||
std::string _entry = std::move(token);
|
||||
|
||||
// Remove trailing 0x0 bytes
|
||||
while (_entry.size() && !_entry[_entry.size() - 1])
|
||||
{
|
||||
_entry = _entry.substr(0, _entry.size() - 1);
|
||||
}
|
||||
|
||||
result.push_back(_entry);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Replace(std::string &string, std::string find, std::string replace)
|
||||
{
|
||||
size_t nPos = 0;
|
||||
|
||||
while ((nPos = string.find(find, nPos)) != std::string::npos)
|
||||
{
|
||||
string = string.replace(nPos, find.length(), replace);
|
||||
nPos += replace.length();
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int OneAtATime(char *key, size_t len)
|
||||
{
|
||||
unsigned int hash, i;
|
||||
for (hash = i = 0; i < len; ++i)
|
||||
{
|
||||
hash += key[i];
|
||||
hash += (hash << 10);
|
||||
hash ^= (hash >> 6);
|
||||
}
|
||||
hash += (hash << 3);
|
||||
hash ^= (hash >> 11);
|
||||
hash += (hash << 15);
|
||||
return hash;
|
||||
}
|
||||
|
||||
// Infostring class
|
||||
void InfoString::Set(std::string key, std::string value)
|
||||
{
|
||||
this->KeyValuePairs[key] = value;
|
||||
}
|
||||
|
||||
std::string InfoString::Get(std::string key)
|
||||
{
|
||||
if (this->KeyValuePairs.find(key) != this->KeyValuePairs.end())
|
||||
{
|
||||
return this->KeyValuePairs[key];
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string InfoString::Build()
|
||||
{
|
||||
std::string infoString;
|
||||
|
||||
bool first = true;
|
||||
|
||||
for (auto i = this->KeyValuePairs.begin(); i != this->KeyValuePairs.end(); i++)
|
||||
{
|
||||
if (first) first = false;
|
||||
else infoString.append("\\");
|
||||
|
||||
infoString.append(i->first); // Key
|
||||
infoString.append("\\");
|
||||
infoString.append(i->second); // Value
|
||||
}
|
||||
|
||||
return infoString;
|
||||
}
|
||||
|
||||
void InfoString::Dump()
|
||||
{
|
||||
for (auto i = this->KeyValuePairs.begin(); i != this->KeyValuePairs.end(); i++)
|
||||
{
|
||||
OutputDebugStringA(Utils::VA("%s: %s", i->first.data(), i->second.data()));
|
||||
}
|
||||
}
|
||||
|
||||
void InfoString::Parse(std::string buffer)
|
||||
{
|
||||
if (buffer[0] == '\\')
|
||||
{
|
||||
buffer = buffer.substr(1);
|
||||
}
|
||||
|
||||
std::vector<std::string> KeyValues = Utils::Explode(buffer, '\\');
|
||||
|
||||
for (unsigned int i = 0; i < (KeyValues.size() - 1); i+=2)
|
||||
{
|
||||
this->KeyValuePairs[KeyValues[i]] = KeyValues[i + 1];
|
||||
}
|
||||
}
|
||||
}
|
28
src/Utils/Utils.hpp
Normal file
28
src/Utils/Utils.hpp
Normal file
@ -0,0 +1,28 @@
|
||||
namespace Utils
|
||||
{
|
||||
const char *VA(const char *fmt, ...);
|
||||
std::string StrToLower(std::string input);
|
||||
bool EndsWith(const char* heystack, const char* needle);
|
||||
std::vector<std::string> Explode(const std::string& str, char delim);
|
||||
void Replace(std::string &string, std::string find, std::string replace);
|
||||
unsigned int OneAtATime(char *key, size_t len);
|
||||
|
||||
class InfoString
|
||||
{
|
||||
public:
|
||||
InfoString() {};
|
||||
InfoString(std::string buffer) :InfoString() { this->Parse(buffer); };
|
||||
InfoString(const InfoString &obj) { this->KeyValuePairs = obj.KeyValuePairs; };
|
||||
|
||||
void Set(std::string key, std::string value);
|
||||
std::string Get(std::string key);
|
||||
|
||||
std::string Build();
|
||||
|
||||
void Dump();
|
||||
|
||||
private:
|
||||
std::map<std::string, std::string> KeyValuePairs;
|
||||
void Parse(std::string buffer);
|
||||
};
|
||||
}
|
Reference in New Issue
Block a user