Dedicated party stuff.

This commit is contained in:
momo5502 2015-12-27 03:56:00 +01:00
parent ca9725e5a4
commit 412dbe3d33
25 changed files with 525 additions and 29 deletions

View File

@ -107,6 +107,6 @@ namespace Components
Renderer::OnFrame(Colors::UpdateColorTable);
// Register dvar
Colors::NewColors = Dvar::Var::Register<bool>("cg_newColors", true, Game::dvar_flag::DVAR_FLAG_SAVED, "Use Warfare˛ color code style.");
Colors::NewColors = Dvar::Register<bool>("cg_newColors", true, Game::dvar_flag::DVAR_FLAG_SAVED, "Use Warfare˛ color code style.");
}
}

View 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);
}
}
}

View 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();
};
}

View File

@ -100,20 +100,32 @@ namespace Components
}
}
template<> static Dvar::Var Dvar::Var::Register(const char* name, bool value, Game::dvar_flag flag, const char* description)
void Dvar::Var::SetRaw(int integer)
{
return Game::Dvar_RegisterBool(name, value, flag, description);
if (this->dvar)
{
this->dvar->current.integer = integer;
}
}
template<> static Dvar::Var Dvar::Var::Register(const char* name, const char* value, Game::dvar_flag flag, const char* description)
template<> static Dvar::Var Dvar::Register(const char* name, bool value, Dvar::Flag flag, const char* description)
{
return Game::Dvar_RegisterString(name, value, flag, 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::Var::Register<const char*>(name, "Unknown Soldier", (Game::dvar_flag)(flag | Game::dvar_flag::DVAR_FLAG_SAVED), description).Get<Game::dvar_t*>();
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()

View File

@ -3,6 +3,14 @@ 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:
@ -21,8 +29,8 @@ namespace Components
void Set(int integer);
void Set(float value);
// Only strings and bools use this type of declaration
template<typename T> static Var Register(const char* name, T value, Game::dvar_flag flag, const char* description);
// TODO: Add others
void SetRaw(int integer);
private:
Game::dvar_t* dvar;
@ -31,6 +39,10 @@ namespace Components
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);
};

View File

@ -18,6 +18,7 @@ namespace Components
Loader::Register(new Network());
Loader::Register(new RawFiles());
Loader::Register(new Renderer());
Loader::Register(new Dedicated());
Loader::Register(new FastFiles());
Loader::Register(new Materials());
Loader::Register(new FileSystem());

View File

@ -32,6 +32,7 @@ namespace Components
#include "Party.hpp" // Destroys the order, but requires network classes :D
#include "RawFiles.hpp"
#include "Renderer.hpp"
#include "Dedicated.hpp"
#include "FastFiles.hpp"
#include "Materials.hpp"
#include "FileSystem.hpp"

View File

@ -34,7 +34,7 @@ namespace Components
Utils::Hook(0x629B90, Localization::Get, HOOK_JUMP).Install()->Quick();
//Localization::Set("MENU_MULTIPLAYER_CAPS", "^5Fotze");
Localization::UseLocalization = Dvar::Var::Register<bool>("ui_localize", true, Game::dvar_flag::DVAR_FLAG_NONE, "Use localization strings");
Localization::UseLocalization = Dvar::Register<bool>("ui_localize", true, Game::dvar_flag::DVAR_FLAG_NONE, "Use localization strings");
}
Localization::~Localization()

View File

@ -3,6 +3,19 @@
namespace Components
{
Party::JoinContainer Party::Container;
std::map<uint64_t, Network::Address> Party::LobbyMap;
SteamID Party::GenerateLobbyId()
{
SteamID id;
id.m_comp.m_unAccountID = Game::Com_Milliseconds();
id.m_comp.m_EUniverse = 1;
id.m_comp.m_EAccountType = 8;
id.m_comp.m_unAccountInstance = 0x40000;
return id;
}
void Party::Connect(Network::Address target)
{
@ -16,6 +29,42 @@ namespace Components
Command::Execute("openmenu popup_reconnectingtoparty");
}
const char* Party::GetLobbyInfo(SteamID lobby, std::string key)
{
if (Party::LobbyMap.find(lobby.m_Bits) != Party::LobbyMap.end())
{
Network::Address address = Party::LobbyMap[lobby.m_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.m_Bits) != Party::LobbyMap.end())
{
Party::LobbyMap.erase(Party::LobbyMap.find(lobby.m_Bits));
}
}
Game::netadr_t* PartyHost_GetMemberAddressBySlotInState(int unk, void *party, const int slot)
{
Game::netadr_t* addr = Game::PartyHost_GetMemberAddressBySlot(unk, party, slot);
OutputDebugStringA(Network::Address(addr).GetString());
return addr;
}
Party::Party()
{
// various changes to SV_DirectConnect-y stuff to allow non-party joinees
@ -29,6 +78,36 @@ namespace Components
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);
Utils::Hook::Nop(0x4CAA5D, 5);
// Steam_JoinLobby call causes migration
Utils::Hook::Nop(0x5AF851, 5);
Utils::Hook::Set<BYTE>(0x5AF85B, 0xEB);
Utils::Hook(0x5B5544, PartyHost_GetMemberAddressBySlotInState, HOOK_CALL).Install()->Quick();
Command::Add("connect", [] (Command::Params params)
{
if (params.Length() < 2)
@ -39,6 +118,28 @@ namespace Components
Party::Connect(Network::Address(params[1]));
});
Command::Add("connect2", [] (Command::Params params)
{
if (params.Length() < 2)
{
return;
}
Network::Address address(params[1]);
SteamID id = Party::GenerateLobbyId();
Party::LobbyMap[id.m_Bits] = address;
OutputDebugStringA(Utils::VA("Mapping %llX -> %s", id.m_Bits, address.GetString()));
Game::Steam_JoinLobby(id, 0);
// Callback not registered on first try
// TODO: Fix :D
if (Party::LobbyMap.size() <= 1) Game::Steam_JoinLobby(id, 0);
});
Renderer::OnFrame([] ()
{
if (!Party::Container.Valid) return;
@ -128,6 +229,6 @@ namespace Components
Party::~Party()
{
Party::LobbyMap.clear();
}
}

View File

@ -8,6 +8,8 @@ namespace Components
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
@ -19,5 +21,8 @@ namespace Components
};
static JoinContainer Container;
static std::map<uint64_t, Network::Address> LobbyMap;
static SteamID GenerateLobbyId();
};
}

View File

@ -17,17 +17,34 @@ namespace Components
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);
//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);
//Utils::Hook::Set<bool>(0x1AD3680, true);
// LSP disabled
Utils::Hook::Set<BYTE>(0x435950, 0xC3); // LSP HELLO

View File

@ -21,7 +21,7 @@ namespace Components
Window::Window()
{
// Borderless window
Window::NoBorder = Dvar::Var::Register<bool>("r_noborder", true, Game::dvar_flag::DVAR_FLAG_SAVED, "Do not use a border in windowed mode");
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();
}
}

View File

@ -61,6 +61,9 @@ namespace Game
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;
sendOOB_t OOBPrint = (sendOOB_t)0x4AEF00;
@ -69,12 +72,16 @@ namespace Game
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;

View File

@ -139,6 +139,12 @@ namespace Game
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;
@ -154,6 +160,9 @@ namespace Game
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;
@ -166,6 +175,9 @@ namespace Game
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;

View File

@ -890,4 +890,30 @@ namespace Game
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;
};
}

View File

@ -8,9 +8,11 @@
#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>
@ -21,12 +23,12 @@
#include <algorithm>
#include <regex>
#include "Game\Structs.hpp"
#include "Game\Functions.hpp"
#include "Utils\Utils.hpp"
#include "Utils\Hooking.hpp"
#include "Steam\Steam.hpp"
#include "Game\Structs.hpp"
#include "Game\Functions.hpp"
#include "Components\Loader.hpp"

View File

@ -24,7 +24,6 @@ namespace Steam
unsigned __int64 Matchmaking::RequestLobbyList()
{
// TODO: Implement
return 0;
}
@ -51,18 +50,42 @@ namespace Steam
unsigned __int64 Matchmaking::CreateLobby(int eLobbyType, int cMaxMembers)
{
// TODO: Implement
return 0;
uint64_t result = Callbacks::RegisterCall();
LobbyCreated* retvals = new LobbyCreated;
SteamID id;
id.m_comp.m_unAccountID = 1337132;
id.m_comp.m_EUniverse = 1;
id.m_comp.m_EAccountType = 8;
id.m_comp.m_unAccountInstance = 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)
{
// TODO: Implement
return 0;
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)
@ -77,12 +100,12 @@ namespace Steam
SteamID Matchmaking::GetLobbyMemberByIndex(SteamID steamIDLobby, int iMember)
{
return SteamID();
return SteamUser()->GetSteamID();
}
const char *Matchmaking::GetLobbyData(SteamID steamIDLobby, const char *pchKey)
{
return "";
return Components::Party::GetLobbyInfo(steamIDLobby, pchKey);
}
bool Matchmaking::SetLobbyData(SteamID steamIDLobby, const char *pchKey, const char *pchValue)
@ -160,7 +183,7 @@ namespace Steam
SteamID Matchmaking::GetLobbyOwner(SteamID steamIDLobby)
{
return SteamID();
return SteamUser()->GetSteamID();
}
bool Matchmaking::SetLobbyOwner(SteamID steamIDLobby, SteamID steamIDNewOwner)

View File

@ -1,5 +1,24 @@
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:

View File

@ -26,7 +26,7 @@ namespace Steam
CryptProtectData(&Data[0], NULL, NULL, NULL, NULL, CRYPTPROTECT_LOCAL_MACHINE, &Data[1]);
subId = ::Utils::OneAtATime((char*)Data[1].pbData, 52); //(Game::Com_Milliseconds() + timeGetTime());
subId = /*::Utils::OneAtATime((char*)Data[1].pbData, 52); */(Game::Com_Milliseconds() + timeGetTime());
}
id.m_Bits = 0x110000100000000 | subId;

View File

@ -3,6 +3,71 @@
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)
{
OutputDebugStringA(::Utils::VA("Registering result: %d", result->GetICallback()));
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()
@ -10,16 +75,19 @@ namespace Steam
return true;
}
void SteamAPI_RegisterCallResult()
void SteamAPI_RegisterCallResult(Callbacks::Base* result, uint64_t call)
{
Callbacks::RegisterCallResult(call, result);
}
void SteamAPI_RegisterCallback()
void SteamAPI_RegisterCallback(Callbacks::Base* handler, int callback)
{
Callbacks::RegisterCallback(handler, callback);
}
void SteamAPI_RunCallbacks()
{
Callbacks::RunCallbacks();
}
void SteamAPI_Shutdown()

View File

@ -26,9 +26,51 @@ typedef union
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();
STEAM_EXPORT void SteamAPI_RegisterCallback();
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();

View File

@ -22,6 +22,15 @@ namespace Utils
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);

View File

@ -39,6 +39,7 @@
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;IW4_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@ -55,6 +56,7 @@
<ClInclude Include="Components\Colors.hpp" />
<ClInclude Include="Components\Command.hpp" />
<ClInclude Include="Components\Console.hpp" />
<ClInclude Include="Components\Dedicated.hpp" />
<ClInclude Include="Components\Dvar.hpp" />
<ClInclude Include="Components\FastFiles.hpp" />
<ClInclude Include="Components\FileSystem.hpp" />
@ -91,6 +93,7 @@
<ClCompile Include="Components\Colors.cpp" />
<ClCompile Include="Components\Command.cpp" />
<ClCompile Include="Components\Console.cpp" />
<ClCompile Include="Components\Dedicated.cpp" />
<ClCompile Include="Components\Dvar.cpp" />
<ClCompile Include="Components\FastFiles.cpp" />
<ClCompile Include="Components\FileSystem.cpp" />

View File

@ -128,6 +128,9 @@
<ClCompile Include="Components\Maps.cpp">
<Filter>Source\Components\Modules</Filter>
</ClCompile>
<ClCompile Include="Components\Dedicated.cpp">
<Filter>Source\Components\Modules</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Steam\Interfaces\SteamUser.hpp">
@ -232,5 +235,8 @@
<ClInclude Include="Components\Maps.hpp">
<Filter>Source\Components\Modules</Filter>
</ClInclude>
<ClInclude Include="Components\Dedicated.hpp">
<Filter>Source\Components\Modules</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -4,5 +4,6 @@
<LocalDebuggerCommand>iw4m.exe</LocalDebuggerCommand>
<LocalDebuggerWorkingDirectory>D:\Games\SteamLibrary\steamapps\common\Call of Duty Modern Warfare 2\</LocalDebuggerWorkingDirectory>
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
<LocalDebuggerCommandArguments>+set dedicated 0</LocalDebuggerCommandArguments>
</PropertyGroup>
</Project>