From 07d508ed4ebcd247250b8a983e5c85dffee4d5ef Mon Sep 17 00:00:00 2001
From: HappyDOGE <28511119+HappyDOGE@users.noreply.github.com>
Date: Mon, 27 Dec 2021 14:53:25 +0300
Subject: initial work on maxplayers
---
.../NorthstarDedicatedTest.vcxproj | 6 +-
.../NorthstarDedicatedTest.vcxproj.filters | 6 +
NorthstarDedicatedTest/dllmain.cpp | 6 +
NorthstarDedicatedTest/hooks.cpp | 34 +-
NorthstarDedicatedTest/hooks.h | 2 +-
NorthstarDedicatedTest/maxplayers.cpp | 559 +++++++++++++++++++++
NorthstarDedicatedTest/maxplayers.h | 4 +
7 files changed, 613 insertions(+), 4 deletions(-)
create mode 100644 NorthstarDedicatedTest/maxplayers.cpp
create mode 100644 NorthstarDedicatedTest/maxplayers.h
diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
index c684b69d..14fb634f 100644
--- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
+++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
@@ -43,13 +43,13 @@
DynamicLibrary
true
- v143
+ v142
Unicode
DynamicLibrary
false
- v143
+ v142
true
Unicode
@@ -576,6 +576,7 @@
+
@@ -611,6 +612,7 @@
+
diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters
index 7c856ea1..a3c17054 100644
--- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters
+++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters
@@ -1386,6 +1386,9 @@
Header Files\include\openssl\internal
+
+ Header Files\Shared
+
@@ -1493,6 +1496,9 @@
Source Files\Client
+
+ Source Files\Shared
+
diff --git a/NorthstarDedicatedTest/dllmain.cpp b/NorthstarDedicatedTest/dllmain.cpp
index 212b5711..c8f29550 100644
--- a/NorthstarDedicatedTest/dllmain.cpp
+++ b/NorthstarDedicatedTest/dllmain.cpp
@@ -25,6 +25,7 @@
#include "scriptmainmenupromos.h"
#include "miscclientfixes.h"
#include "memalloc.h"
+#include "maxplayers.h"
bool initialised = false;
@@ -116,6 +117,11 @@ void InitialiseNorthstar()
AddDllLoadCallback("filesystem_stdio.dll", InitialiseFilesystem);
AddDllLoadCallback("engine.dll", InitialiseKeyValues);
+ // maxplayers increase
+ AddDllLoadCallback("engine.dll", InitialiseMaxPlayersOverride_Engine);
+ AddDllLoadCallback("client.dll", InitialiseMaxPlayersOverride_Client, true);
+ AddDllLoadCallback("server.dll", InitialiseMaxPlayersOverride_Server, true);
+
// mod manager after everything else
AddDllLoadCallback("engine.dll", InitialiseModManager);
}
\ No newline at end of file
diff --git a/NorthstarDedicatedTest/hooks.cpp b/NorthstarDedicatedTest/hooks.cpp
index 3de8d483..e5ea0cb6 100644
--- a/NorthstarDedicatedTest/hooks.cpp
+++ b/NorthstarDedicatedTest/hooks.cpp
@@ -1,10 +1,12 @@
#include "pch.h"
#include "hooks.h"
#include "hookutils.h"
+#include "sigscanning.h"
#include
#include
#include
+#include
typedef HMODULE(*LoadLibraryExAType)(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
HMODULE LoadLibraryExAHook(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
@@ -12,9 +14,15 @@ HMODULE LoadLibraryExAHook(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
typedef HMODULE(*LoadLibraryExWType)(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
HMODULE LoadLibraryExWHook(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
+typedef BOOLEAN(*PDLL_INIT_ROUTINE)(PVOID DllHandle, ULONG Reason, PCONTEXT Context);
+typedef BOOLEAN(*LdrpCallInitRoutineType)(PDLL_INIT_ROUTINE EntryPoint, PVOID BaseAddress, ULONG Reason, PVOID Context);
+BOOLEAN LdrpCallInitRoutineHook(PDLL_INIT_ROUTINE EntryPoint, PVOID BaseAddress, ULONG Reason, PVOID Context);
+
LoadLibraryExAType LoadLibraryExAOriginal;
LoadLibraryExWType LoadLibraryExWOriginal;
+LdrpCallInitRoutineType LdrpCallInitRoutineHookOriginal;
+
void InstallInitialHooks()
{
if (MH_Initialize() != MH_OK)
@@ -23,6 +31,9 @@ void InstallInitialHooks()
HookEnabler hook;
ENABLER_CREATEHOOK(hook, &LoadLibraryExA, &LoadLibraryExAHook, reinterpret_cast(&LoadLibraryExAOriginal));
ENABLER_CREATEHOOK(hook, &LoadLibraryExW, &LoadLibraryExWHook, reinterpret_cast(&LoadLibraryExWOriginal));
+
+ void* LdrpCallInitRoutine = FindSignature("ntdll.dll", "\x48\x89\x5C\x24\x00\x44\x89\x44\x24\x00\x48\x89\x54\x24", "xxxx?xxxx?xxxx");
+ ENABLER_CREATEHOOK(hook, LdrpCallInitRoutine, &LdrpCallInitRoutineHook, reinterpret_cast(&LdrpCallInitRoutineHookOriginal));
}
// dll load callback stuff
@@ -32,16 +43,18 @@ struct DllLoadCallback
std::string dll;
DllLoadCallbackFuncType callback;
bool called;
+ bool preinit;
};
std::vector dllLoadCallbacks;
-void AddDllLoadCallback(std::string dll, DllLoadCallbackFuncType callback)
+void AddDllLoadCallback(std::string dll, DllLoadCallbackFuncType callback, bool preinit)
{
DllLoadCallback* callbackStruct = new DllLoadCallback;
callbackStruct->dll = dll;
callbackStruct->callback = callback;
callbackStruct->called = false;
+ callbackStruct->preinit = preinit;
dllLoadCallbacks.push_back(callbackStruct);
}
@@ -84,4 +97,23 @@ HMODULE LoadLibraryExWHook(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
}
return moduleAddress;
+}
+
+BOOLEAN LdrpCallInitRoutineHook(PDLL_INIT_ROUTINE EntryPoint, PVOID BaseAddress, ULONG Reason, PVOID Context)
+{
+ char fullModulePath[MAX_PATH] = { 0 };
+ GetModuleFileNameA((HMODULE)BaseAddress, fullModulePath, sizeof(fullModulePath));
+
+ std::string name = std::filesystem::path(fullModulePath).filename().string();
+
+ for (auto& callbackStruct : dllLoadCallbacks)
+ {
+ if (!callbackStruct->called && callbackStruct->preinit && name == callbackStruct->dll)
+ {
+ callbackStruct->callback((HMODULE)BaseAddress);
+ callbackStruct->called = true;
+ }
+ }
+
+ return LdrpCallInitRoutineHookOriginal(EntryPoint, BaseAddress, Reason, Context);
}
\ No newline at end of file
diff --git a/NorthstarDedicatedTest/hooks.h b/NorthstarDedicatedTest/hooks.h
index 972b38a6..012b12ec 100644
--- a/NorthstarDedicatedTest/hooks.h
+++ b/NorthstarDedicatedTest/hooks.h
@@ -4,4 +4,4 @@
void InstallInitialHooks();
typedef void(*DllLoadCallbackFuncType)(HMODULE moduleAddress);
-void AddDllLoadCallback(std::string dll, DllLoadCallbackFuncType callback);
\ No newline at end of file
+void AddDllLoadCallback(std::string dll, DllLoadCallbackFuncType callback, bool preinit = false);
\ No newline at end of file
diff --git a/NorthstarDedicatedTest/maxplayers.cpp b/NorthstarDedicatedTest/maxplayers.cpp
new file mode 100644
index 00000000..bf550693
--- /dev/null
+++ b/NorthstarDedicatedTest/maxplayers.cpp
@@ -0,0 +1,559 @@
+#include "pch.h"
+#include "maxplayers.h"
+
+// never set this to anything below 32
+#define NEW_MAX_PLAYERS 64
+
+#define PAD_NUMBER(number, boundary) \
+ ( ((number) + ((boundary)-1)) / (boundary) ) * (boundary)
+
+// this is horrible
+constexpr int PlayerResource_Name_Start = 0; // Start of modded allocated space.
+constexpr int PlayerResource_Name_Size = ((NEW_MAX_PLAYERS + 1) * 8); // const char* m_szName[MAX_PLAYERS + 1];
+
+constexpr int PlayerResource_Ping_Start = PlayerResource_Name_Start + PlayerResource_Name_Size;
+constexpr int PlayerResource_Ping_Size = ((NEW_MAX_PLAYERS + 1) * 4); // int m_iPing[MAX_PLAYERS + 1];
+
+constexpr int PlayerResource_Team_Start = PlayerResource_Ping_Start + PlayerResource_Ping_Size;
+constexpr int PlayerResource_Team_Size = ((NEW_MAX_PLAYERS + 1) * 4); // int m_iTeam[MAX_PLAYERS + 1];
+
+constexpr int PlayerResource_PRHealth_Start = PlayerResource_Team_Start + PlayerResource_Team_Size;
+constexpr int PlayerResource_PRHealth_Size = ((NEW_MAX_PLAYERS + 1) * 4); // int m_iPRHealth[MAX_PLAYERS + 1];
+
+constexpr int PlayerResource_Connected_Start = PlayerResource_PRHealth_Start + PlayerResource_PRHealth_Size;
+constexpr int PlayerResource_Connected_Size = ((NEW_MAX_PLAYERS + 1) * 4); // int (used as a bool) m_bConnected[MAX_PLAYERS + 1];
+
+constexpr int PlayerResource_Alive_Start = PlayerResource_Connected_Start + PlayerResource_Connected_Size;
+constexpr int PlayerResource_Alive_Size = ((NEW_MAX_PLAYERS + 1) * 4); // int (used as a bool) m_bAlive[MAX_PLAYERS + 1];
+
+constexpr int PlayerResource_BoolStats_Start = PlayerResource_Alive_Start + PlayerResource_Alive_Size;
+constexpr int PlayerResource_BoolStats_Size = ((NEW_MAX_PLAYERS + 1) * 4); // int (used as a bool idk) m_boolStats[MAX_PLAYERS + 1];
+
+constexpr int PlayerResource_KillStats_Start = PlayerResource_BoolStats_Start + PlayerResource_BoolStats_Size;
+constexpr int PlayerResource_KillStats_Length = PAD_NUMBER((NEW_MAX_PLAYERS + 1) * 6, 4);
+constexpr int PlayerResource_KillStats_Size = (PlayerResource_KillStats_Length * 6); // int m_killStats[MAX_PLAYERS + 1][6];
+
+constexpr int PlayerResource_ScoreStats_Start = PlayerResource_KillStats_Start + PlayerResource_KillStats_Size;
+constexpr int PlayerResource_ScoreStats_Length = PAD_NUMBER((NEW_MAX_PLAYERS + 1) * 5, 4);
+constexpr int PlayerResource_ScoreStats_Size = (PlayerResource_ScoreStats_Length * 4); // int m_scoreStats[MAX_PLAYERS + 1][5];
+
+// must be the usage of the last field to account for any possible paddings
+constexpr int PlayerResource_TotalSize = PlayerResource_ScoreStats_Start + PlayerResource_ScoreStats_Size;
+
+template
+void ChangeOffset(void* addr, unsigned int offset)
+{
+ TempReadWrite rw(addr);
+ *((T*)addr) = offset;
+}
+
+/*
+typedef bool(*MatchRecvPropsToSendProps_R_Type)(__int64 lookup, __int64 tableNameBroken, __int64 sendTable, __int64 recvTable);
+MatchRecvPropsToSendProps_R_Type MatchRecvPropsToSendProps_R_Original;
+
+bool MatchRecvPropsToSendProps_R_Hook(__int64 lookup, __int64 tableNameBroken, __int64 sendTable, __int64 recvTable)
+{
+ const char* tableName = *(const char**)(sendTable + 0x118);
+
+ spdlog::info("MatchRecvPropsToSendProps_R table name {}", tableName);
+
+ bool orig = MatchRecvPropsToSendProps_R_Original(lookup, tableNameBroken, sendTable, recvTable);
+ return orig;
+}
+
+typedef bool(*DataTable_SetupReceiveTableFromSendTable_Type)(__int64 sendTable, bool needsDecoder);
+DataTable_SetupReceiveTableFromSendTable_Type DataTable_SetupReceiveTableFromSendTable_Original;
+
+bool DataTable_SetupReceiveTableFromSendTable_Hook(__int64 sendTable, bool needsDecoder)
+{
+ const char* tableName = *(const char**)(sendTable + 0x118);
+
+ spdlog::info("DataTable_SetupReceiveTableFromSendTable table name {}", tableName);
+ if (!strcmp(tableName, "m_bConnected")) {
+ char f[64];
+ sprintf_s(f, "%p", sendTable);
+ MessageBoxA(0, f, "DataTable_SetupReceiveTableFromSendTable", 0);
+ }
+
+ return DataTable_SetupReceiveTableFromSendTable_Original(sendTable, needsDecoder);
+}
+*/
+
+void InitialiseMaxPlayersOverride_Engine(HMODULE baseAddress)
+{
+ // patch GetPlayerLimits to ignore the boundary limit
+ ChangeOffset((char*)baseAddress + 0x116458, 0xEB); // jle => jmp
+
+ // patch ED_Alloc to change nFirstIndex
+ ChangeOffset((char*)baseAddress + 0x18F46C + 1, NEW_MAX_PLAYERS + 8 + 1); // original: 41 (sv.GetMaxClients() + 1)
+
+ // patch CGameServer::SpawnServer to change GetMaxClients inline
+ ChangeOffset((char*)baseAddress + 0x119543 + 2, NEW_MAX_PLAYERS + 8 + 1); // original: 41 (sv.GetMaxClients() + 1)
+
+ // patch CGameServer::SpawnServer to change for loop
+ ChangeOffset((char*)baseAddress + 0x11957F + 2, NEW_MAX_PLAYERS); // original: 32
+
+ // patch CGameServer::SpawnServer to change for loop (there are two)
+ ChangeOffset((char*)baseAddress + 0x119586 + 2, NEW_MAX_PLAYERS + 1); // original: 33 (32 + 1)
+
+ // patch max players somewhere in CClientState
+ ChangeOffset((char*)baseAddress + 0x1A162C + 2, NEW_MAX_PLAYERS - 1); // original: 31 (32 - 1)
+
+ // patch max players in userinfo stringtable creation
+ {
+ int maxPlayersPowerOf2 = 1;
+ while (maxPlayersPowerOf2 < NEW_MAX_PLAYERS)
+ maxPlayersPowerOf2 <<= 1;
+ ChangeOffset((char*)baseAddress + 0x114B79 + 3, maxPlayersPowerOf2); // original: 32
+ }
+
+ // patch max players in userinfo stringtable creation loop
+ ChangeOffset((char*)baseAddress + 0x114C48 + 2, NEW_MAX_PLAYERS); // original: 32
+
+ // do not load prebaked SendTable message list
+ ChangeOffset((char*)baseAddress + 0x75859, 0xEB); // jnz -> jmp
+
+ // HookEnabler hook;
+ // ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x209000, &MatchRecvPropsToSendProps_R_Hook, reinterpret_cast(&MatchRecvPropsToSendProps_R_Original));
+ // ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x1FACD0, &DataTable_SetupReceiveTableFromSendTable_Hook, reinterpret_cast(&DataTable_SetupReceiveTableFromSendTable_Original));
+}
+
+typedef void(*RunUserCmds_Type)(bool a1, float a2);
+RunUserCmds_Type RunUserCmds_Original;
+
+HMODULE serverBase = 0;
+auto RandomIntZeroMax = (__int64(__fastcall*)())0;
+
+// lazy rebuild
+void RunUserCmds_Hook(bool a1, float a2)
+{
+ unsigned char v3; // bl
+ int v5; // er14
+ int i; // edi
+ __int64 v7; // rax
+ DWORD* v8; // rbx
+ int v9; // edi
+ __int64* v10; // rsi
+ __int64 v11; // rax
+ int v12; // er12
+ __int64 v13; // rdi
+ int v14; // ebx
+ int v15; // eax
+ __int64 v16; // r8
+ int v17; // edx
+ char v18; // r15
+ char v19; // bp
+ int v20; // esi
+ __int64* v21; // rdi
+ __int64 v22; // rcx
+ bool v23; // al
+ __int64 v24; // rax
+ __int64 v25[NEW_MAX_PLAYERS]; // [rsp+20h] [rbp-138h] BYREF
+
+ uintptr_t base = (__int64)serverBase;
+ auto g_pGlobals = *(__int64*)(base + 0xBFBE08);
+ __int64 globals = g_pGlobals;
+
+ auto g_pEngineServer = *(__int64*)(base + 0xBFBD98);
+
+ auto qword_1814D9648 = *(__int64*)(base + 0x14D9648);
+ auto qword_1814DA408 = *(__int64*)(base + 0x14DA408);
+ auto qword_1812107E8 = *(__int64*)(base + 0x12107E8);
+ auto qword_1812105A8 = *(__int64*)(base + 0x12105A8);
+
+ auto UTIL_PlayerByIndex = (__int64(__fastcall*)(int index))(base + 0x26AA10);
+ auto sub_180485590 = (void(__fastcall*)(__int64))(base + 0x485590);
+ auto sub_18058CD80 = (void(__fastcall*)(__int64))(base + 0x58CD80);
+ auto sub_1805A6D90 = (void(__fastcall*)(__int64))(base + 0x5A6D90);
+ auto sub_1805A6E50 = (bool(__fastcall*)(__int64, int, char))(base + 0x5A6E50);
+ auto sub_1805A6C20 = (void(__fastcall*)(__int64))(base + 0x5A6C20);
+
+ v3 = *(unsigned char*)(g_pGlobals + 73);
+ if (*(DWORD*)(qword_1814D9648 + 92)
+ && ((*(unsigned __int8(__fastcall**)(__int64))(*(__int64*)g_pEngineServer + 32i64))(g_pEngineServer)
+ || !*(DWORD*)(qword_1814DA408 + 92))
+ && v3)
+ {
+ globals = g_pGlobals;
+ v5 = 1;
+ for (i = 1; i <= *(DWORD*)(g_pGlobals + 52); ++i)
+ {
+ v7 = UTIL_PlayerByIndex(i);
+ v8 = (DWORD*)v7;
+ if (v7)
+ {
+ *(__int64*)(base + 0x1210420) = v7;
+ *(float*)(g_pGlobals + 16) = a2;
+ if (!a1)
+ sub_18058CD80(v7);
+ sub_1805A6D90((__int64)v8);
+ }
+ globals = g_pGlobals;
+ }
+ memset(v25, 0, sizeof(v25));
+ v9 = 0;
+ if (*(int*)(globals + 52) > 0)
+ {
+ v10 = v25;
+ do
+ {
+ v11 = UTIL_PlayerByIndex(++v9);
+ globals = g_pGlobals;
+ *v10++ = v11;
+ } while (v9 < *(DWORD*)(globals + 52));
+ }
+ v12 = *(DWORD*)(qword_1812107E8 + 92);
+ if (*(DWORD*)(qword_1812105A8 + 92))
+ {
+ v13 = *(DWORD*)(globals + 52) - 1;
+ if (v13 >= 1)
+ {
+ v14 = *(DWORD*)(globals + 52);
+ do
+ {
+ v15 = RandomIntZeroMax();
+ v16 = v25[v13--];
+ v17 = v15 % v14--;
+ v25[v13 + 1] = v25[v17];
+ v25[v17] = v16;
+ } while (v13 >= 1);
+ globals = g_pGlobals;
+ }
+ }
+ v18 = 1;
+ do
+ {
+ v19 = 0;
+ v20 = 0;
+ if (*(int*)(globals + 52) > 0)
+ {
+ v21 = v25;
+ do
+ {
+ v22 = *v21;
+ if (*v21)
+ {
+ *(__int64*)(base + 0x1210420) = *v21;
+ *(float*)(globals + 16) = a2;
+ v23 = sub_1805A6E50(v22, v12, v18);
+ globals = g_pGlobals;
+ if (v23)
+ v19 = 1;
+ else
+ *v21 = 0i64;
+ }
+ ++v20;
+ ++v21;
+ } while (v20 < *(DWORD*)(globals + 52));
+ }
+ v18 = 0;
+ } while (v19);
+ if (*(int*)(globals + 52) >= 1)
+ {
+ do
+ {
+ v24 = UTIL_PlayerByIndex(v5);
+ if (v24)
+ {
+ *(__int64*)(base + 0x1210420) = v24;
+ *(float*)(g_pGlobals + 16) = a2;
+ sub_1805A6C20(v24);
+ }
+ ++v5;
+ } while (v5 <= *(DWORD*)(g_pGlobals + 52));
+ }
+ sub_180485590(*(__int64*)(base + 0xB7B2D8));
+ }
+}
+
+void InitialiseMaxPlayersOverride_Server(HMODULE baseAddress)
+{
+ // get required data
+ serverBase = GetModuleHandleA("server.dll");
+ RandomIntZeroMax = (decltype(RandomIntZeroMax))(GetProcAddress(GetModuleHandleA("vstdlib.dll"), "RandomIntZeroMax"));
+
+ // patch max players amount
+ ChangeOffset((char*)baseAddress + 0x9A44D + 3, NEW_MAX_PLAYERS); // 0x20 (32) => 0x80 (128)
+
+ // patch SpawnGlobalNonRewinding to change forced edict index
+ ChangeOffset((char*)baseAddress + 0x2BC403 + 2, NEW_MAX_PLAYERS + 1); // original: 33 (32 + 1)
+
+ constexpr int CPlayerResource_OriginalSize = 4776;
+ constexpr int CPlayerResource_AddedSize = PlayerResource_TotalSize;
+ constexpr int CPlayerResource_ModifiedSize = CPlayerResource_OriginalSize + CPlayerResource_AddedSize;
+
+ // CPlayerResource class allocation function - allocate a bigger amount to fit all new max player data
+ ChangeOffset((char*)baseAddress + 0x5C560A + 1, CPlayerResource_ModifiedSize);
+
+ // DT_PlayerResource::m_iPing SendProp
+ ChangeOffset((char*)baseAddress + 0x5C5059 + 2, CPlayerResource_OriginalSize + PlayerResource_Ping_Start);
+ ChangeOffset((char*)baseAddress + 0x5C50A8 + 2, CPlayerResource_OriginalSize + PlayerResource_Ping_Start);
+ ChangeOffset((char*)baseAddress + 0x5C50E2 + 4, NEW_MAX_PLAYERS + 1);
+
+ // DT_PlayerResource::m_iPing DataMap
+ ChangeOffset((char*)baseAddress + 0xB94598, CPlayerResource_OriginalSize + PlayerResource_Ping_Start);
+ ChangeOffset((char*)baseAddress + 0xB9459C, NEW_MAX_PLAYERS + 1);
+ ChangeOffset((char*)baseAddress + 0xB945C0, PlayerResource_Ping_Size);
+
+ // DT_PlayerResource::m_iTeam SendProp
+ ChangeOffset((char*)baseAddress + 0x5C5110 + 2, CPlayerResource_OriginalSize + PlayerResource_Team_Start);
+ ChangeOffset((char*)baseAddress + 0x5C519C + 2, CPlayerResource_OriginalSize + PlayerResource_Team_Start);
+ ChangeOffset((char*)baseAddress + 0x5C517E + 4, NEW_MAX_PLAYERS + 1);
+
+ // DT_PlayerResource::m_iTeam DataMap
+ ChangeOffset((char*)baseAddress + 0xB94600, CPlayerResource_OriginalSize + PlayerResource_Team_Start);
+ ChangeOffset((char*)baseAddress + 0xB94604, NEW_MAX_PLAYERS + 1);
+ ChangeOffset((char*)baseAddress + 0xB94628, PlayerResource_Team_Size);
+
+ // DT_PlayerResource::m_iPRHealth SendProp
+ ChangeOffset((char*)baseAddress + 0x5C51C0 + 2, CPlayerResource_OriginalSize + PlayerResource_PRHealth_Start);
+ ChangeOffset((char*)baseAddress + 0x5C5204 + 2, CPlayerResource_OriginalSize + PlayerResource_PRHealth_Start);
+ ChangeOffset((char*)baseAddress + 0x5C523E + 4, NEW_MAX_PLAYERS + 1);
+
+ // DT_PlayerResource::m_iPRHealth DataMap
+ ChangeOffset((char*)baseAddress + 0xB94668, CPlayerResource_OriginalSize + PlayerResource_PRHealth_Start);
+ ChangeOffset((char*)baseAddress + 0xB9466C, NEW_MAX_PLAYERS + 1);
+ ChangeOffset((char*)baseAddress + 0xB94690, PlayerResource_PRHealth_Size);
+
+ // DT_PlayerResource::m_bConnected SendProp
+ ChangeOffset((char*)baseAddress + 0x5C526C + 2, CPlayerResource_OriginalSize + PlayerResource_Connected_Start);
+ ChangeOffset((char*)baseAddress + 0x5C52B4 + 2, CPlayerResource_OriginalSize + PlayerResource_Connected_Start);
+ ChangeOffset((char*)baseAddress + 0x5C52EE + 4, NEW_MAX_PLAYERS + 1);
+
+ // DT_PlayerResource::m_bConnected DataMap
+ ChangeOffset((char*)baseAddress + 0xB946D0, CPlayerResource_OriginalSize + PlayerResource_Connected_Start);
+ ChangeOffset((char*)baseAddress + 0xB946D4, NEW_MAX_PLAYERS + 1);
+ ChangeOffset((char*)baseAddress + 0xB946F8, PlayerResource_Connected_Size);
+
+ // DT_PlayerResource::m_bAlive SendProp
+ ChangeOffset((char*)baseAddress + 0x5C5321 + 2, CPlayerResource_OriginalSize + PlayerResource_Alive_Start);
+ ChangeOffset((char*)baseAddress + 0x5C5364 + 2, CPlayerResource_OriginalSize + PlayerResource_Alive_Start);
+ ChangeOffset((char*)baseAddress + 0x5C539E + 4, NEW_MAX_PLAYERS + 1);
+
+ // DT_PlayerResource::m_bAlive DataMap
+ ChangeOffset((char*)baseAddress + 0xB94738, CPlayerResource_OriginalSize + PlayerResource_Alive_Start);
+ ChangeOffset((char*)baseAddress + 0xB9473C, NEW_MAX_PLAYERS + 1);
+ ChangeOffset((char*)baseAddress + 0xB94760, PlayerResource_Alive_Size);
+
+ // DT_PlayerResource::m_boolStats SendProp
+ ChangeOffset((char*)baseAddress + 0x5C53CC + 2, CPlayerResource_OriginalSize + PlayerResource_BoolStats_Start);
+ ChangeOffset((char*)baseAddress + 0x5C5414 + 2, CPlayerResource_OriginalSize + PlayerResource_BoolStats_Start);
+ ChangeOffset((char*)baseAddress + 0x5C544E + 4, NEW_MAX_PLAYERS + 1);
+
+ // DT_PlayerResource::m_boolStats DataMap
+ ChangeOffset((char*)baseAddress + 0xB947A0, CPlayerResource_OriginalSize + PlayerResource_BoolStats_Start);
+ ChangeOffset((char*)baseAddress + 0xB947A4, NEW_MAX_PLAYERS + 1);
+ ChangeOffset((char*)baseAddress + 0xB947C8, PlayerResource_BoolStats_Size);
+
+ // DT_PlayerResource::m_killStats SendProp
+ ChangeOffset((char*)baseAddress + 0x5C547C + 2, CPlayerResource_OriginalSize + PlayerResource_KillStats_Start);
+ ChangeOffset((char*)baseAddress + 0x5C54E2 + 2, CPlayerResource_OriginalSize + PlayerResource_KillStats_Start);
+ ChangeOffset((char*)baseAddress + 0x5C54FE + 4, PlayerResource_KillStats_Length);
+
+ // DT_PlayerResource::m_killStats DataMap
+ ChangeOffset((char*)baseAddress + 0xB94808, CPlayerResource_OriginalSize + PlayerResource_KillStats_Start);
+ ChangeOffset((char*)baseAddress + 0xB9480C, PlayerResource_KillStats_Length);
+ ChangeOffset((char*)baseAddress + 0xB94830, PlayerResource_KillStats_Size);
+
+ // DT_PlayerResource::m_scoreStats SendProp
+ ChangeOffset((char*)baseAddress + 0x5C5528 + 2, CPlayerResource_OriginalSize + PlayerResource_ScoreStats_Start);
+ ChangeOffset((char*)baseAddress + 0x5C5576 + 2, CPlayerResource_OriginalSize + PlayerResource_ScoreStats_Start);
+ ChangeOffset((char*)baseAddress + 0x5C5584 + 4, PlayerResource_ScoreStats_Length);
+
+ // DT_PlayerResource::m_scoreStats DataMap
+ ChangeOffset((char*)baseAddress + 0xB94870, CPlayerResource_OriginalSize + PlayerResource_ScoreStats_Start);
+ ChangeOffset((char*)baseAddress + 0xB94874, PlayerResource_ScoreStats_Length);
+ ChangeOffset((char*)baseAddress + 0xB94898, PlayerResource_ScoreStats_Size);
+
+ // CPlayerResource::UpdatePlayerData - m_bConnected
+ ChangeOffset((char*)baseAddress + 0x5C66EE + 4, CPlayerResource_OriginalSize + PlayerResource_Connected_Start);
+ ChangeOffset((char*)baseAddress + 0x5C672E + 4, CPlayerResource_OriginalSize + PlayerResource_Connected_Start);
+
+ // CPlayerResource::UpdatePlayerData - m_iPing
+ ChangeOffset((char*)baseAddress + 0x5C6394 + 4, CPlayerResource_OriginalSize + PlayerResource_Ping_Start);
+ ChangeOffset((char*)baseAddress + 0x5C63DB + 4, CPlayerResource_OriginalSize + PlayerResource_Ping_Start);
+
+ // CPlayerResource::UpdatePlayerData - m_iTeam
+ ChangeOffset((char*)baseAddress + 0x5C63FD + 4, CPlayerResource_OriginalSize + PlayerResource_Team_Start);
+ ChangeOffset((char*)baseAddress + 0x5C6442 + 4, CPlayerResource_OriginalSize + PlayerResource_Team_Start);
+
+ // CPlayerResource::UpdatePlayerData - m_iPRHealth
+ ChangeOffset((char*)baseAddress + 0x5C645B + 4, CPlayerResource_OriginalSize + PlayerResource_PRHealth_Start);
+ ChangeOffset((char*)baseAddress + 0x5C64A0 + 4, CPlayerResource_OriginalSize + PlayerResource_PRHealth_Start);
+
+ // CPlayerResource::UpdatePlayerData - m_bConnected
+ ChangeOffset((char*)baseAddress + 0x5C64AA + 4, CPlayerResource_OriginalSize + PlayerResource_Connected_Start);
+ ChangeOffset((char*)baseAddress + 0x5C64F0 + 4, CPlayerResource_OriginalSize + PlayerResource_Connected_Start);
+
+ // CPlayerResource::UpdatePlayerData - m_bAlive
+ ChangeOffset((char*)baseAddress + 0x5C650A + 4, CPlayerResource_OriginalSize + PlayerResource_Alive_Start);
+ ChangeOffset((char*)baseAddress + 0x5C654F + 4, CPlayerResource_OriginalSize + PlayerResource_Alive_Start);
+
+ // CPlayerResource::UpdatePlayerData - m_boolStats
+ ChangeOffset((char*)baseAddress + 0x5C6557 + 4, CPlayerResource_OriginalSize + PlayerResource_BoolStats_Start);
+ ChangeOffset((char*)baseAddress + 0x5C65A5 + 4, CPlayerResource_OriginalSize + PlayerResource_BoolStats_Start);
+
+ // CPlayerResource::UpdatePlayerData - m_scoreStats
+ ChangeOffset((char*)baseAddress + 0x5C65C2 + 3, CPlayerResource_OriginalSize + PlayerResource_ScoreStats_Start);
+ ChangeOffset((char*)baseAddress + 0x5C65E3 + 4, CPlayerResource_OriginalSize + PlayerResource_ScoreStats_Start);
+
+ // CPlayerResource::UpdatePlayerData - m_killStats
+ ChangeOffset((char*)baseAddress + 0x5C6654 + 3, CPlayerResource_OriginalSize + PlayerResource_KillStats_Start);
+ ChangeOffset((char*)baseAddress + 0x5C665B + 3, CPlayerResource_OriginalSize + PlayerResource_KillStats_Start);
+
+ // GameLoop::RunUserCmds - rebuild
+ HookEnabler hook;
+ ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x483D10, &RunUserCmds_Hook, reinterpret_cast(&RunUserCmds_Original));
+}
+
+void InitialiseMaxPlayersOverride_Client(HMODULE baseAddress)
+{
+ constexpr int C_PlayerResource_OriginalSize = 5768;
+ constexpr int C_PlayerResource_AddedSize = PlayerResource_TotalSize;
+ constexpr int C_PlayerResource_ModifiedSize = C_PlayerResource_OriginalSize + C_PlayerResource_AddedSize;
+
+ // C_PlayerResource class allocation function - allocate a bigger amount to fit all new max player data
+ ChangeOffset((char*)baseAddress + 0x164C41 + 1, C_PlayerResource_ModifiedSize);
+
+ // C_PlayerResource::C_PlayerResource - change loop end value
+ ChangeOffset((char*)baseAddress + 0x1640C4 + 2, NEW_MAX_PLAYERS - 32);
+
+ // C_PlayerResource::C_PlayerResource - change m_szName address
+ ChangeOffset((char*)baseAddress + 0x1640D0 + 3, C_PlayerResource_OriginalSize + PlayerResource_Name_Start); // appended to the end of the class
+
+ // C_PlayerResource::C_PlayerResource - change m_szName address
+ ChangeOffset((char*)baseAddress + 0x1640D0 + 3, C_PlayerResource_OriginalSize + PlayerResource_Name_Start); // appended to the end of the class
+
+ // C_PlayerResource::C_PlayerResource - increase memset length to clean newly allocated data
+ ChangeOffset((char*)baseAddress + 0x1640D0 + 3, 2244 + C_PlayerResource_AddedSize);
+
+ // C_PlayerResource::UpdatePlayerName - change m_szName address
+ ChangeOffset((char*)baseAddress + 0x16431F + 3, C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
+
+ // C_PlayerResource::GetPlayerName - change m_szName address 1
+ ChangeOffset((char*)baseAddress + 0x1645B1 + 3, C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
+
+ // C_PlayerResource::GetPlayerName - change m_szName address 2
+ ChangeOffset((char*)baseAddress + 0x1645C0 + 3, C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
+
+ // C_PlayerResource::GetPlayerName - change m_szName address 3
+ ChangeOffset((char*)baseAddress + 0x1645DD + 3, C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
+
+ // C_PlayerResource::GetPlayerName internal func - change m_szName address 1
+ ChangeOffset((char*)baseAddress + 0x164B71 + 4, C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
+
+ // C_PlayerResource::GetPlayerName internal func - change m_szName address 2
+ ChangeOffset((char*)baseAddress + 0x164B9B + 4, C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
+
+ // C_PlayerResource::GetPlayerName2 (?) - change m_szName address 1
+ ChangeOffset((char*)baseAddress + 0x164641 + 3, C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
+
+ // C_PlayerResource::GetPlayerName2 (?) - change m_szName address 2
+ ChangeOffset((char*)baseAddress + 0x164650 + 3, C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
+
+ // C_PlayerResource::GetPlayerName2 (?) - change m_szName address 3
+ ChangeOffset((char*)baseAddress + 0x16466D + 3, C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
+
+ // C_PlayerResource::GetPlayerName internal func - change m_szName2 (?) address 1
+ ChangeOffset((char*)baseAddress + 0x164BA3 + 4, C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
+
+ // C_PlayerResource::GetPlayerName internal func - change m_szName2 (?) address 2
+ ChangeOffset((char*)baseAddress + 0x164BCE + 4, C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
+
+ // C_PlayerResource::GetPlayerName internal func - change m_szName2 (?) address 3
+ ChangeOffset((char*)baseAddress + 0x164BE7 + 4, C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
+
+ // C_PlayerResource::m_szName
+ ChangeOffset((char*)baseAddress + 0xc350f8, C_PlayerResource_OriginalSize + PlayerResource_Name_Start);
+ ChangeOffset((char*)baseAddress + 0xc350f8 + 4, NEW_MAX_PLAYERS + 1);
+
+ // DT_PlayerResource size
+ ChangeOffset((char*)baseAddress + 0x163415 + 6, C_PlayerResource_ModifiedSize);
+
+ // DT_PlayerResource::m_iPing RecvProp
+ ChangeOffset((char*)baseAddress + 0x163492 + 2, C_PlayerResource_OriginalSize + PlayerResource_Ping_Start);
+ ChangeOffset((char*)baseAddress + 0x1634D6 + 2, C_PlayerResource_OriginalSize + PlayerResource_Ping_Start);
+ ChangeOffset((char*)baseAddress + 0x163515 + 5, NEW_MAX_PLAYERS + 1);
+
+ // C_PlayerResource::m_iPing
+ ChangeOffset((char*)baseAddress + 0xc35170, C_PlayerResource_OriginalSize + PlayerResource_Ping_Start);
+ ChangeOffset((char*)baseAddress + 0xc35170 + 4, NEW_MAX_PLAYERS + 1);
+
+ // DT_PlayerResource::m_iTeam RecvProp
+ ChangeOffset((char*)baseAddress + 0x163549 + 2, C_PlayerResource_OriginalSize + PlayerResource_Team_Start);
+ ChangeOffset((char*)baseAddress + 0x1635C8 + 2, C_PlayerResource_OriginalSize + PlayerResource_Team_Start);
+ ChangeOffset((char*)baseAddress + 0x1635AD + 5, NEW_MAX_PLAYERS + 1);
+
+ // C_PlayerResource::m_iTeam
+ ChangeOffset((char*)baseAddress + 0xc351e8, C_PlayerResource_OriginalSize + PlayerResource_Team_Start);
+ ChangeOffset((char*)baseAddress + 0xc351e8 + 4, NEW_MAX_PLAYERS + 1);
+
+ // DT_PlayerResource::m_iPRHealth RecvProp
+ ChangeOffset((char*)baseAddress + 0x1635F9 + 2, C_PlayerResource_OriginalSize + PlayerResource_PRHealth_Start);
+ ChangeOffset((char*)baseAddress + 0x163625 + 2, C_PlayerResource_OriginalSize + PlayerResource_PRHealth_Start);
+ ChangeOffset((char*)baseAddress + 0x163675 + 5, NEW_MAX_PLAYERS + 1);
+
+ // C_PlayerResource::m_iPRHealth
+ ChangeOffset((char*)baseAddress + 0xc35260, C_PlayerResource_OriginalSize + PlayerResource_PRHealth_Start);
+ ChangeOffset((char*)baseAddress + 0xc35260 + 4, NEW_MAX_PLAYERS + 1);
+
+ // DT_PlayerResource::m_bConnected RecvProp
+ ChangeOffset((char*)baseAddress + 0x1636A9 + 2, C_PlayerResource_OriginalSize + PlayerResource_Connected_Start);
+ ChangeOffset((char*)baseAddress + 0x1636D5 + 2, C_PlayerResource_OriginalSize + PlayerResource_Connected_Start);
+ ChangeOffset((char*)baseAddress + 0x163725 + 5, NEW_MAX_PLAYERS + 1);
+
+ // C_PlayerResource::m_bConnected
+ ChangeOffset((char*)baseAddress + 0xc352d8, C_PlayerResource_OriginalSize + PlayerResource_Connected_Start);
+ ChangeOffset((char*)baseAddress + 0xc352d8 + 4, NEW_MAX_PLAYERS + 1);
+
+ // DT_PlayerResource::m_bAlive RecvProp
+ ChangeOffset((char*)baseAddress + 0x163759 + 2, C_PlayerResource_OriginalSize + PlayerResource_Alive_Start);
+ ChangeOffset((char*)baseAddress + 0x163785 + 2, C_PlayerResource_OriginalSize + PlayerResource_Alive_Start);
+ ChangeOffset((char*)baseAddress + 0x1637D5 + 5, NEW_MAX_PLAYERS + 1);
+
+ // C_PlayerResource::m_bAlive
+ ChangeOffset((char*)baseAddress + 0xc35350, C_PlayerResource_OriginalSize + PlayerResource_Alive_Start);
+ ChangeOffset((char*)baseAddress + 0xc35350 + 4, NEW_MAX_PLAYERS + 1);
+
+ // DT_PlayerResource::m_boolStats RecvProp
+ ChangeOffset((char*)baseAddress + 0x163809 + 2, C_PlayerResource_OriginalSize + PlayerResource_BoolStats_Start);
+ ChangeOffset((char*)baseAddress + 0x163835 + 2, C_PlayerResource_OriginalSize + PlayerResource_BoolStats_Start);
+ ChangeOffset((char*)baseAddress + 0x163885 + 5, NEW_MAX_PLAYERS + 1);
+
+ // C_PlayerResource::m_boolStats
+ ChangeOffset((char*)baseAddress + 0xc353c8, C_PlayerResource_OriginalSize + PlayerResource_BoolStats_Start);
+ ChangeOffset((char*)baseAddress + 0xc353c8 + 4, NEW_MAX_PLAYERS + 1);
+
+ // DT_PlayerResource::m_killStats RecvProp
+ ChangeOffset((char*)baseAddress + 0x1638B3 + 2, C_PlayerResource_OriginalSize + PlayerResource_KillStats_Start);
+ ChangeOffset((char*)baseAddress + 0x1638E5 + 2, C_PlayerResource_OriginalSize + PlayerResource_KillStats_Start);
+ ChangeOffset((char*)baseAddress + 0x163935 + 5, PlayerResource_KillStats_Length);
+
+ // C_PlayerResource::m_killStats
+ ChangeOffset((char*)baseAddress + 0xc35440, C_PlayerResource_OriginalSize + PlayerResource_KillStats_Start);
+ ChangeOffset((char*)baseAddress + 0xc35440 + 4, PlayerResource_KillStats_Length);
+
+ // DT_PlayerResource::m_scoreStats RecvProp
+ ChangeOffset((char*)baseAddress + 0x163969 + 2, C_PlayerResource_OriginalSize + PlayerResource_ScoreStats_Start);
+ ChangeOffset((char*)baseAddress + 0x163995 + 2, C_PlayerResource_OriginalSize + PlayerResource_ScoreStats_Start);
+ ChangeOffset((char*)baseAddress + 0x1639E5 + 5, PlayerResource_ScoreStats_Length);
+
+ // C_PlayerResource::m_scoreStats
+ ChangeOffset((char*)baseAddress + 0xc354b8, C_PlayerResource_OriginalSize + PlayerResource_ScoreStats_Start);
+ ChangeOffset((char*)baseAddress + 0xc354b8 + 4, PlayerResource_ScoreStats_Length);
+
+ // C_PlayerResource::GetPlayerName - change m_bConnected address
+ ChangeOffset((char*)baseAddress + 0x164599 + 3, C_PlayerResource_OriginalSize + PlayerResource_Connected_Start);
+
+ // C_PlayerResource::GetPlayerName2 (?) - change m_bConnected address
+ ChangeOffset((char*)baseAddress + 0x164629 + 3, C_PlayerResource_OriginalSize + PlayerResource_Connected_Start);
+
+ // C_PlayerResource::GetPlayerName internal func - change m_bConnected address
+ ChangeOffset((char*)baseAddress + 0x164B13 + 3, C_PlayerResource_OriginalSize + PlayerResource_Connected_Start);
+
+ // Some other get name func (that seems to be unused) - change m_bConnected address
+ ChangeOffset((char*)baseAddress + 0x164860 + 3, C_PlayerResource_OriginalSize + PlayerResource_Connected_Start);
+
+ // Some other get name func 2 (that seems to be unused too) - change m_bConnected address
+ ChangeOffset((char*)baseAddress + 0x164834 + 3, C_PlayerResource_OriginalSize + PlayerResource_Connected_Start);
+}
\ No newline at end of file
diff --git a/NorthstarDedicatedTest/maxplayers.h b/NorthstarDedicatedTest/maxplayers.h
new file mode 100644
index 00000000..cd191fc8
--- /dev/null
+++ b/NorthstarDedicatedTest/maxplayers.h
@@ -0,0 +1,4 @@
+#pragma once
+void InitialiseMaxPlayersOverride_Engine(HMODULE baseAddress);
+void InitialiseMaxPlayersOverride_Server(HMODULE baseAddress);
+void InitialiseMaxPlayersOverride_Client(HMODULE baseAddress);
\ No newline at end of file
--
cgit v1.2.3
From 2dac0c0c284f2464b919c1f20c741dda8ff17163 Mon Sep 17 00:00:00 2001
From: HappyDOGE <28511119+HappyDOGE@users.noreply.github.com>
Date: Mon, 27 Dec 2021 14:56:08 +0300
Subject: add maxplayers to filters
---
NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters | 3 +++
1 file changed, 3 insertions(+)
diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters
index 5b287ad1..37be2f7e 100644
--- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters
+++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters
@@ -1389,6 +1389,9 @@
Header Files\Server
+
+ Header Files\Shared
+
--
cgit v1.2.3
From 22f39a161516fee4e1350ec4e8830c120d1d53c5 Mon Sep 17 00:00:00 2001
From: HappyDOGE <28511119+HappyDOGE@users.noreply.github.com>
Date: Mon, 27 Dec 2021 15:50:01 +0300
Subject: fix status command not working for server operator
---
.../NorthstarDedicatedTest.vcxproj.filters | 6 +++++
NorthstarDedicatedTest/logging.cpp | 30 +++++++++++++++++++++-
2 files changed, 35 insertions(+), 1 deletion(-)
diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters
index 37be2f7e..a3d5e82d 100644
--- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters
+++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj.filters
@@ -1499,6 +1499,12 @@
Source Files\Client
+
+ Source Files\Shared
+
+
+ Source Files\Server
+
diff --git a/NorthstarDedicatedTest/logging.cpp b/NorthstarDedicatedTest/logging.cpp
index 09ae6961..6525df27 100644
--- a/NorthstarDedicatedTest/logging.cpp
+++ b/NorthstarDedicatedTest/logging.cpp
@@ -242,7 +242,7 @@ void EngineSpewFuncHook(void* engineServer, SpewType_t type, const char* format,
}
}
- char formatted[2048];
+ char formatted[2048] = { 0 };
bool shouldFormat = true;
// because titanfall 2 is quite possibly the worst thing to yet exist, it sometimes gives invalid specifiers which will crash
@@ -304,11 +304,39 @@ void EngineSpewFuncHook(void* engineServer, SpewType_t type, const char* format,
spdlog::warn("Failed to format {} \"{}\"", typeStr, format);
}
+ auto endpos = strlen(formatted);
+ if (formatted[endpos - 1] == '\n')
+ formatted[endpos - 1] = '\0'; // cut off repeated newline
+
spdlog::info("[SERVER {}] {}", typeStr, formatted);
}
+
+typedef void(*Status_ConMsg_Type)(const char* text, ...);
+Status_ConMsg_Type Status_ConMsg_Original;
+
+void Status_ConMsg_Hook(const char* text, ...)
+{
+ char formatted[2048];
+ va_list list;
+
+ va_start(list, text);
+ vsprintf_s(formatted, text, list);
+ va_end(list);
+
+ auto endpos = strlen(formatted);
+ if (formatted[endpos - 1] == '\n')
+ formatted[endpos - 1] = '\0'; // cut off repeated newline
+
+ spdlog::info(formatted);
+}
+
void InitialiseEngineSpewFuncHooks(HMODULE baseAddress)
{
HookEnabler hook;
+
ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x11CA80, EngineSpewFuncHook, reinterpret_cast(&EngineSpewFunc));
+
+ // Hook print function that status concmd uses to actually print data
+ ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x15ABD0, Status_ConMsg_Hook, reinterpret_cast(&Status_ConMsg_Original));
}
\ No newline at end of file
--
cgit v1.2.3
From 785ad98f7077b9b1a1b1ada21219465c21dcbb09 Mon Sep 17 00:00:00 2001
From: HappyDOGE <28511119+HappyDOGE@users.noreply.github.com>
Date: Mon, 27 Dec 2021 17:59:24 +0300
Subject: 64 maxplayers
---
NorthstarDedicatedTest/maxplayers.cpp | 29 ++++++++++++++++++++++++++---
1 file changed, 26 insertions(+), 3 deletions(-)
diff --git a/NorthstarDedicatedTest/maxplayers.cpp b/NorthstarDedicatedTest/maxplayers.cpp
index bf550693..1c984c96 100644
--- a/NorthstarDedicatedTest/maxplayers.cpp
+++ b/NorthstarDedicatedTest/maxplayers.cpp
@@ -79,6 +79,24 @@ bool DataTable_SetupReceiveTableFromSendTable_Hook(__int64 sendTable, bool needs
}
*/
+typedef void* (*StringTables_CreateStringTable_Type)(__int64 thisptr, const char* name, int maxentries, int userdatafixedsize, int userdatanetworkbits, int flags);
+StringTables_CreateStringTable_Type StringTables_CreateStringTable_Original;
+
+void* StringTables_CreateStringTable_Hook(__int64 thisptr, const char* name, int maxentries, int userdatafixedsize, int userdatanetworkbits, int flags)
+{
+ // Change the amount of entries to account for a bigger player amount
+ if (!strcmp(name, "userinfo"))
+ {
+ int maxPlayersPowerOf2 = 1;
+ while (maxPlayersPowerOf2 < NEW_MAX_PLAYERS)
+ maxPlayersPowerOf2 <<= 1;
+
+ maxentries = maxPlayersPowerOf2;
+ }
+
+ return StringTables_CreateStringTable_Original(thisptr, name, maxentries, userdatafixedsize, userdatanetworkbits, flags);
+}
+
void InitialiseMaxPlayersOverride_Engine(HMODULE baseAddress)
{
// patch GetPlayerLimits to ignore the boundary limit
@@ -100,12 +118,14 @@ void InitialiseMaxPlayersOverride_Engine(HMODULE baseAddress)
ChangeOffset((char*)baseAddress + 0x1A162C + 2, NEW_MAX_PLAYERS - 1); // original: 31 (32 - 1)
// patch max players in userinfo stringtable creation
- {
+ /*{
int maxPlayersPowerOf2 = 1;
while (maxPlayersPowerOf2 < NEW_MAX_PLAYERS)
maxPlayersPowerOf2 <<= 1;
ChangeOffset((char*)baseAddress + 0x114B79 + 3, maxPlayersPowerOf2); // original: 32
- }
+ }*/
+ // this is not supposed to work at all but it does on 64 players (how)
+ // proper fix below
// patch max players in userinfo stringtable creation loop
ChangeOffset((char*)baseAddress + 0x114C48 + 2, NEW_MAX_PLAYERS); // original: 32
@@ -113,9 +133,12 @@ void InitialiseMaxPlayersOverride_Engine(HMODULE baseAddress)
// do not load prebaked SendTable message list
ChangeOffset((char*)baseAddress + 0x75859, 0xEB); // jnz -> jmp
- // HookEnabler hook;
+ HookEnabler hook;
+
// ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x209000, &MatchRecvPropsToSendProps_R_Hook, reinterpret_cast(&MatchRecvPropsToSendProps_R_Original));
// ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x1FACD0, &DataTable_SetupReceiveTableFromSendTable_Hook, reinterpret_cast(&DataTable_SetupReceiveTableFromSendTable_Original));
+
+ ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x22E220, &StringTables_CreateStringTable_Hook, reinterpret_cast(&StringTables_CreateStringTable_Original));
}
typedef void(*RunUserCmds_Type)(bool a1, float a2);
--
cgit v1.2.3
From bf41a73a0a9d3c5c26086559570a9d6502f137c3 Mon Sep 17 00:00:00 2001
From: HappyDOGE <28511119+HappyDOGE@users.noreply.github.com>
Date: Mon, 27 Dec 2021 18:01:58 +0300
Subject: change toolset back to v143
---
NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
index c324d60f..759ede07 100644
--- a/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
+++ b/NorthstarDedicatedTest/NorthstarDedicatedTest.vcxproj
@@ -43,13 +43,13 @@
DynamicLibrary
true
- v142
+ v143
Unicode
DynamicLibrary
false
- v142
+ v143
true
Unicode
--
cgit v1.2.3
From 1cb1d1e19804d1b7b52c8b2bd21f10dde4bf6bf8 Mon Sep 17 00:00:00 2001
From: HappyDOGE <28511119+HappyDOGE@users.noreply.github.com>
Date: Mon, 27 Dec 2021 19:56:08 +0300
Subject: remove hook preload as it's not crossplatform use a universal
solution instead
---
NorthstarDedicatedTest/dllmain.cpp | 4 ++--
NorthstarDedicatedTest/hooks.cpp | 32 +-------------------------------
NorthstarDedicatedTest/hooks.h | 2 +-
NorthstarDedicatedTest/maxplayers.cpp | 8 ++++++++
4 files changed, 12 insertions(+), 34 deletions(-)
diff --git a/NorthstarDedicatedTest/dllmain.cpp b/NorthstarDedicatedTest/dllmain.cpp
index 1eafef7f..6f57d265 100644
--- a/NorthstarDedicatedTest/dllmain.cpp
+++ b/NorthstarDedicatedTest/dllmain.cpp
@@ -121,8 +121,8 @@ void InitialiseNorthstar()
// maxplayers increase
AddDllLoadCallback("engine.dll", InitialiseMaxPlayersOverride_Engine);
- AddDllLoadCallback("client.dll", InitialiseMaxPlayersOverride_Client, true);
- AddDllLoadCallback("server.dll", InitialiseMaxPlayersOverride_Server, true);
+ AddDllLoadCallback("client.dll", InitialiseMaxPlayersOverride_Client);
+ AddDllLoadCallback("server.dll", InitialiseMaxPlayersOverride_Server);
// mod manager after everything else
AddDllLoadCallback("engine.dll", InitialiseModManager);
diff --git a/NorthstarDedicatedTest/hooks.cpp b/NorthstarDedicatedTest/hooks.cpp
index e5ea0cb6..302fa7bb 100644
--- a/NorthstarDedicatedTest/hooks.cpp
+++ b/NorthstarDedicatedTest/hooks.cpp
@@ -14,15 +14,9 @@ HMODULE LoadLibraryExAHook(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
typedef HMODULE(*LoadLibraryExWType)(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
HMODULE LoadLibraryExWHook(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
-typedef BOOLEAN(*PDLL_INIT_ROUTINE)(PVOID DllHandle, ULONG Reason, PCONTEXT Context);
-typedef BOOLEAN(*LdrpCallInitRoutineType)(PDLL_INIT_ROUTINE EntryPoint, PVOID BaseAddress, ULONG Reason, PVOID Context);
-BOOLEAN LdrpCallInitRoutineHook(PDLL_INIT_ROUTINE EntryPoint, PVOID BaseAddress, ULONG Reason, PVOID Context);
-
LoadLibraryExAType LoadLibraryExAOriginal;
LoadLibraryExWType LoadLibraryExWOriginal;
-LdrpCallInitRoutineType LdrpCallInitRoutineHookOriginal;
-
void InstallInitialHooks()
{
if (MH_Initialize() != MH_OK)
@@ -31,9 +25,6 @@ void InstallInitialHooks()
HookEnabler hook;
ENABLER_CREATEHOOK(hook, &LoadLibraryExA, &LoadLibraryExAHook, reinterpret_cast(&LoadLibraryExAOriginal));
ENABLER_CREATEHOOK(hook, &LoadLibraryExW, &LoadLibraryExWHook, reinterpret_cast(&LoadLibraryExWOriginal));
-
- void* LdrpCallInitRoutine = FindSignature("ntdll.dll", "\x48\x89\x5C\x24\x00\x44\x89\x44\x24\x00\x48\x89\x54\x24", "xxxx?xxxx?xxxx");
- ENABLER_CREATEHOOK(hook, LdrpCallInitRoutine, &LdrpCallInitRoutineHook, reinterpret_cast(&LdrpCallInitRoutineHookOriginal));
}
// dll load callback stuff
@@ -43,18 +34,16 @@ struct DllLoadCallback
std::string dll;
DllLoadCallbackFuncType callback;
bool called;
- bool preinit;
};
std::vector dllLoadCallbacks;
-void AddDllLoadCallback(std::string dll, DllLoadCallbackFuncType callback, bool preinit)
+void AddDllLoadCallback(std::string dll, DllLoadCallbackFuncType callback)
{
DllLoadCallback* callbackStruct = new DllLoadCallback;
callbackStruct->dll = dll;
callbackStruct->callback = callback;
callbackStruct->called = false;
- callbackStruct->preinit = preinit;
dllLoadCallbacks.push_back(callbackStruct);
}
@@ -97,23 +86,4 @@ HMODULE LoadLibraryExWHook(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
}
return moduleAddress;
-}
-
-BOOLEAN LdrpCallInitRoutineHook(PDLL_INIT_ROUTINE EntryPoint, PVOID BaseAddress, ULONG Reason, PVOID Context)
-{
- char fullModulePath[MAX_PATH] = { 0 };
- GetModuleFileNameA((HMODULE)BaseAddress, fullModulePath, sizeof(fullModulePath));
-
- std::string name = std::filesystem::path(fullModulePath).filename().string();
-
- for (auto& callbackStruct : dllLoadCallbacks)
- {
- if (!callbackStruct->called && callbackStruct->preinit && name == callbackStruct->dll)
- {
- callbackStruct->callback((HMODULE)BaseAddress);
- callbackStruct->called = true;
- }
- }
-
- return LdrpCallInitRoutineHookOriginal(EntryPoint, BaseAddress, Reason, Context);
}
\ No newline at end of file
diff --git a/NorthstarDedicatedTest/hooks.h b/NorthstarDedicatedTest/hooks.h
index 012b12ec..972b38a6 100644
--- a/NorthstarDedicatedTest/hooks.h
+++ b/NorthstarDedicatedTest/hooks.h
@@ -4,4 +4,4 @@
void InstallInitialHooks();
typedef void(*DllLoadCallbackFuncType)(HMODULE moduleAddress);
-void AddDllLoadCallback(std::string dll, DllLoadCallbackFuncType callback, bool preinit = false);
\ No newline at end of file
+void AddDllLoadCallback(std::string dll, DllLoadCallbackFuncType callback);
\ No newline at end of file
diff --git a/NorthstarDedicatedTest/maxplayers.cpp b/NorthstarDedicatedTest/maxplayers.cpp
index 1c984c96..e649b0a6 100644
--- a/NorthstarDedicatedTest/maxplayers.cpp
+++ b/NorthstarDedicatedTest/maxplayers.cpp
@@ -427,6 +427,10 @@ void InitialiseMaxPlayersOverride_Server(HMODULE baseAddress)
// GameLoop::RunUserCmds - rebuild
HookEnabler hook;
ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x483D10, &RunUserCmds_Hook, reinterpret_cast(&RunUserCmds_Original));
+
+ *(DWORD*)((char*)baseAddress + 0x14E7390) = 0;
+ auto DT_PlayerResource_Construct = (__int64(__fastcall*)())((char*)baseAddress + 0x5C4FE0);
+ DT_PlayerResource_Construct();
}
void InitialiseMaxPlayersOverride_Client(HMODULE baseAddress)
@@ -579,4 +583,8 @@ void InitialiseMaxPlayersOverride_Client(HMODULE baseAddress)
// Some other get name func 2 (that seems to be unused too) - change m_bConnected address
ChangeOffset((char*)baseAddress + 0x164834 + 3, C_PlayerResource_OriginalSize + PlayerResource_Connected_Start);
+
+ *(DWORD*)((char*)baseAddress + 0xC35068) = 0;
+ auto DT_PlayerResource_Construct = (__int64(__fastcall*)())((char*)baseAddress + 0x163400);
+ DT_PlayerResource_Construct();
}
\ No newline at end of file
--
cgit v1.2.3
From bea776a8f6bcba5f702483d868d6fb6c4a069416 Mon Sep 17 00:00:00 2001
From: HappyDOGE <28511119+HappyDOGE@users.noreply.github.com>
Date: Tue, 28 Dec 2021 11:53:34 +0300
Subject: fix C(_)Team classes
---
NorthstarDedicatedTest/maxplayers.cpp | 70 +++++++++++++++++++++++++++++++++++
1 file changed, 70 insertions(+)
diff --git a/NorthstarDedicatedTest/maxplayers.cpp b/NorthstarDedicatedTest/maxplayers.cpp
index e649b0a6..e7d23032 100644
--- a/NorthstarDedicatedTest/maxplayers.cpp
+++ b/NorthstarDedicatedTest/maxplayers.cpp
@@ -3,6 +3,7 @@
// never set this to anything below 32
#define NEW_MAX_PLAYERS 64
+// dg note: the theoretical limit is actually 100, 76 works without entity issues, and 64 works without clientside prediction issues.
#define PAD_NUMBER(number, boundary) \
( ((number) + ((boundary)-1)) / (boundary) ) * (boundary)
@@ -40,6 +41,10 @@ constexpr int PlayerResource_ScoreStats_Size = (PlayerResource_ScoreStats_Length
// must be the usage of the last field to account for any possible paddings
constexpr int PlayerResource_TotalSize = PlayerResource_ScoreStats_Start + PlayerResource_ScoreStats_Size;
+constexpr int Team_PlayerArray_AddedLength = NEW_MAX_PLAYERS - 32;
+constexpr int Team_PlayerArray_AddedSize = PAD_NUMBER(Team_PlayerArray_AddedLength * 8, 4);
+constexpr int Team_AddedSize = Team_PlayerArray_AddedSize;
+
template
void ChangeOffset(void* addr, unsigned int offset)
{
@@ -289,6 +294,18 @@ void RunUserCmds_Hook(bool a1, float a2)
}
}
+typedef __int64(*SendPropArray2_Type)(__int64 recvProp, int elements, int flags, const char* name, __int64 proxyFn, unsigned char unk1);
+SendPropArray2_Type SendPropArray2_Original;
+
+__int64 __fastcall SendPropArray2_Hook(__int64 recvProp, int elements, int flags, const char* name, __int64 proxyFn, unsigned char unk1)
+{
+ // Change the amount of elements to account for a bigger player amount
+ if (!strcmp(name, "\"player_array\""))
+ elements = NEW_MAX_PLAYERS;
+
+ return SendPropArray2_Original(recvProp, elements, flags, name, proxyFn, unk1);
+}
+
void InitialiseMaxPlayersOverride_Server(HMODULE baseAddress)
{
// get required data
@@ -431,6 +448,37 @@ void InitialiseMaxPlayersOverride_Server(HMODULE baseAddress)
*(DWORD*)((char*)baseAddress + 0x14E7390) = 0;
auto DT_PlayerResource_Construct = (__int64(__fastcall*)())((char*)baseAddress + 0x5C4FE0);
DT_PlayerResource_Construct();
+
+ constexpr int CTeam_OriginalSize = 3336;
+ constexpr int CTeam_AddedSize = Team_AddedSize;
+ constexpr int CTeam_ModifiedSize = CTeam_OriginalSize + CTeam_AddedSize;
+
+ // CTeam class allocation function - allocate a bigger amount to fit all new team player data
+ ChangeOffset((char*)baseAddress + 0x23924A + 1, CTeam_ModifiedSize);
+
+ // CTeam::CTeam - increase memset length to clean newly allocated data
+ ChangeOffset((char*)baseAddress + 0x2395AE + 2, 256 + CTeam_AddedSize);
+
+ // hook required to change the size of DT_Team::"player_array"
+ HookEnabler hook2;
+ ENABLER_CREATEHOOK(hook2, (char*)baseAddress + 0x12B130, &SendPropArray2_Hook, reinterpret_cast(&SendPropArray2_Original));
+ hook2.~HookEnabler(); // force hook before calling construct function
+
+ *(DWORD*)((char*)baseAddress + 0xC945A0) = 0;
+ auto DT_Team_Construct = (__int64(__fastcall*)())((char*)baseAddress + 0x238F50);
+ DT_Team_Construct();
+}
+
+typedef __int64(*RecvPropArray2_Type)(__int64 recvProp, int elements, int flags, const char* name, __int64 proxyFn);
+RecvPropArray2_Type RecvPropArray2_Original;
+
+__int64 __fastcall RecvPropArray2_Hook(__int64 recvProp, int elements, int flags, const char* name, __int64 proxyFn)
+{
+ // Change the amount of elements to account for a bigger player amount
+ if (!strcmp(name, "\"player_array\""))
+ elements = NEW_MAX_PLAYERS;
+
+ return RecvPropArray2_Original(recvProp, elements, flags, name, proxyFn);
}
void InitialiseMaxPlayersOverride_Client(HMODULE baseAddress)
@@ -587,4 +635,26 @@ void InitialiseMaxPlayersOverride_Client(HMODULE baseAddress)
*(DWORD*)((char*)baseAddress + 0xC35068) = 0;
auto DT_PlayerResource_Construct = (__int64(__fastcall*)())((char*)baseAddress + 0x163400);
DT_PlayerResource_Construct();
+
+ constexpr int C_Team_OriginalSize = 3200;
+ constexpr int C_Team_AddedSize = Team_AddedSize;
+ constexpr int C_Team_ModifiedSize = C_Team_OriginalSize + C_Team_AddedSize;
+
+ // C_Team class allocation function - allocate a bigger amount to fit all new team player data
+ ChangeOffset((char*)baseAddress + 0x182321 + 1, C_Team_ModifiedSize);
+
+ // C_Team::C_Team - increase memset length to clean newly allocated data
+ ChangeOffset((char*)baseAddress + 0x1804A2 + 2, 256 + C_Team_AddedSize);
+
+ // DT_Team size
+ ChangeOffset((char*)baseAddress + 0xC3AA0C, C_Team_ModifiedSize);
+
+ // hook required to change the size of DT_Team::"player_array"
+ HookEnabler hook;
+ ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x1CEDA0, &RecvPropArray2_Hook, reinterpret_cast(&RecvPropArray2_Original));
+ hook.~HookEnabler(); // force hook before calling construct function
+
+ *(DWORD*)((char*)baseAddress + 0xC3AFF8) = 0;
+ auto DT_Team_Construct = (__int64(__fastcall*)())((char*)baseAddress + 0x17F950);
+ DT_Team_Construct();
}
\ No newline at end of file
--
cgit v1.2.3
From e49f026c92c75c4f10afd7f8895d8ebe2a01e97d Mon Sep 17 00:00:00 2001
From: HappyDOGE <28511119+HappyDOGE@users.noreply.github.com>
Date: Tue, 28 Dec 2021 12:18:58 +0300
Subject: implement svc_Print, copy NS hostname to source cvar
---
NorthstarDedicatedTest/logging.cpp | 18 ++++++++++++++++++
NorthstarDedicatedTest/masterserver.cpp | 12 +++++++++++-
2 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/NorthstarDedicatedTest/logging.cpp b/NorthstarDedicatedTest/logging.cpp
index 6525df27..0e72cc80 100644
--- a/NorthstarDedicatedTest/logging.cpp
+++ b/NorthstarDedicatedTest/logging.cpp
@@ -331,6 +331,21 @@ void Status_ConMsg_Hook(const char* text, ...)
spdlog::info(formatted);
}
+typedef bool(*CClientState_ProcessPrint_Type)(__int64 thisptr, __int64 msg);
+CClientState_ProcessPrint_Type CClientState_ProcessPrint_Original;
+
+bool CClientState_ProcessPrint_Hook(__int64 thisptr, __int64 msg)
+{
+ char* text = *(char**)(msg + 0x20);
+
+ auto endpos = strlen(text);
+ if (text[endpos - 1] == '\n')
+ text[endpos - 1] = '\0'; // cut off repeated newline
+
+ spdlog::info(text);
+ return true;
+}
+
void InitialiseEngineSpewFuncHooks(HMODULE baseAddress)
{
HookEnabler hook;
@@ -339,4 +354,7 @@ void InitialiseEngineSpewFuncHooks(HMODULE baseAddress)
// Hook print function that status concmd uses to actually print data
ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x15ABD0, Status_ConMsg_Hook, reinterpret_cast(&Status_ConMsg_Original));
+
+ // Hook CClientState::ProcessPrint
+ ENABLER_CREATEHOOK(hook, (char*)baseAddress + 0x1A1530, CClientState_ProcessPrint_Hook, reinterpret_cast(&CClientState_ProcessPrint_Original));
}
\ No newline at end of file
diff --git a/NorthstarDedicatedTest/masterserver.cpp b/NorthstarDedicatedTest/masterserver.cpp
index 706f60ec..d7fea6d1 100644
--- a/NorthstarDedicatedTest/masterserver.cpp
+++ b/NorthstarDedicatedTest/masterserver.cpp
@@ -21,6 +21,9 @@ ConVar* Cvar_ns_server_name;
ConVar* Cvar_ns_server_desc;
ConVar* Cvar_ns_server_password;
+// Source ConVar
+ConVar* Cvar_hostname;
+
MasterServerManager* g_MasterServerManager;
typedef void(*CHostState__State_NewGameType)(CHostState* hostState);
@@ -127,7 +130,7 @@ void MasterServerManager::AuthenticateOriginWithMasterServer(char* uid, char* or
if (originAuthInfo.HasParseError())
{
- spdlog::error("Failed reading origin auth info response: encountered parse error \{}\"", rapidjson::GetParseError_En(originAuthInfo.GetParseError()));
+ spdlog::error("Failed reading origin auth info response: encountered parse error \"{}\"", rapidjson::GetParseError_En(originAuthInfo.GetParseError()));
goto REQUEST_END_CLEANUP;
}
@@ -852,6 +855,10 @@ void CHostState__State_NewGameHook(CHostState* hostState)
if (maxPlayersVar) // GetCurrentPlaylistVar can return null so protect against this
maxPlayers = std::stoi(maxPlayersVar);
+ // Copy new server name cvar to source
+ Cvar_hostname->m_pszString = Cvar_ns_server_name->m_pszString;
+ Cvar_hostname->m_StringLength = Cvar_ns_server_name->m_StringLength;
+
g_MasterServerManager->AddSelfToServerList(Cvar_hostport->m_nValue, Cvar_ns_player_auth_port->m_nValue, Cvar_ns_server_name->m_pszString, Cvar_ns_server_desc->m_pszString, hostState->m_levelName, (char*)GetCurrentPlaylistName(), maxPlayers, Cvar_ns_server_password->m_pszString);
g_ServerAuthenticationManager->StartPlayerAuthServer();
g_ServerAuthenticationManager->m_bNeedLocalAuthForNewgame = false;
@@ -898,6 +905,9 @@ void InitialiseSharedMasterServer(HMODULE baseAddress)
Cvar_ns_server_password = RegisterConVar("ns_server_password", "", FCVAR_GAMEDLL, "");
Cvar_ns_report_server_to_masterserver = RegisterConVar("ns_report_server_to_masterserver", "1", FCVAR_GAMEDLL, "");
Cvar_ns_report_sp_server_to_masterserver = RegisterConVar("ns_report_sp_server_to_masterserver", "0", FCVAR_GAMEDLL, "");
+
+ Cvar_hostname = *(ConVar**)((char*)baseAddress + 0x1315bae8);
+
g_MasterServerManager = new MasterServerManager;
RegisterConCommand("ns_fetchservers", ConCommand_ns_fetchservers, "", FCVAR_CLIENTDLL);
--
cgit v1.2.3
From 010a6e1399d09faf1eac21b57efd55c736b11608 Mon Sep 17 00:00:00 2001
From: HappyDOGE <28511119+HappyDOGE@users.noreply.github.com>
Date: Tue, 28 Dec 2021 12:27:28 +0300
Subject: fix build error in masterserver.cpp
---
NorthstarDedicatedTest/masterserver.cpp | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/NorthstarDedicatedTest/masterserver.cpp b/NorthstarDedicatedTest/masterserver.cpp
index b5b394cc..da017b24 100644
--- a/NorthstarDedicatedTest/masterserver.cpp
+++ b/NorthstarDedicatedTest/masterserver.cpp
@@ -892,18 +892,22 @@ void MasterServerManager::WritePlayerPersistentData(char* playerId, char* pdata,
bool MasterServerManager::RemoveSelfFromServerListThread()
{
+ bool removed = true;
+
// we dont process this at all atm, maybe do later, but atm not necessary
LazyCreateHttpClient();
if (auto result = m_httpClient->Delete(fmt::format("/server/remove_server?id={}", m_ownServerId).c_str()))
{
m_successfullyConnected = true;
+ m_ownServerId[0] = 0;
}
else
{
m_successfullyConnected = false;
+ removed = false;
}
- m_ownServerId[0] = 0;
+ return removed;
}
void MasterServerManager::RemoveSelfFromServerList()
--
cgit v1.2.3
From 1c1b18e1b7887a76eb56bd33fd983fdcfd171a08 Mon Sep 17 00:00:00 2001
From: HappyDOGE <28511119+HappyDOGE@users.noreply.github.com>
Date: Tue, 28 Dec 2021 12:31:54 +0300
Subject: add a toggle for maxplayers increase functionality (unrecommended)
---
NorthstarDedicatedTest/maxplayers.cpp | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/NorthstarDedicatedTest/maxplayers.cpp b/NorthstarDedicatedTest/maxplayers.cpp
index e7d23032..ed2ac26a 100644
--- a/NorthstarDedicatedTest/maxplayers.cpp
+++ b/NorthstarDedicatedTest/maxplayers.cpp
@@ -1,5 +1,6 @@
#include "pch.h"
#include "maxplayers.h"
+#include "gameutils.h"
// never set this to anything below 32
#define NEW_MAX_PLAYERS 64
@@ -102,8 +103,17 @@ void* StringTables_CreateStringTable_Hook(__int64 thisptr, const char* name, int
return StringTables_CreateStringTable_Original(thisptr, name, maxentries, userdatafixedsize, userdatanetworkbits, flags);
}
+bool MaxPlayersIncreaseEnabled()
+{
+ // Unrecommended: this will break compatibility with clients/servers that have it enabled.
+ return CommandLine() && !CommandLine()->CheckParm("-nomaxplayersincrease");
+}
+
void InitialiseMaxPlayersOverride_Engine(HMODULE baseAddress)
{
+ if (!MaxPlayersIncreaseEnabled())
+ return;
+
// patch GetPlayerLimits to ignore the boundary limit
ChangeOffset((char*)baseAddress + 0x116458, 0xEB); // jle => jmp
@@ -308,6 +318,9 @@ __int64 __fastcall SendPropArray2_Hook(__int64 recvProp, int elements, int flags
void InitialiseMaxPlayersOverride_Server(HMODULE baseAddress)
{
+ if (!MaxPlayersIncreaseEnabled())
+ return;
+
// get required data
serverBase = GetModuleHandleA("server.dll");
RandomIntZeroMax = (decltype(RandomIntZeroMax))(GetProcAddress(GetModuleHandleA("vstdlib.dll"), "RandomIntZeroMax"));
@@ -483,6 +496,9 @@ __int64 __fastcall RecvPropArray2_Hook(__int64 recvProp, int elements, int flags
void InitialiseMaxPlayersOverride_Client(HMODULE baseAddress)
{
+ if (!MaxPlayersIncreaseEnabled())
+ return;
+
constexpr int C_PlayerResource_OriginalSize = 5768;
constexpr int C_PlayerResource_AddedSize = PlayerResource_TotalSize;
constexpr int C_PlayerResource_ModifiedSize = C_PlayerResource_OriginalSize + C_PlayerResource_AddedSize;
--
cgit v1.2.3
From bb93442db8b1e450adf08a8305335020c436d358 Mon Sep 17 00:00:00 2001
From: HappyDOGE <28511119+HappyDOGE@users.noreply.github.com>
Date: Tue, 28 Dec 2021 12:56:08 +0300
Subject: dedicated console command input
---
NorthstarDedicatedTest/dedicated.cpp | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/NorthstarDedicatedTest/dedicated.cpp b/NorthstarDedicatedTest/dedicated.cpp
index 83a9950a..26dcc9ae 100644
--- a/NorthstarDedicatedTest/dedicated.cpp
+++ b/NorthstarDedicatedTest/dedicated.cpp
@@ -76,6 +76,32 @@ bool IsGameActiveWindowHook()
return true;
}
+HANDLE consoleInputThreadHandle = NULL;
+
+DWORD WINAPI ConsoleInputThread(PVOID pThreadParameter)
+{
+ while (!g_pEngine || !g_pHostState || g_pHostState->m_iCurrentState != HostState_t::HS_RUN)
+ Sleep(1000);
+
+ // Bind stdin to receive console input.
+ FILE* fp = nullptr;
+ freopen_s(&fp, "CONIN$", "r", stdin);
+
+ spdlog::info("Ready to receive console commands.");
+
+ {
+ // Process console input
+ std::string input;
+ while (g_pEngine && g_pEngine->m_nQuitting == EngineQuitState::QUIT_NOTQUITTING && std::getline(std::cin, input))
+ {
+ input += "\n";
+ Cbuf_AddText(Cbuf_GetCurrentPlayer(), input.c_str(), cmd_source_t::kCommandSrcCode);
+ }
+ }
+
+ return 0;
+}
+
void InitialiseDedicated(HMODULE engineAddress)
{
if (!IsDedicated())
@@ -380,6 +406,9 @@ void InitialiseDedicated(HMODULE engineAddress)
CommandLine()->AppendParm("+host_preload_shaders", "0");
CommandLine()->AppendParm("+net_usesocketsforloopback", "1");
CommandLine()->AppendParm("+exec", "autoexec_ns_server");
+
+ // create console input thread
+ consoleInputThreadHandle = CreateThread(0, 0, ConsoleInputThread, 0, 0, NULL);
}
typedef void(*Tier0_InitOriginType)();
--
cgit v1.2.3
From 8179de9831dd415794269015a40de44baa4c29d1 Mon Sep 17 00:00:00 2001
From: HappyDOGE <28511119+HappyDOGE@users.noreply.github.com>
Date: Tue, 28 Dec 2021 13:17:55 +0300
Subject: add parm checks for dedicated input + disable quick edit
---
NorthstarDedicatedTest/dedicated.cpp | 24 +++++++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/NorthstarDedicatedTest/dedicated.cpp b/NorthstarDedicatedTest/dedicated.cpp
index 26dcc9ae..91e9cef6 100644
--- a/NorthstarDedicatedTest/dedicated.cpp
+++ b/NorthstarDedicatedTest/dedicated.cpp
@@ -407,8 +407,30 @@ void InitialiseDedicated(HMODULE engineAddress)
CommandLine()->AppendParm("+net_usesocketsforloopback", "1");
CommandLine()->AppendParm("+exec", "autoexec_ns_server");
+ // Disable Quick Edit mode to reduce chance of user unintentionally hanging their server by selecting something.
+ if (!CommandLine()->CheckParm("-bringbackquickedit"))
+ {
+ spdlog::info("Quick Edit enabled by user request");
+
+ HANDLE stdIn = GetStdHandle(STD_INPUT_HANDLE);
+ DWORD mode = 0;
+
+ if (GetConsoleMode(stdIn, &mode)) {
+ if (mode & ENABLE_QUICK_EDIT_MODE) {
+ mode &= ~ENABLE_QUICK_EDIT_MODE;
+ mode &= ~ENABLE_MOUSE_INPUT;
+
+ mode |= ENABLE_PROCESSED_INPUT;
+
+ SetConsoleMode(stdIn, mode);
+ }
+ }
+ }
+
// create console input thread
- consoleInputThreadHandle = CreateThread(0, 0, ConsoleInputThread, 0, 0, NULL);
+ if (!CommandLine()->CheckParm("-noconsoleinput"))
+ consoleInputThreadHandle = CreateThread(0, 0, ConsoleInputThread, 0, 0, NULL);
+ else spdlog::info("Console input disabled by user request");
}
typedef void(*Tier0_InitOriginType)();
--
cgit v1.2.3
From 4e9e9d9766663c39e21fcdd33e865cdc8cbf7e6a Mon Sep 17 00:00:00 2001
From: HappyDOGE <28511119+HappyDOGE@users.noreply.github.com>
Date: Tue, 28 Dec 2021 13:34:09 +0300
Subject: fix quick edit enabled message
---
NorthstarDedicatedTest/dedicated.cpp | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/NorthstarDedicatedTest/dedicated.cpp b/NorthstarDedicatedTest/dedicated.cpp
index 91e9cef6..f77567ec 100644
--- a/NorthstarDedicatedTest/dedicated.cpp
+++ b/NorthstarDedicatedTest/dedicated.cpp
@@ -410,8 +410,6 @@ void InitialiseDedicated(HMODULE engineAddress)
// Disable Quick Edit mode to reduce chance of user unintentionally hanging their server by selecting something.
if (!CommandLine()->CheckParm("-bringbackquickedit"))
{
- spdlog::info("Quick Edit enabled by user request");
-
HANDLE stdIn = GetStdHandle(STD_INPUT_HANDLE);
DWORD mode = 0;
@@ -425,7 +423,7 @@ void InitialiseDedicated(HMODULE engineAddress)
SetConsoleMode(stdIn, mode);
}
}
- }
+ } else spdlog::info("Quick Edit enabled by user request");
// create console input thread
if (!CommandLine()->CheckParm("-noconsoleinput"))
--
cgit v1.2.3
From 2942ea56527100d5e39e0bbba4a1d16b1cde6128 Mon Sep 17 00:00:00 2001
From: HappyDOGE <28511119+HappyDOGE@users.noreply.github.com>
Date: Tue, 28 Dec 2021 19:18:32 +0300
Subject: make max players increase disabled by default
---
NorthstarDedicatedTest/maxplayers.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/NorthstarDedicatedTest/maxplayers.cpp b/NorthstarDedicatedTest/maxplayers.cpp
index ed2ac26a..9d08e83f 100644
--- a/NorthstarDedicatedTest/maxplayers.cpp
+++ b/NorthstarDedicatedTest/maxplayers.cpp
@@ -105,8 +105,7 @@ void* StringTables_CreateStringTable_Hook(__int64 thisptr, const char* name, int
bool MaxPlayersIncreaseEnabled()
{
- // Unrecommended: this will break compatibility with clients/servers that have it enabled.
- return CommandLine() && !CommandLine()->CheckParm("-nomaxplayersincrease");
+ return CommandLine() && CommandLine()->CheckParm("-experimentalmaxplayersincrease");
}
void InitialiseMaxPlayersOverride_Engine(HMODULE baseAddress)
--
cgit v1.2.3