aboutsummaryrefslogtreecommitdiff
path: root/NorthstarDLL
diff options
context:
space:
mode:
authorBobTheBob9 <for.oliver.kirkham@gmail.com>2022-07-12 14:05:02 +0100
committerBobTheBob9 <for.oliver.kirkham@gmail.com>2022-07-12 14:05:02 +0100
commit6ae30c9b15fcc200c7b642016e7adbfdf9b979f4 (patch)
treef645afba242a092e1e920582f37ae396e35b5e06 /NorthstarDLL
parent1068b3daeb95322461e69a2d8f0203309bd22830 (diff)
downloadNorthstarLauncher-6ae30c9b15fcc200c7b642016e7adbfdf9b979f4.tar.gz
NorthstarLauncher-6ae30c9b15fcc200c7b642016e7adbfdf9b979f4.zip
move exploit prevention and limits code out of serverauthentication, and have actual defs for CBasePlayer
Diffstat (limited to 'NorthstarDLL')
-rw-r--r--NorthstarDLL/ExploitFixes_UTF8Parser.h175
-rw-r--r--NorthstarDLL/NorthstarDLL.vcxproj7
-rw-r--r--NorthstarDLL/NorthstarDLL.vcxproj.filters428
-rw-r--r--NorthstarDLL/audio.cpp3
-rw-r--r--NorthstarDLL/bansystem.cpp19
-rw-r--r--NorthstarDLL/bansystem.h2
-rw-r--r--NorthstarDLL/buildainfile.cpp14
-rw-r--r--NorthstarDLL/clientauthhooks.cpp6
-rw-r--r--NorthstarDLL/clientchathooks.cpp32
-rw-r--r--NorthstarDLL/dedicated.cpp4
-rw-r--r--NorthstarDLL/exploitfixes.cpp (renamed from NorthstarDLL/ExploitFixes.cpp)78
-rw-r--r--NorthstarDLL/exploitfixes_utf8parser.cpp190
-rw-r--r--NorthstarDLL/hoststate.cpp16
-rw-r--r--NorthstarDLL/limits.cpp185
-rw-r--r--NorthstarDLL/limits.h44
-rw-r--r--NorthstarDLL/localchatwriter.cpp69
-rw-r--r--NorthstarDLL/localchatwriter.h19
-rw-r--r--NorthstarDLL/masterserver.cpp26
-rw-r--r--NorthstarDLL/masterserver.h2
-rw-r--r--NorthstarDLL/misccommands.cpp8
-rw-r--r--NorthstarDLL/miscserverfixes.cpp4
-rw-r--r--NorthstarDLL/miscserverscript.cpp31
-rw-r--r--NorthstarDLL/miscserverscript.h2
-rw-r--r--NorthstarDLL/modmanager.cpp2
-rw-r--r--NorthstarDLL/playlist.cpp6
-rw-r--r--NorthstarDLL/plugins.cpp2
-rw-r--r--NorthstarDLL/printmaps.cpp2
-rw-r--r--NorthstarDLL/r2engine.cpp4
-rw-r--r--NorthstarDLL/r2engine.h41
-rw-r--r--NorthstarDLL/r2server.cpp6
-rw-r--r--NorthstarDLL/r2server.h42
-rw-r--r--NorthstarDLL/scriptmainmenupromos.cpp32
-rw-r--r--NorthstarDLL/scriptserverbrowser.cpp114
-rw-r--r--NorthstarDLL/serverauthentication.cpp403
-rw-r--r--NorthstarDLL/serverauthentication.h96
-rw-r--r--NorthstarDLL/serverchathooks.cpp25
36 files changed, 1112 insertions, 1027 deletions
diff --git a/NorthstarDLL/ExploitFixes_UTF8Parser.h b/NorthstarDLL/ExploitFixes_UTF8Parser.h
deleted file mode 100644
index 77014a35..00000000
--- a/NorthstarDLL/ExploitFixes_UTF8Parser.h
+++ /dev/null
@@ -1,175 +0,0 @@
-// Reimplementation of a exploitable UTF decoding function in titanfall
-
-#include "NSMem.h"
-
-#pragma once
-
-namespace ExploitFixes_UTF8Parser
-{
- bool __fastcall CheckValid(INT64* a1, DWORD* a2, char* strData)
- {
- static auto sub_F1320 = (INT64(__fastcall*)(DWORD a1, char* a2))NSMem::PatternScan("engine.dll", "83 F9 7F 77 08 88 0A");
-
- DWORD v3; // eax
- char* v4; // rbx
- char v5; // si
- char* _strData; // rdi
- char* v7; // rbp
- char v11; // al
- DWORD v12; // er9
- DWORD v13; // ecx
- DWORD v14; // edx
- DWORD v15; // er8
- int v16; // eax
- DWORD v17; // er9
- int v18; // eax
- DWORD v19; // er9
- DWORD v20; // ecx
- int v21; // eax
- int v22; // er9
- DWORD v23; // edx
- int v24; // eax
- int v25; // er9
- DWORD v26; // er9
- DWORD v27; // er10
- DWORD v28; // ecx
- DWORD v29; // edx
- DWORD v30; // er8
- int v31; // eax
- DWORD v32; // er10
- int v33; // eax
- DWORD v34; // er10
- DWORD v35; // ecx
- int v36; // eax
- int v37; // er10
- DWORD v38; // edx
- int v39; // eax
- int v40; // er10
- DWORD v41; // er10
- INT64 v43; // r8
- INT64 v44; // rdx
- INT64 v45; // rcx
- INT64 v46; // rax
- INT64 v47; // rax
- char v48; // al
- INT64 v49; // r8
- INT64 v50; // rdx
- INT64 v51; // rcx
- INT64 v52; // rax
- INT64 v53; // rax
-
- v3 = a2[2];
- v4 = (char*)(a1[1] + *a2);
- v5 = 0;
- _strData = strData;
- v7 = &v4[*((UINT16*)a2 + 2)];
- if (v3 >= 2)
- {
- ++v4;
- --v7;
- if (v3 != 2)
- {
- while (1)
- {
-
- if (!NSMem::IsMemoryReadable(v4, 1))
- return false; // INVALID
-
- v11 = *v4++; // crash potential
- if (v11 != 92)
- goto LABEL_6;
- v11 = *v4++;
- if (v11 == 110)
- break;
- switch (v11)
- {
- case 't':
- v11 = 9;
- goto LABEL_6;
- case 'r':
- v11 = 13;
- goto LABEL_6;
- case 'b':
- v11 = 8;
- goto LABEL_6;
- case 'f':
- v11 = 12;
- goto LABEL_6;
- }
- if (v11 != 117)
- goto LABEL_6;
- v12 = *v4 | 0x20;
- v13 = v4[1] | 0x20;
- v14 = v4[2] | 0x20;
- v15 = v4[3] | 0x20;
- v16 = 87;
- if (v12 <= 0x39)
- v16 = 48;
- v17 = v12 - v16;
- v18 = 87;
- v19 = v17 << 12;
- if (v13 <= 0x39)
- v18 = 48;
- v20 = v13 - v18;
- v21 = 87;
- v22 = (v20 << 8) | v19;
- if (v14 <= 0x39)
- v21 = 48;
- v23 = v14 - v21;
- v24 = 87;
- v25 = (16 * v23) | v22;
- if (v15 <= 0x39)
- v24 = 48;
- v4 += 4;
- v26 = (v15 - v24) | v25;
- if (v26 - 55296 <= 0x7FF)
- {
- if (v26 >= 0xDC00)
- return true;
- if (*v4 != 92 || v4[1] != 117)
- return true;
-
- v27 = v4[2] | 0x20;
- v28 = v4[3] | 0x20;
- v29 = v4[4] | 0x20;
- v30 = v4[5] | 0x20;
- v31 = 87;
- if (v27 <= 0x39)
- v31 = 48;
- v32 = v27 - v31;
- v33 = 87;
- v34 = v32 << 12;
- if (v28 <= 0x39)
- v33 = 48;
- v35 = v28 - v33;
- v36 = 87;
- v37 = (v35 << 8) | v34;
- if (v29 <= 0x39)
- v36 = 48;
- v38 = v29 - v36;
- v39 = 87;
- v40 = (16 * v38) | v37;
- if (v30 <= 0x39)
- v39 = 48;
- v4 += 6;
- v41 = ((v30 - v39) | v40) - 56320;
- if (v41 > 0x3FF)
- return true;
- v26 = v41 | ((v26 - 55296) << 10);
- }
- _strData += (DWORD)sub_F1320(v26, _strData);
- LABEL_7:
- if (v4 == v7)
- goto LABEL_48;
- }
- v11 = 10;
- LABEL_6:
- v5 |= v11;
- *_strData++ = v11;
- goto LABEL_7;
- }
- }
- LABEL_48:
- return true;
- }
-} // namespace ExploitFixes_UTF8Parser \ No newline at end of file
diff --git a/NorthstarDLL/NorthstarDLL.vcxproj b/NorthstarDLL/NorthstarDLL.vcxproj
index 4f880642..43e1062a 100644
--- a/NorthstarDLL/NorthstarDLL.vcxproj
+++ b/NorthstarDLL/NorthstarDLL.vcxproj
@@ -120,6 +120,7 @@
<ClInclude Include="bitbuf.h" />
<ClInclude Include="bits.h" />
<ClInclude Include="crashhandler.h" />
+ <ClInclude Include="limits.h" />
<ClInclude Include="printcommand.h" />
<ClInclude Include="hoststate.h" />
<ClInclude Include="localchatwriter.h" />
@@ -545,7 +546,6 @@
<ClInclude Include="pch.h" />
<ClInclude Include="pdef.h" />
<ClInclude Include="playlist.h" />
- <ClInclude Include="miscserverscript.h" />
<ClInclude Include="rpakfilesystem.h" />
<ClInclude Include="scriptsrson.h" />
<ClInclude Include="serverauthentication.h" />
@@ -553,7 +553,7 @@
<ClInclude Include="sourceconsole.h" />
<ClInclude Include="sourceinterface.h" />
<ClInclude Include="squirrel.h" />
- <ClInclude Include="ExploitFixes_UTF8Parser.h" />
+ <ClInclude Include="exploitfixes_utf8parser.cpp" />
<ClInclude Include="NSMem.h" />
<ClInclude Include="tier0.h" />
<ClInclude Include="version.h" />
@@ -569,6 +569,7 @@
<ClCompile Include="clientruihooks.cpp" />
<ClCompile Include="clientvideooverrides.cpp" />
<ClCompile Include="concommand.cpp" />
+ <ClCompile Include="limits.cpp" />
<ClCompile Include="nsprefix.cpp" />
<ClCompile Include="convar.cpp" />
<ClCompile Include="crashhandler.cpp" />
@@ -621,7 +622,7 @@
<ClCompile Include="sourceconsole.cpp" />
<ClCompile Include="sourceinterface.cpp" />
<ClCompile Include="squirrel.cpp" />
- <ClCompile Include="ExploitFixes.cpp" />
+ <ClCompile Include="exploitfixes.cpp" />
<ClCompile Include="tier0.cpp" />
<ClCompile Include="version.cpp" />
</ItemGroup>
diff --git a/NorthstarDLL/NorthstarDLL.vcxproj.filters b/NorthstarDLL/NorthstarDLL.vcxproj.filters
index 1b7603c3..514800c1 100644
--- a/NorthstarDLL/NorthstarDLL.vcxproj.filters
+++ b/NorthstarDLL/NorthstarDLL.vcxproj.filters
@@ -16,27 +16,12 @@
<Filter Include="Header Files\include">
<UniqueIdentifier>{d4199e4b-10d2-43ce-af9c-e1fa79e1e64e}</UniqueIdentifier>
</Filter>
- <Filter Include="Header Files\Shared">
- <UniqueIdentifier>{4d322431-dcaa-4f75-aee0-3b6371cf52a6}</UniqueIdentifier>
- </Filter>
- <Filter Include="Header Files\Shared\Hooks">
- <UniqueIdentifier>{94259c8c-5411-48bf-af4f-46ca32b7d0bb}</UniqueIdentifier>
- </Filter>
- <Filter Include="Source Files\Shared">
- <UniqueIdentifier>{4f525372-34a8-40b3-8a95-81d77cdfcf7f}</UniqueIdentifier>
- </Filter>
<Filter Include="Source Files\Client">
<UniqueIdentifier>{b6f79919-9735-476d-8798-067a75cbeca0}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\Client">
<UniqueIdentifier>{ca657be5-c2d8-4322-a689-1154aaafe57b}</UniqueIdentifier>
</Filter>
- <Filter Include="Source Files\Shared\Convar">
- <UniqueIdentifier>{a18afb37-5fdd-4340-a6b4-a6541593e398}</UniqueIdentifier>
- </Filter>
- <Filter Include="Header Files\Shared\Convar">
- <UniqueIdentifier>{9751b551-5886-45d4-a039-cbd10445263d}</UniqueIdentifier>
- </Filter>
<Filter Include="Header Files\include\spdlog">
<UniqueIdentifier>{8596cc1c-0492-4467-91e3-1f03b7e19f77}</UniqueIdentifier>
</Filter>
@@ -55,12 +40,6 @@
<Filter Include="Header Files\include\spdlog\details">
<UniqueIdentifier>{74567974-c66b-45ef-ab28-97b7154ca224}</UniqueIdentifier>
</Filter>
- <Filter Include="Source Files\Shared\Mods">
- <UniqueIdentifier>{3e892d07-2239-44da-9cf3-c288a34cf9a2}</UniqueIdentifier>
- </Filter>
- <Filter Include="Header Files\Shared\Mods">
- <UniqueIdentifier>{6bbce8a5-38b4-4763-a7cb-4e98012ec245}</UniqueIdentifier>
- </Filter>
<Filter Include="Header Files\include\rapidjson">
<UniqueIdentifier>{4ca5392e-7d3d-4066-833f-f534cd5787c3}</UniqueIdentifier>
</Filter>
@@ -73,12 +52,6 @@
<Filter Include="Header Files\include\rapidjson\msinttypes">
<UniqueIdentifier>{85aacdee-0f92-4ec4-b20c-0739c1175055}</UniqueIdentifier>
</Filter>
- <Filter Include="Source Files\Shared\Hooks">
- <UniqueIdentifier>{4db0d1e9-9035-457f-87f1-5dc3f13b6b9e}</UniqueIdentifier>
- </Filter>
- <Filter Include="Header Files\Shared\Mods\Compiled">
- <UniqueIdentifier>{d1f93d1e-0ecb-44fe-a277-d3e75aec2570}</UniqueIdentifier>
- </Filter>
<Filter Include="Source Files\Server">
<UniqueIdentifier>{3d41d3fc-8a3b-4358-b3e8-4f06dc96abfe}</UniqueIdentifier>
</Filter>
@@ -91,12 +64,6 @@
<Filter Include="Header Files\Server\Authentication">
<UniqueIdentifier>{24fd0855-9288-4129-93ba-c6cafdc98d1b}</UniqueIdentifier>
</Filter>
- <Filter Include="Source Files\Shared\Game Functions">
- <UniqueIdentifier>{2cbddb28-0b17-4881-847d-8773da52b268}</UniqueIdentifier>
- </Filter>
- <Filter Include="Header Files\Shared\Game Functions">
- <UniqueIdentifier>{0c93d909-e0d6-4c35-a8a4-a13f681a1012}</UniqueIdentifier>
- </Filter>
<Filter Include="Header Files\include\openssl">
<UniqueIdentifier>{4cb0dd89-5f16-4549-a864-34ca3075352a}</UniqueIdentifier>
</Filter>
@@ -112,45 +79,75 @@
<Filter Include="Header Files\include\libcurl">
<UniqueIdentifier>{ea1e17a6-40b7-4e1b-8edb-e9ae704ce604}</UniqueIdentifier>
</Filter>
- <Filter Include="Source Files\Shared\Math">
- <UniqueIdentifier>{59b0f68f-daa7-4641-b6fa-8464b56da2bb}</UniqueIdentifier>
- </Filter>
- <Filter Include="Header Files\Shared\Math">
- <UniqueIdentifier>{44a83740-9d70-480d-9a7a-43b81f8eab9e}</UniqueIdentifier>
- </Filter>
- <Filter Include="Source Files\Shared\Exploit Fixes">
- <UniqueIdentifier>{4a8a695a-a103-4b1f-b314-0ec19a253119}</UniqueIdentifier>
- </Filter>
- <Filter Include="Source Files\Shared\Mods\Compiled Assets">
- <UniqueIdentifier>{14fc0931-acad-46ec-a55e-94f4469d4235}</UniqueIdentifier>
- </Filter>
<Filter Include="Source Files\Client\Scripted">
<UniqueIdentifier>{51910ba0-2ff8-461d-9f67-8d7907b57d22}</UniqueIdentifier>
</Filter>
- <Filter Include="Source Files\Shared\Console">
- <UniqueIdentifier>{04fd662a-6e70-494c-b720-c694a5cc2fb1}</UniqueIdentifier>
- </Filter>
<Filter Include="Source Files\Server\Scripted">
<UniqueIdentifier>{325e0d7d-6832-496d-8d8e-968fdfa5dd40}</UniqueIdentifier>
</Filter>
<Filter Include="Header Files\Server\Scripted">
<UniqueIdentifier>{802d0771-62f1-4733-89f9-57a4d8864b8d}</UniqueIdentifier>
</Filter>
- <Filter Include="Header Files\Server\Dedicated">
- <UniqueIdentifier>{0f1ba4c4-78ee-4b05-afa5-6f598063f5c1}</UniqueIdentifier>
+ <Filter Include="Source Files\Console">
+ <UniqueIdentifier>{04fd662a-6e70-494c-b720-c694a5cc2fb1}</UniqueIdentifier>
</Filter>
- <Filter Include="Header Files\Shared\Console">
- <UniqueIdentifier>{bf0769d8-40fd-4701-85e9-7ed94aab2283}</UniqueIdentifier>
+ <Filter Include="Source Files\Convar">
+ <UniqueIdentifier>{a18afb37-5fdd-4340-a6b4-a6541593e398}</UniqueIdentifier>
</Filter>
- <Filter Include="Source Files\Shared\Filesystem">
+ <Filter Include="Source Files\Exploit Fixes">
+ <UniqueIdentifier>{4a8a695a-a103-4b1f-b314-0ec19a253119}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Filesystem">
<UniqueIdentifier>{d8a83b5e-9a23-4124-824f-eab37880cb08}</UniqueIdentifier>
</Filter>
- <Filter Include="Header Files\Shared\Filesystem">
- <UniqueIdentifier>{ee3ba13a-3061-41d7-981d-328ac2596fd2}</UniqueIdentifier>
+ <Filter Include="Source Files\Game Functions">
+ <UniqueIdentifier>{2cbddb28-0b17-4881-847d-8773da52b268}</UniqueIdentifier>
</Filter>
- <Filter Include="Source Files\Server\Dedicated Server">
+ <Filter Include="Source Files\Hooks">
+ <UniqueIdentifier>{4db0d1e9-9035-457f-87f1-5dc3f13b6b9e}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Math">
+ <UniqueIdentifier>{59b0f68f-daa7-4641-b6fa-8464b56da2bb}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Mods">
+ <UniqueIdentifier>{3e892d07-2239-44da-9cf3-c288a34cf9a2}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Mods\Compiled Assets">
+ <UniqueIdentifier>{14fc0931-acad-46ec-a55e-94f4469d4235}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files\Dedicated Server">
<UniqueIdentifier>{947835db-67d6-42c0-870d-62743f85231f}</UniqueIdentifier>
</Filter>
+ <Filter Include="Header Files\Console">
+ <UniqueIdentifier>{bf0769d8-40fd-4701-85e9-7ed94aab2283}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Convar">
+ <UniqueIdentifier>{9751b551-5886-45d4-a039-cbd10445263d}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Exploit Fixes">
+ <UniqueIdentifier>{96101d42-72af-4fd1-8559-8d1d1ff66240}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Filesystem">
+ <UniqueIdentifier>{ee3ba13a-3061-41d7-981d-328ac2596fd2}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Game Functions">
+ <UniqueIdentifier>{0c93d909-e0d6-4c35-a8a4-a13f681a1012}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Hooks">
+ <UniqueIdentifier>{94259c8c-5411-48bf-af4f-46ca32b7d0bb}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Math">
+ <UniqueIdentifier>{44a83740-9d70-480d-9a7a-43b81f8eab9e}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Mods">
+ <UniqueIdentifier>{6bbce8a5-38b4-4763-a7cb-4e98012ec245}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Mods\Compiled Assets">
+ <UniqueIdentifier>{826d5193-3ad0-434b-ba7c-dd24ed4bbd0c}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Header Files\Dedicated Server">
+ <UniqueIdentifier>{0f1ba4c4-78ee-4b05-afa5-6f598063f5c1}</UniqueIdentifier>
+ </Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="pch.h">
@@ -159,30 +156,12 @@
<ClInclude Include="include\MinHook.h">
<Filter>Header Files\include</Filter>
</ClInclude>
- <ClInclude Include="hooks.h">
- <Filter>Header Files\Shared\Hooks</Filter>
- </ClInclude>
<ClInclude Include="main.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="sourceconsole.h">
<Filter>Header Files\Client</Filter>
</ClInclude>
- <ClInclude Include="squirrel.h">
- <Filter>Header Files\Shared</Filter>
- </ClInclude>
- <ClInclude Include="sigscanning.h">
- <Filter>Header Files\Shared\Hooks</Filter>
- </ClInclude>
- <ClInclude Include="logging.h">
- <Filter>Header Files\Shared</Filter>
- </ClInclude>
- <ClInclude Include="sourceinterface.h">
- <Filter>Header Files\Shared</Filter>
- </ClInclude>
- <ClInclude Include="concommand.h">
- <Filter>Header Files\Shared\Convar</Filter>
- </ClInclude>
<ClInclude Include="include\spdlog\async.h">
<Filter>Header Files\include\spdlog</Filter>
</ClInclude>
@@ -453,12 +432,6 @@
<ClInclude Include="include\spdlog\details\windows_include.h">
<Filter>Header Files\include\spdlog\details</Filter>
</ClInclude>
- <ClInclude Include="convar.h">
- <Filter>Header Files\Shared\Convar</Filter>
- </ClInclude>
- <ClInclude Include="modmanager.h">
- <Filter>Header Files\Shared\Mods</Filter>
- </ClInclude>
<ClInclude Include="include\rapidjson\allocators.h">
<Filter>Header Files\include\rapidjson</Filter>
</ClInclude>
@@ -564,27 +537,12 @@
<ClInclude Include="include\rapidjson\msinttypes\stdint.h">
<Filter>Header Files\include\rapidjson\msinttypes</Filter>
</ClInclude>
- <ClInclude Include="scriptsrson.h">
- <Filter>Header Files\Shared\Mods\Compiled</Filter>
- </ClInclude>
<ClInclude Include="serverauthentication.h">
<Filter>Header Files\Server\Authentication</Filter>
</ClInclude>
<ClInclude Include="include\httplib.h">
<Filter>Header Files\include</Filter>
</ClInclude>
- <ClInclude Include="masterserver.h">
- <Filter>Header Files\Shared</Filter>
- </ClInclude>
- <ClInclude Include="misccommands.h">
- <Filter>Header Files\Shared\Convar</Filter>
- </ClInclude>
- <ClInclude Include="pdef.h">
- <Filter>Header Files\Shared\Mods\Compiled</Filter>
- </ClInclude>
- <ClInclude Include="memalloc.h">
- <Filter>Header Files\Shared</Filter>
- </ClInclude>
<ClInclude Include="include\openssl\__DECC_INCLUDE_EPILOGUE.H">
<Filter>Header Files\include\openssl\openssl</Filter>
</ClInclude>
@@ -1401,18 +1359,6 @@
<ClInclude Include="audio.h">
<Filter>Header Files\Client</Filter>
</ClInclude>
- <ClInclude Include="bitbuf.h">
- <Filter>Header Files\Shared</Filter>
- </ClInclude>
- <ClInclude Include="cvar.h">
- <Filter>Header Files\Shared\Convar</Filter>
- </ClInclude>
- <ClInclude Include="color.h">
- <Filter>Header Files\Shared\Math</Filter>
- </ClInclude>
- <ClInclude Include="bits.h">
- <Filter>Header Files\Shared\Math</Filter>
- </ClInclude>
<ClInclude Include="localchatwriter.h">
<Filter>Header Files\Client</Filter>
</ClInclude>
@@ -1422,106 +1368,136 @@
<ClInclude Include="plugin_abi.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="NSMem.h">
- <Filter>Source Files\Shared\Exploit Fixes</Filter>
- </ClInclude>
<ClInclude Include="version.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ns_version.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="playlist.h">
- <Filter>Header Files\Shared</Filter>
+ <ClInclude Include="serverchathooks.h">
+ <Filter>Header Files\Server\Scripted</Filter>
</ClInclude>
- <ClInclude Include="tier0.h">
- <Filter>Header Files\Shared\Game Functions</Filter>
+ <ClInclude Include="dedicated.h">
+ <Filter>Header Files\Dedicated Server</Filter>
+ </ClInclude>
+ <ClInclude Include="nsprefix.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="exploitfixes_utf8parser.cpp">
+ <Filter>Source Files\Exploit Fixes</Filter>
+ </ClInclude>
+ <ClInclude Include="crashhandler.h">
+ <Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="hoststate.h">
- <Filter>Header Files\Shared</Filter>
+ <Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="miscserverscript.h">
- <Filter>Header Files\Server\Scripted</Filter>
+ <ClInclude Include="masterserver.h">
+ <Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="serverchathooks.h">
- <Filter>Header Files\Server\Scripted</Filter>
+ <ClInclude Include="memalloc.h">
+ <Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="dedicated.h">
- <Filter>Header Files\Server\Dedicated</Filter>
+ <ClInclude Include="playlist.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="sourceinterface.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="squirrel.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="bits.h">
+ <Filter>Header Files\Math</Filter>
+ </ClInclude>
+ <ClInclude Include="bitbuf.h">
+ <Filter>Header Files\Math</Filter>
+ </ClInclude>
+ <ClInclude Include="convar.h">
+ <Filter>Header Files\Convar</Filter>
+ </ClInclude>
+ <ClInclude Include="concommand.h">
+ <Filter>Header Files\Convar</Filter>
+ </ClInclude>
+ <ClInclude Include="cvar.h">
+ <Filter>Header Files\Convar</Filter>
+ </ClInclude>
+ <ClInclude Include="filesystem.h">
+ <Filter>Header Files\Filesystem</Filter>
+ </ClInclude>
+ <ClInclude Include="hooks.h">
+ <Filter>Header Files\Hooks</Filter>
+ </ClInclude>
+ <ClInclude Include="limits.h">
+ <Filter>Header Files\Exploit Fixes</Filter>
+ </ClInclude>
+ <ClInclude Include="logging.h">
+ <Filter>Header Files\Console</Filter>
+ </ClInclude>
+ <ClInclude Include="misccommands.h">
+ <Filter>Header Files\Convar</Filter>
+ </ClInclude>
+ <ClInclude Include="modmanager.h">
+ <Filter>Header Files\Mods</Filter>
+ </ClInclude>
+ <ClInclude Include="pdef.h">
+ <Filter>Header Files\Mods\Compiled Assets</Filter>
</ClInclude>
<ClInclude Include="printcommand.h">
- <Filter>Header Files\Shared\Console</Filter>
+ <Filter>Header Files\Console</Filter>
</ClInclude>
<ClInclude Include="printmaps.h">
- <Filter>Header Files\Shared\Console</Filter>
+ <Filter>Header Files\Console</Filter>
+ </ClInclude>
+ <ClInclude Include="r2client.h">
+ <Filter>Header Files\Game Functions</Filter>
</ClInclude>
<ClInclude Include="r2engine.h">
- <Filter>Header Files\Shared\Game Functions</Filter>
+ <Filter>Header Files\Game Functions</Filter>
</ClInclude>
<ClInclude Include="r2server.h">
- <Filter>Header Files\Shared\Game Functions</Filter>
+ <Filter>Header Files\Game Functions</Filter>
</ClInclude>
- <ClInclude Include="r2client.h">
- <Filter>Header Files\Shared\Game Functions</Filter>
+ <ClInclude Include="scriptsrson.h">
+ <Filter>Header Files\Mods\Compiled Assets</Filter>
</ClInclude>
- <ClInclude Include="crashhandler.h">
- <Filter>Header Files\Shared</Filter>
+ <ClInclude Include="tier0.h">
+ <Filter>Header Files\Game Functions</Filter>
</ClInclude>
- <ClInclude Include="filesystem.h">
- <Filter>Header Files\Shared\Filesystem</Filter>
+ <ClInclude Include="sigscanning.h">
+ <Filter>Header Files\Hooks</Filter>
</ClInclude>
<ClInclude Include="rpakfilesystem.h">
- <Filter>Header Files\Shared\Filesystem</Filter>
+ <Filter>Header Files\Filesystem</Filter>
</ClInclude>
- <ClInclude Include="nsprefix.h">
- <Filter>Header Files</Filter>
+ <ClInclude Include="color.h">
+ <Filter>Header Files\Math</Filter>
</ClInclude>
- <ClInclude Include="ExploitFixes_UTF8Parser.h">
- <Filter>Source Files\Shared\Exploit Fixes</Filter>
+ <ClInclude Include="NSMem.h">
+ <Filter>Header Files\Hooks</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="pch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="hooks.cpp">
- <Filter>Source Files\Shared\Hooks</Filter>
- </ClCompile>
<ClCompile Include="dedicated.cpp">
- <Filter>Source Files\Server\Dedicated Server</Filter>
+ <Filter>Source Files\Dedicated Server</Filter>
</ClCompile>
<ClCompile Include="sourceconsole.cpp">
<Filter>Source Files\Client</Filter>
</ClCompile>
- <ClCompile Include="squirrel.cpp">
- <Filter>Source Files\Shared</Filter>
- </ClCompile>
- <ClCompile Include="sigscanning.cpp">
- <Filter>Source Files\Shared\Hooks</Filter>
- </ClCompile>
- <ClCompile Include="sourceinterface.cpp">
- <Filter>Source Files\Shared</Filter>
- </ClCompile>
- <ClCompile Include="convar.cpp">
- <Filter>Source Files\Shared\Convar</Filter>
- </ClCompile>
- <ClCompile Include="concommand.cpp">
- <Filter>Source Files\Shared\Convar</Filter>
- </ClCompile>
<ClCompile Include="modmanager.cpp">
- <Filter>Source Files\Shared\Mods</Filter>
+ <Filter>Source Files\Mods</Filter>
</ClCompile>
<ClCompile Include="scriptsrson.cpp">
- <Filter>Source Files\Shared\Mods\Compiled Assets</Filter>
+ <Filter>Source Files\Mods\Compiled Assets</Filter>
</ClCompile>
<ClCompile Include="serverauthentication.cpp">
<Filter>Source Files\Server\Authentication</Filter>
</ClCompile>
<ClCompile Include="keyvalues.cpp">
- <Filter>Source Files\Shared\Mods\Compiled Assets</Filter>
- </ClCompile>
- <ClCompile Include="masterserver.cpp">
- <Filter>Source Files\Shared</Filter>
+ <Filter>Source Files\Mods\Compiled Assets</Filter>
</ClCompile>
<ClCompile Include="chatcommand.cpp">
<Filter>Source Files\Client</Filter>
@@ -1530,26 +1506,17 @@
<Filter>Source Files\Client</Filter>
</ClCompile>
<ClCompile Include="dedicatedmaterialsystem.cpp">
- <Filter>Source Files\Server\Dedicated Server</Filter>
- </ClCompile>
- <ClCompile Include="misccommands.cpp">
- <Filter>Source Files\Shared\Convar</Filter>
+ <Filter>Source Files\Dedicated Server</Filter>
</ClCompile>
<ClCompile Include="pdef.cpp">
- <Filter>Source Files\Shared\Mods\Compiled Assets</Filter>
+ <Filter>Source Files\Mods\Compiled Assets</Filter>
</ClCompile>
<ClCompile Include="clientauthhooks.cpp">
<Filter>Source Files\Client</Filter>
</ClCompile>
- <ClCompile Include="memalloc.cpp">
- <Filter>Source Files\Shared</Filter>
- </ClCompile>
<ClCompile Include="miscclientfixes.cpp">
<Filter>Source Files\Client</Filter>
</ClCompile>
- <ClCompile Include="maxplayers.cpp">
- <Filter>Source Files\Shared</Filter>
- </ClCompile>
<ClCompile Include="miscserverfixes.cpp">
<Filter>Source Files\Server</Filter>
</ClCompile>
@@ -1568,12 +1535,6 @@
<ClCompile Include="buildainfile.cpp">
<Filter>Source Files\Server</Filter>
</ClCompile>
- <ClCompile Include="cvar.cpp">
- <Filter>Source Files\Shared\Convar</Filter>
- </ClCompile>
- <ClCompile Include="bits.cpp">
- <Filter>Source Files\Shared\Math</Filter>
- </ClCompile>
<ClCompile Include="localchatwriter.cpp">
<Filter>Source Files\Client</Filter>
</ClCompile>
@@ -1586,27 +1547,12 @@
<ClCompile Include="clientvideooverrides.cpp">
<Filter>Source Files\Client</Filter>
</ClCompile>
- <ClCompile Include="ExploitFixes.cpp">
- <Filter>Source Files\Shared\Exploit Fixes</Filter>
- </ClCompile>
<ClCompile Include="version.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="clientruihooks.cpp">
<Filter>Source Files\Client</Filter>
</ClCompile>
- <ClCompile Include="playlist.cpp">
- <Filter>Source Files\Shared</Filter>
- </ClCompile>
- <ClCompile Include="tier0.cpp">
- <Filter>Source Files\Shared\Game Functions</Filter>
- </ClCompile>
- <ClCompile Include="hoststate.cpp">
- <Filter>Source Files\Shared</Filter>
- </ClCompile>
- <ClCompile Include="host.cpp">
- <Filter>Source Files\Shared</Filter>
- </ClCompile>
<ClCompile Include="scriptmainmenupromos.cpp">
<Filter>Source Files\Client\Scripted</Filter>
</ClCompile>
@@ -1631,42 +1577,96 @@
<ClCompile Include="miscserverscript.cpp">
<Filter>Source Files\Server\Scripted</Filter>
</ClCompile>
- <ClCompile Include="printcommands.cpp">
- <Filter>Source Files\Shared\Console</Filter>
- </ClCompile>
<ClCompile Include="demofixes.cpp">
<Filter>Source Files\Client</Filter>
</ClCompile>
- <ClCompile Include="printmaps.cpp">
- <Filter>Source Files\Shared\Console</Filter>
- </ClCompile>
- <ClCompile Include="r2client.cpp">
- <Filter>Source Files\Shared\Game Functions</Filter>
+ <ClCompile Include="nsprefix.cpp">
+ <Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="r2server.cpp">
- <Filter>Source Files\Shared\Game Functions</Filter>
+ <ClCompile Include="dllmain.cpp">
+ <Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="r2engine.cpp">
- <Filter>Source Files\Shared\Game Functions</Filter>
+ <ClCompile Include="squirrel.cpp">
+ <Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="crashhandler.cpp">
- <Filter>Source Files\Shared</Filter>
+ <Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="logging.cpp">
- <Filter>Source Files\Shared\Console</Filter>
+ <ClCompile Include="host.cpp">
+ <Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="filesystem.cpp">
- <Filter>Source Files\Shared\Filesystem</Filter>
+ <ClCompile Include="hoststate.cpp">
+ <Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="rpakfilesystem.cpp">
- <Filter>Source Files\Shared\Filesystem</Filter>
+ <ClCompile Include="masterserver.cpp">
+ <Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="nsprefix.cpp">
+ <ClCompile Include="maxplayers.cpp">
<Filter>Source Files</Filter>
</ClCompile>
- <ClCompile Include="dllmain.cpp">
+ <ClCompile Include="memalloc.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="playlist.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="sourceinterface.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="r2server.cpp">
+ <Filter>Source Files\Game Functions</Filter>
+ </ClCompile>
+ <ClCompile Include="r2client.cpp">
+ <Filter>Source Files\Game Functions</Filter>
+ </ClCompile>
+ <ClCompile Include="r2engine.cpp">
+ <Filter>Source Files\Game Functions</Filter>
+ </ClCompile>
+ <ClCompile Include="rpakfilesystem.cpp">
+ <Filter>Source Files\Filesystem</Filter>
+ </ClCompile>
+ <ClCompile Include="filesystem.cpp">
+ <Filter>Source Files\Filesystem</Filter>
+ </ClCompile>
+ <ClCompile Include="exploitfixes.cpp">
+ <Filter>Source Files\Exploit Fixes</Filter>
+ </ClCompile>
+ <ClCompile Include="limits.cpp">
+ <Filter>Source Files\Exploit Fixes</Filter>
+ </ClCompile>
+ <ClCompile Include="hooks.cpp">
+ <Filter>Source Files\Hooks</Filter>
+ </ClCompile>
+ <ClCompile Include="sigscanning.cpp">
+ <Filter>Source Files\Hooks</Filter>
+ </ClCompile>
+ <ClCompile Include="bits.cpp">
+ <Filter>Source Files\Math</Filter>
+ </ClCompile>
+ <ClCompile Include="convar.cpp">
+ <Filter>Source Files\Convar</Filter>
+ </ClCompile>
+ <ClCompile Include="concommand.cpp">
+ <Filter>Source Files\Convar</Filter>
+ </ClCompile>
+ <ClCompile Include="printcommands.cpp">
+ <Filter>Source Files\Console</Filter>
+ </ClCompile>
+ <ClCompile Include="printmaps.cpp">
+ <Filter>Source Files\Console</Filter>
+ </ClCompile>
+ <ClCompile Include="cvar.cpp">
+ <Filter>Source Files\Convar</Filter>
+ </ClCompile>
+ <ClCompile Include="misccommands.cpp">
+ <Filter>Source Files\Convar</Filter>
+ </ClCompile>
+ <ClCompile Include="tier0.cpp">
+ <Filter>Source Files\Game Functions</Filter>
+ </ClCompile>
+ <ClCompile Include="logging.cpp">
+ <Filter>Source Files\Console</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<MASM Include="audio_asm.asm">
diff --git a/NorthstarDLL/audio.cpp b/NorthstarDLL/audio.cpp
index 629d9179..0aa5c9f0 100644
--- a/NorthstarDLL/audio.cpp
+++ b/NorthstarDLL/audio.cpp
@@ -315,6 +315,7 @@ void CustomAudioManager::ClearAudioOverrides()
{
// stop all miles sounds beforehand
// miles_stop_all
+
MilesStopAll();
// this is cancer but it works
@@ -498,5 +499,5 @@ ON_DLL_LOAD_CLIENT_RELIESON("client.dll", AudioHooks, ConVar, (HMODULE baseAddre
AUTOHOOK_DISPATCH()
Cvar_ns_print_played_sounds = new ConVar("ns_print_played_sounds", "0", FCVAR_NONE, "");
- MilesStopAll = (MilesStopAll_Type)((char*)GetModuleHandleA("mileswin64.dll") + 0x580850);
+ MilesStopAll = (MilesStopAll_Type)((char*)baseAddress + 0x580850);
} \ No newline at end of file
diff --git a/NorthstarDLL/bansystem.cpp b/NorthstarDLL/bansystem.cpp
index 2a277874..d1b58102 100644
--- a/NorthstarDLL/bansystem.cpp
+++ b/NorthstarDLL/bansystem.cpp
@@ -3,14 +3,15 @@
#include "bansystem.h"
#include "serverauthentication.h"
#include "concommand.h"
-#include "miscserverscript.h"
+#include "r2server.h"
+#include "r2engine.h"
#include "nsprefix.h"
#include <filesystem>
const char* BANLIST_PATH_SUFFIX = "/banlist.txt";
-ServerBanSystem* g_ServerBanSystem;
+ServerBanSystem* g_pServerBanSystem;
void ServerBanSystem::OpenBanlist()
{
@@ -71,11 +72,11 @@ void ConCommand_ban(const CCommand& args)
// assuming maxplayers 32
for (int i = 0; i < 32; i++)
{
- void* player = GetPlayerByIndex(i);
+ R2::CBasePlayer* player = R2::UTIL_PlayerByIndex(i);
- if (!strcmp((char*)player + 0x16, args.Arg(1)) || !strcmp((char*)player + 0xF500, args.Arg(1)))
+ if (!strcmp(player->m_Name, args.Arg(1)) || !strcmp(player->m_UID, args.Arg(1)))
{
- g_ServerBanSystem->BanUID(strtoll((char*)player + 0xF500, nullptr, 10));
+ g_pServerBanSystem->BanUID(strtoll((char*)player + 0xF500, nullptr, 10));
R2::CBaseClient__Disconnect(player, 1, "Banned from server");
break;
}
@@ -88,18 +89,18 @@ void ConCommand_unban(const CCommand& args)
return;
// assumedly the player being unbanned here wasn't already connected, so don't need to iterate over players or anything
- g_ServerBanSystem->UnbanUID(strtoll(args.Arg(1), nullptr, 10));
+ g_pServerBanSystem->UnbanUID(strtoll(args.Arg(1), nullptr, 10));
}
void ConCommand_clearbanlist(const CCommand& args)
{
- g_ServerBanSystem->ClearBanlist();
+ g_pServerBanSystem->ClearBanlist();
}
ON_DLL_LOAD_RELIESON("engine.dll", BanSystem, ConCommand, (HMODULE baseAddress))
{
- g_ServerBanSystem = new ServerBanSystem;
- g_ServerBanSystem->OpenBanlist();
+ g_pServerBanSystem = new ServerBanSystem;
+ g_pServerBanSystem->OpenBanlist();
RegisterConCommand("ban", ConCommand_ban, "bans a given player by uid or name", FCVAR_GAMEDLL);
RegisterConCommand("unban", ConCommand_unban, "unbans a given player by uid", FCVAR_NONE);
diff --git a/NorthstarDLL/bansystem.h b/NorthstarDLL/bansystem.h
index b4238982..0d21aaa5 100644
--- a/NorthstarDLL/bansystem.h
+++ b/NorthstarDLL/bansystem.h
@@ -15,4 +15,4 @@ class ServerBanSystem
bool IsUIDAllowed(uint64_t uid);
};
-extern ServerBanSystem* g_ServerBanSystem;
+extern ServerBanSystem* g_pServerBanSystem;
diff --git a/NorthstarDLL/buildainfile.cpp b/NorthstarDLL/buildainfile.cpp
index 6659677e..1ac73b43 100644
--- a/NorthstarDLL/buildainfile.cpp
+++ b/NorthstarDLL/buildainfile.cpp
@@ -16,6 +16,7 @@ const int AINET_SCRIPT_VERSION_NUMBER = 21;
const int PLACEHOLDER_CRC = 0;
const int MAX_HULLS = 5;
+#pragma pack(push, 1)
struct CAI_NodeLink
{
short srcId;
@@ -26,6 +27,7 @@ struct CAI_NodeLink
char unk2[5];
int64_t flags;
};
+#pragma pack(pop)
#pragma pack(push, 1)
struct CAI_NodeLinkDisk
@@ -35,7 +37,9 @@ struct CAI_NodeLinkDisk
char unk0;
bool hulls[MAX_HULLS];
};
+#pragma pack(pop)
+#pragma pack(push, 1)
struct CAI_Node
{
int index; // not present on disk
@@ -64,6 +68,7 @@ struct CAI_Node
char unk9[8]; // padding until next bit
char unk10[8]; // should match up to unk6 on disk
};
+#pragma pack(pop)
// the way CAI_Nodes are represented in on-disk ain files
#pragma pack(push, 1)
@@ -83,7 +88,9 @@ struct CAI_NodeDisk
short unk5;
char unk6[8];
}; // total size of 68 bytes
+#pragma pack(pop)
+#pragma pack(push, 1)
struct UnkNodeStruct0
{
int index;
@@ -108,10 +115,12 @@ struct UnkNodeStruct0
char pad4[132];
char unk5;
};
+#pragma pack(pop)
int* pUnkStruct0Count;
UnkNodeStruct0*** pppUnkNodeStruct0s;
+#pragma pack(push, 1)
struct UnkLinkStruct1
{
short unk0;
@@ -121,10 +130,12 @@ struct UnkLinkStruct1
char unk4;
char unk5;
};
+#pragma pack(pop)
int* pUnkLinkStruct1Count;
UnkLinkStruct1*** pppUnkStruct1s;
+#pragma pack(push, 1)
struct CAI_ScriptNode
{
float x;
@@ -132,7 +143,9 @@ struct CAI_ScriptNode
float z;
uint64_t scriptdata;
};
+#pragma pack(pop)
+#pragma pack(push, 1)
struct CAI_Network
{
// +0
@@ -162,6 +175,7 @@ struct CAI_Network
// +84176
CAI_Node** nodes;
};
+#pragma pack(pop)
char** pUnkServerMapversionGlobal;
diff --git a/NorthstarDLL/clientauthhooks.cpp b/NorthstarDLL/clientauthhooks.cpp
index 2ddee855..3ba66d6f 100644
--- a/NorthstarDLL/clientauthhooks.cpp
+++ b/NorthstarDLL/clientauthhooks.cpp
@@ -17,12 +17,12 @@ void,, (void* a1))
{
// game will call this forever, until it gets a valid auth key
// so, we need to manually invalidate our key until we're authed with northstar, then we'll allow game to auth with stryder
- if (!g_MasterServerManager->m_bOriginAuthWithMasterServerDone && Cvar_ns_has_agreed_to_send_token->GetInt() != DISAGREED_TO_SEND_TOKEN)
+ if (!g_pMasterServerManager->m_bOriginAuthWithMasterServerDone && Cvar_ns_has_agreed_to_send_token->GetInt() != DISAGREED_TO_SEND_TOKEN)
{
// if player has agreed to send token and we aren't already authing, try to auth
if (Cvar_ns_has_agreed_to_send_token->GetInt() == AGREED_TO_SEND_TOKEN &&
- !g_MasterServerManager->m_bOriginAuthWithMasterServerInProgress)
- g_MasterServerManager->AuthenticateOriginWithMasterServer(R2::g_pLocalPlayerUserID, R2::g_pLocalPlayerOriginToken);
+ !g_pMasterServerManager->m_bOriginAuthWithMasterServerInProgress)
+ g_pMasterServerManager->AuthenticateOriginWithMasterServer(R2::g_pLocalPlayerUserID, R2::g_pLocalPlayerOriginToken);
// invalidate key so auth will fail
*R2::g_pLocalPlayerOriginToken = 0;
diff --git a/NorthstarDLL/clientchathooks.cpp b/NorthstarDLL/clientchathooks.cpp
index 8e1f7c77..ca783f88 100644
--- a/NorthstarDLL/clientchathooks.cpp
+++ b/NorthstarDLL/clientchathooks.cpp
@@ -12,9 +12,7 @@ void,, (void* self, const char* message, int inboxId, bool isTeam, bool isDead))
{
// This hook is called for each HUD, but we only want our logic to run once.
if (self != *CHudChat::allHuds)
- {
return;
- }
if (g_pClientSquirrel->setupfunc("CHudChat_ProcessMessageStartThread") != SQRESULT_ERROR)
{
@@ -31,7 +29,7 @@ void,, (void* self, const char* message, int inboxId, bool isTeam, bool isDead))
payload = message + 1;
}
- g_pClientSquirrel->pushinteger(g_pClientSquirrel->sqvm2, (int) senderId - 1);
+ g_pClientSquirrel->pushinteger(g_pClientSquirrel->sqvm2, (int)senderId - 1);
g_pClientSquirrel->pushstring(g_pClientSquirrel->sqvm2, payload);
g_pClientSquirrel->pushbool(g_pClientSquirrel->sqvm2, isTeam);
g_pClientSquirrel->pushbool(g_pClientSquirrel->sqvm2, isDead);
@@ -39,42 +37,38 @@ void,, (void* self, const char* message, int inboxId, bool isTeam, bool isDead))
g_pClientSquirrel->call(g_pClientSquirrel->sqvm2, 5);
}
else
- {
for (CHudChat* hud = *CHudChat::allHuds; hud != NULL; hud = hud->next)
- {
CHudChat__AddGameLine(hud, message, inboxId, isTeam, isDead);
- }
- }
}
// void NSChatWrite( int context, string str )
-static SQRESULT SQ_ChatWrite(void* sqvm)
+SQRESULT SQ_ChatWrite(void* sqvm)
{
- int context = g_pClientSquirrel->getinteger(g_pClientSquirrel->sqvm2, 1);
- const char* str = g_pClientSquirrel->getstring(g_pClientSquirrel->sqvm2, 2);
+ int context = g_pClientSquirrel->getinteger(sqvm, 1);
+ const char* str = g_pClientSquirrel->getstring(sqvm, 2);
LocalChatWriter((LocalChatWriter::Context)context).Write(str);
- return SQRESULT_NOTNULL;
+ return SQRESULT_NULL;
}
// void NSChatWriteRaw( int context, string str )
-static SQRESULT SQ_ChatWriteRaw(void* sqvm)
+SQRESULT SQ_ChatWriteRaw(void* sqvm)
{
- int context = g_pClientSquirrel->getinteger(g_pClientSquirrel->sqvm2, 1);
- const char* str = g_pClientSquirrel->getstring(g_pClientSquirrel->sqvm2, 2);
+ int context = g_pClientSquirrel->getinteger(sqvm, 1);
+ const char* str = g_pClientSquirrel->getstring(sqvm, 2);
LocalChatWriter((LocalChatWriter::Context)context).InsertText(str);
- return SQRESULT_NOTNULL;
+ return SQRESULT_NULL;
}
// void NSChatWriteLine( int context, string str )
-static SQRESULT SQ_ChatWriteLine(void* sqvm)
+SQRESULT SQ_ChatWriteLine(void* sqvm)
{
- int context = g_pClientSquirrel->getinteger(g_pClientSquirrel->sqvm2, 1);
- const char* str = g_pClientSquirrel->getstring(g_pClientSquirrel->sqvm2, 2);
+ int context = g_pClientSquirrel->getinteger(sqvm, 1);
+ const char* str = g_pClientSquirrel->getstring(sqvm, 2);
LocalChatWriter((LocalChatWriter::Context)context).WriteLine(str);
- return SQRESULT_NOTNULL;
+ return SQRESULT_NULL;
}
ON_DLL_LOAD_CLIENT_RELIESON("client.dll", ClientChatHooks, ClientSquirrel, (HMODULE baseAddress))
diff --git a/NorthstarDLL/dedicated.cpp b/NorthstarDLL/dedicated.cpp
index cf0d68f1..cbaed442 100644
--- a/NorthstarDLL/dedicated.cpp
+++ b/NorthstarDLL/dedicated.cpp
@@ -81,9 +81,9 @@ void RunServer(CDedicatedExports* dedicated)
SetConsoleTitleA(fmt::format(
"{} - {} {}/{} players ({})",
- g_MasterServerManager->m_sUnicodeServerName,
+ g_pMasterServerManager->m_sUnicodeServerName,
g_pHostState->m_levelName,
- g_pServerAuthenticationManager->m_additionalPlayerData.size(),
+ g_pServerAuthentication->m_PlayerAuthenticationData.size(),
maxPlayers,
GetCurrentPlaylistName())
.c_str());
diff --git a/NorthstarDLL/ExploitFixes.cpp b/NorthstarDLL/exploitfixes.cpp
index b347310c..fbe91e3b 100644
--- a/NorthstarDLL/ExploitFixes.cpp
+++ b/NorthstarDLL/exploitfixes.cpp
@@ -1,9 +1,11 @@
#include "pch.h"
-
-#include "ExploitFixes_UTF8Parser.h"
#include "NSMem.h"
#include "cvar.h"
+#include "limits.h"
+#include "dedicated.h"
#include "tier0.h"
+#include "r2engine.h"
+#include "r2client.h"
AUTOHOOK_INIT()
@@ -71,7 +73,7 @@ bool, __fastcall, (void* thisptr, void* buffer)) // 48 89 5C 24 ? 48 89 6C 24 ?
return false;
}
-// This is unused ingame and a big client=>client exploit vector
+// This is unused ingame and a big client=>server=>client exploit vector
AUTOHOOK(Base_CmdKeyValues_ReadFromBuffer, engine.dll + 0x220040,
bool, __fastcall, (void* thisptr, void* buffer)) // 40 55 48 81 EC ? ? ? ? 48 8D 6C 24 ? 48 89 5D 70
{
@@ -326,39 +328,85 @@ bool, __fastcall, (const char* pModName)) // 48 83 EC 28 48 8B 0D ? ? ? ? 48 8D
&& !Tier0::CommandLine()->CheckParm("-norestrictservercommands");
}
-// prevent utf8 parser from crashing when provided bad data, which can be sent through user-controlled openinvites
-AUTOHOOK(Rson_ParseUTF8, engine.dll + 0xEF670,
-bool, __fastcall, (INT64 * a1, DWORD* a2, char* strData)) // 48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 41 54 41 55 41 56 41 57 48 83 EC 20 8B 1A
+// ratelimit stringcmds, and prevent remote clients from calling non-FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS commands
+bool (*CCommand__Tokenize)(CCommand& self, const char* pCommandString, R2::cmd_source_t commandSource);
+AUTOHOOK(CGameClient__ExecuteStringCommand,
+engine.dll + 0x1022E0, bool, , (R2::CBasePlayer* self, uint32_t unknown, const char* pCommandString))
{
- static void* targetRetAddr = NSMem::PatternScan("engine.dll", "84 C0 75 2C 49 8B 16");
+ if (!g_pServerLimits->CheckStringCommandLimits(self))
+ {
+ R2::CBaseClient__Disconnect(self, 1, "Sent too many stringcmd commands");
+ return false;
+ }
+
+ // verify the command we're trying to execute is FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS, if it's a concommand
+ char* commandBuf[1040]; // assumedly this is the size of CCommand since we don't have an actual constructor
+ memset(commandBuf, 0, sizeof(commandBuf));
+ CCommand tempCommand = *(CCommand*)&commandBuf;
+
+ if (!CCommand__Tokenize(tempCommand, pCommandString, R2::cmd_source_t::kCommandSrcCode) || !tempCommand.ArgC())
+ return false;
+
+ ConCommand* command = R2::g_pCVar->FindCommand(tempCommand.Arg(0));
- // only call if we're parsing utf8 data from the network (i.e. communities), otherwise we get perf issues
- if (_ReturnAddress() == targetRetAddr)
+ // if the command doesn't exist pass it on to ExecuteStringCommand for script clientcommands and stuff
+ if (command && !command->IsFlagSet(FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS))
{
- if (!ExploitFixes_UTF8Parser::CheckValid(a1, a2, strData))
- {
- const char* BLOCK_PREFIX = "ParseUTF8 Hook: ";
- BLOCKED_INFO("Ignoring potentially-crashing utf8 string");
+ // ensure FCVAR_GAMEDLL concommands without FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS can't be executed by remote clients
+ if (IsDedicatedServer())
+ return false;
+
+ if (strcmp(self->m_UID, R2::g_pLocalPlayerUserID))
return false;
- }
}
- return Rson_ParseUTF8(a1, a2, strData);
+ return CGameClient__ExecuteStringCommand(self, unknown, pCommandString);
+}
+
+// prevent clients from crashing servers through overflowing CNetworkStringTableContainer::WriteBaselines
+bool bWasWritingStringTableSuccessful;
+AUTOHOOK(CBaseClient__SendServerInfo,
+engine.dll + 0x104FB0, void, , (void* self))
+{
+ bWasWritingStringTableSuccessful = true;
+ CBaseClient__SendServerInfo(self);
+ if (!bWasWritingStringTableSuccessful)
+ R2::CBaseClient__Disconnect(
+ self, 1, "Overflowed CNetworkStringTableContainer::WriteBaselines, try restarting your client and reconnecting");
}
ON_DLL_LOAD("engine.dll", EngineExploitFixes, (HMODULE baseAddress))
{
AUTOHOOK_DISPATCH_MODULE(engine.dll)
+ CCommand__Tokenize = (bool(*)(CCommand&, const char*, R2::cmd_source_t))((char*)baseAddress + 0x418380);
+
// allow client/ui to run clientcommands despite restricting servercommands
NSMem::BytePatch((uintptr_t)baseAddress + 0x4FB65, "EB 11");
NSMem::BytePatch((uintptr_t)baseAddress + 0x4FBAC, "EB 16");
+
+ // patch to set bWasWritingStringTableSuccessful in CNetworkStringTableContainer::WriteBaselines if it fails
+ {
+ uintptr_t writeAddress = (uintptr_t)(&bWasWritingStringTableSuccessful - ((uintptr_t)baseAddress + 0x234EDC));
+
+ auto addr = (uintptr_t)baseAddress + 0x234ED2;
+ NSMem::BytePatch(addr, "C7 05");
+ NSMem::BytePatch(addr + 2, (BYTE*)&writeAddress, sizeof(writeAddress));
+
+ NSMem::BytePatch(addr + 6, "00 00 00 00");
+
+ NSMem::NOP(addr + 10, 5);
+ }
}
ON_DLL_LOAD_RELIESON("server.dll", ServerExploitFixes, ConVar, (HMODULE baseAddress))
{
AUTOHOOK_DISPATCH_MODULE(server.dll)
+ // ret at the start of CServerGameClients::ClientCommandKeyValues as it has no benefit and is forwarded to client (i.e. security issue)
+ // this prevents the attack vector of client=>server=>client, however server=>client also has clientside patches
+ NSMem::BytePatch((uintptr_t)baseAddress + 0x153920, "C3");
+
// Dumb ANTITAMPER patches (they negatively impact performance and security)
constexpr const char* ANTITAMPER_EXPORTS[] = {
"ANTITAMPER_SPOTCHECK_CODEMARKER",
diff --git a/NorthstarDLL/exploitfixes_utf8parser.cpp b/NorthstarDLL/exploitfixes_utf8parser.cpp
new file mode 100644
index 00000000..5627c3e3
--- /dev/null
+++ b/NorthstarDLL/exploitfixes_utf8parser.cpp
@@ -0,0 +1,190 @@
+#include "pch.h"
+#include "NSMem.h"
+
+AUTOHOOK_INIT()
+
+// Reimplementation of an exploitable UTF decoding function in titanfall
+bool __fastcall CheckUTF8Valid(INT64* a1, DWORD* a2, char* strData)
+{
+ static auto sub_F1320 = (INT64(__fastcall*)(DWORD a1, char* a2))NSMem::PatternScan("engine.dll", "83 F9 7F 77 08 88 0A");
+
+ DWORD v3; // eax
+ char* v4; // rbx
+ char v5; // si
+ char* _strData; // rdi
+ char* v7; // rbp
+ char v11; // al
+ DWORD v12; // er9
+ DWORD v13; // ecx
+ DWORD v14; // edx
+ DWORD v15; // er8
+ int v16; // eax
+ DWORD v17; // er9
+ int v18; // eax
+ DWORD v19; // er9
+ DWORD v20; // ecx
+ int v21; // eax
+ int v22; // er9
+ DWORD v23; // edx
+ int v24; // eax
+ int v25; // er9
+ DWORD v26; // er9
+ DWORD v27; // er10
+ DWORD v28; // ecx
+ DWORD v29; // edx
+ DWORD v30; // er8
+ int v31; // eax
+ DWORD v32; // er10
+ int v33; // eax
+ DWORD v34; // er10
+ DWORD v35; // ecx
+ int v36; // eax
+ int v37; // er10
+ DWORD v38; // edx
+ int v39; // eax
+ int v40; // er10
+ DWORD v41; // er10
+ INT64 v43; // r8
+ INT64 v44; // rdx
+ INT64 v45; // rcx
+ INT64 v46; // rax
+ INT64 v47; // rax
+ char v48; // al
+ INT64 v49; // r8
+ INT64 v50; // rdx
+ INT64 v51; // rcx
+ INT64 v52; // rax
+ INT64 v53; // rax
+
+ v3 = a2[2];
+ v4 = (char*)(a1[1] + *a2);
+ v5 = 0;
+ _strData = strData;
+ v7 = &v4[*((UINT16*)a2 + 2)];
+ if (v3 >= 2)
+ {
+ ++v4;
+ --v7;
+ if (v3 != 2)
+ {
+ while (1)
+ {
+
+ if (!NSMem::IsMemoryReadable(v4, 1))
+ return false; // INVALID
+
+ v11 = *v4++; // crash potential
+ if (v11 != 92)
+ goto LABEL_6;
+ v11 = *v4++;
+ if (v11 == 110)
+ break;
+ switch (v11)
+ {
+ case 't':
+ v11 = 9;
+ goto LABEL_6;
+ case 'r':
+ v11 = 13;
+ goto LABEL_6;
+ case 'b':
+ v11 = 8;
+ goto LABEL_6;
+ case 'f':
+ v11 = 12;
+ goto LABEL_6;
+ }
+ if (v11 != 117)
+ goto LABEL_6;
+ v12 = *v4 | 0x20;
+ v13 = v4[1] | 0x20;
+ v14 = v4[2] | 0x20;
+ v15 = v4[3] | 0x20;
+ v16 = 87;
+ if (v12 <= 0x39)
+ v16 = 48;
+ v17 = v12 - v16;
+ v18 = 87;
+ v19 = v17 << 12;
+ if (v13 <= 0x39)
+ v18 = 48;
+ v20 = v13 - v18;
+ v21 = 87;
+ v22 = (v20 << 8) | v19;
+ if (v14 <= 0x39)
+ v21 = 48;
+ v23 = v14 - v21;
+ v24 = 87;
+ v25 = (16 * v23) | v22;
+ if (v15 <= 0x39)
+ v24 = 48;
+ v4 += 4;
+ v26 = (v15 - v24) | v25;
+ if (v26 - 55296 <= 0x7FF)
+ {
+ if (v26 >= 0xDC00)
+ return true;
+ if (*v4 != 92 || v4[1] != 117)
+ return true;
+
+ v27 = v4[2] | 0x20;
+ v28 = v4[3] | 0x20;
+ v29 = v4[4] | 0x20;
+ v30 = v4[5] | 0x20;
+ v31 = 87;
+ if (v27 <= 0x39)
+ v31 = 48;
+ v32 = v27 - v31;
+ v33 = 87;
+ v34 = v32 << 12;
+ if (v28 <= 0x39)
+ v33 = 48;
+ v35 = v28 - v33;
+ v36 = 87;
+ v37 = (v35 << 8) | v34;
+ if (v29 <= 0x39)
+ v36 = 48;
+ v38 = v29 - v36;
+ v39 = 87;
+ v40 = (16 * v38) | v37;
+ if (v30 <= 0x39)
+ v39 = 48;
+ v4 += 6;
+ v41 = ((v30 - v39) | v40) - 56320;
+ if (v41 > 0x3FF)
+ return true;
+ v26 = v41 | ((v26 - 55296) << 10);
+ }
+ _strData += (DWORD)sub_F1320(v26, _strData);
+ LABEL_7:
+ if (v4 == v7)
+ goto LABEL_48;
+ }
+ v11 = 10;
+ LABEL_6:
+ v5 |= v11;
+ *_strData++ = v11;
+ goto LABEL_7;
+ }
+ }
+LABEL_48:
+ return true;
+}
+
+// prevent utf8 parser from crashing when provided bad data, which can be sent through user-controlled openinvites
+AUTOHOOK(Rson_ParseUTF8, engine.dll + 0xEF670,
+bool, __fastcall, (INT64 * a1, DWORD* a2, char* strData)) // 48 89 5C 24 ? 48 89 6C 24 ? 48 89 74 24 ? 57 41 54 41 55 41 56 41 57 48 83 EC 20 8B 1A
+{
+ static void* targetRetAddr = NSMem::PatternScan("engine.dll", "84 C0 75 2C 49 8B 16");
+
+ // only call if we're parsing utf8 data from the network (i.e. communities), otherwise we get perf issues
+ if (_ReturnAddress() == targetRetAddr && !CheckUTF8Valid(a1, a2, strData))
+ return false;
+
+ return Rson_ParseUTF8(a1, a2, strData);
+}
+
+ON_DLL_LOAD("engine.dll", EngineExploitFixes_UTF8Parser, (HMODULE baseAddress))
+{
+ AUTOHOOK_DISPATCH()
+} \ No newline at end of file
diff --git a/NorthstarDLL/hoststate.cpp b/NorthstarDLL/hoststate.cpp
index 248f7259..aabfbe7b 100644
--- a/NorthstarDLL/hoststate.cpp
+++ b/NorthstarDLL/hoststate.cpp
@@ -25,7 +25,7 @@ void,, (CHostState* hostState))
Cbuf_Execute();
// need to do this to ensure we don't go to private match
- if (g_pServerAuthenticationManager->m_bNeedLocalAuthForNewgame)
+ if (g_pServerAuthentication->m_bNeedLocalAuthForNewgame)
SetCurrentPlaylist("tdm");
// net_data_block_enabled is required for sp, force it if we're on an sp map
@@ -45,17 +45,17 @@ void,, (CHostState* hostState))
// Copy new server name cvar to source
Cvar_hostname->SetValue(Cvar_ns_server_name->GetString());
- g_MasterServerManager->AddSelfToServerList(
+ g_pMasterServerManager->AddSelfToServerList(
Cvar_hostport->GetInt(),
- Cvar_ns_player_auth_port->GetInt(),
+ g_pServerAuthentication->Cvar_ns_player_auth_port->GetInt(),
Cvar_ns_server_name->GetString(),
Cvar_ns_server_desc->GetString(),
hostState->m_levelName,
GetCurrentPlaylistName(),
maxPlayers,
Cvar_ns_server_password->GetString());
- g_pServerAuthenticationManager->StartPlayerAuthServer();
- g_pServerAuthenticationManager->m_bNeedLocalAuthForNewgame = false;
+ g_pServerAuthentication->StartPlayerAuthServer();
+ g_pServerAuthentication->m_bNeedLocalAuthForNewgame = false;
}
AUTOHOOK(CHostState__State_ChangeLevelMP, engine.dll + 0x16E520,
@@ -73,7 +73,7 @@ void,, (CHostState* hostState))
if (!strncmp(g_pHostState->m_levelName, "sp_", 3))
g_pCVar->FindVar("net_data_block_enabled")->SetValue(true);
- g_MasterServerManager->UpdateServerMapAndPlaylist(hostState->m_levelName, GetCurrentPlaylistName(), maxPlayers);
+ g_pMasterServerManager->UpdateServerMapAndPlaylist(hostState->m_levelName, GetCurrentPlaylistName(), maxPlayers);
double dStartTime = Tier0::Plat_FloatTime();
CHostState__State_ChangeLevelMP(hostState);
@@ -85,8 +85,8 @@ void,, (CHostState* hostState))
{
spdlog::info("HostState: GameShutdown");
- g_MasterServerManager->RemoveSelfFromServerList();
- g_pServerAuthenticationManager->StopPlayerAuthServer();
+ g_pMasterServerManager->RemoveSelfFromServerList();
+ g_pServerAuthentication->StopPlayerAuthServer();
CHostState__State_GameShutdown(hostState);
}
diff --git a/NorthstarDLL/limits.cpp b/NorthstarDLL/limits.cpp
new file mode 100644
index 00000000..051ed8f8
--- /dev/null
+++ b/NorthstarDLL/limits.cpp
@@ -0,0 +1,185 @@
+#include "pch.h"
+#include "limits.h"
+#include "hoststate.h"
+#include "r2client.h"
+#include "r2engine.h"
+#include "tier0.h"
+#include "serverauthentication.h"
+
+AUTOHOOK_INIT()
+
+ServerLimitsManager* g_pServerLimits;
+
+ConVar* Cvar_net_datablock_enabled;
+
+void ServerLimitsManager::AddPlayer(R2::CBasePlayer* player)
+{
+ PlayerLimitData limitData;
+ m_PlayerLimitData.insert(std::make_pair(player, limitData));
+}
+
+bool ServerLimitsManager::CheckStringCommandLimits(R2::CBasePlayer* player)
+{
+ if (CVar_sv_quota_stringcmdspersecond->GetInt() != -1)
+ {
+ // note: this isn't super perfect, legit clients can trigger it in lobby if they try, mostly good enough tho imo
+ if (Tier0::Plat_FloatTime() - m_PlayerLimitData[player].lastClientCommandQuotaStart >= 1.0)
+ {
+ // reset quota
+ m_PlayerLimitData[player].lastClientCommandQuotaStart = Tier0::Plat_FloatTime();
+ m_PlayerLimitData[player].numClientCommandsInQuota = 0;
+ }
+
+ m_PlayerLimitData[player].numClientCommandsInQuota++;
+ if (m_PlayerLimitData[player].numClientCommandsInQuota >
+ CVar_sv_quota_stringcmdspersecond->GetInt())
+ {
+ // too many stringcmds, dc player
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool ServerLimitsManager::CheckChatLimits(R2::CBasePlayer* player)
+{
+ if (Tier0::Plat_FloatTime() - m_PlayerLimitData[player].lastSayTextLimitStart >= 1.0)
+ {
+ m_PlayerLimitData[player].lastSayTextLimitStart = Tier0::Plat_FloatTime();
+ m_PlayerLimitData[player].sayTextLimitCount = 0;
+ }
+
+ if (m_PlayerLimitData[player].sayTextLimitCount >= Cvar_sv_max_chat_messages_per_sec->GetInt())
+ return false;
+
+ m_PlayerLimitData[player].sayTextLimitCount++;
+ return true;
+}
+
+AUTOHOOK(CNetChan__ProcessMessages, engine.dll + 0x2140A0, char, __fastcall, (void* self, void* buf))
+{
+ enum eNetChanLimitMode
+ {
+ NETCHANLIMIT_WARN,
+ NETCHANLIMIT_KICK
+ };
+
+ double startTime = Tier0::Plat_FloatTime();
+ char ret = CNetChan__ProcessMessages(self, buf);
+
+ // check processing limits, unless we're in a level transition
+ if (R2::g_pHostState->m_iCurrentState == R2::HostState_t::HS_RUN && Tier0::ThreadInServerFrameThread())
+ {
+ // player that sent the message
+ R2::CBasePlayer* sender = *(R2::CBasePlayer**)((char*)self + 368);
+
+ // if no sender, return
+ // relatively certain this is fine?
+ if (!sender || !g_pServerLimits->m_PlayerLimitData.count(sender))
+ return ret;
+
+ // reset every second
+ if (startTime - g_pServerLimits->m_PlayerLimitData[sender].lastNetChanProcessingLimitStart >= 1.0 ||
+ g_pServerLimits->m_PlayerLimitData[sender].lastNetChanProcessingLimitStart == -1.0)
+ {
+ g_pServerLimits->m_PlayerLimitData[sender].lastNetChanProcessingLimitStart = startTime;
+ g_pServerLimits->m_PlayerLimitData[sender].netChanProcessingLimitTime = 0.0;
+ }
+ g_pServerLimits->m_PlayerLimitData[sender].netChanProcessingLimitTime +=
+ (Tier0::Plat_FloatTime() * 1000) - (startTime * 1000);
+
+ if (g_pServerLimits->m_PlayerLimitData[sender].netChanProcessingLimitTime >=
+ g_pServerLimits->Cvar_net_chan_limit_msec_per_sec->GetInt())
+ {
+ spdlog::warn(
+ "Client {} hit netchan processing limit with {}ms of processing time this second (max is {})",
+ (char*)sender + 0x16,
+ g_pServerLimits->m_PlayerLimitData[sender].netChanProcessingLimitTime,
+ g_pServerLimits->Cvar_net_chan_limit_msec_per_sec->GetInt());
+
+ // never kick local player
+ if (g_pServerLimits->Cvar_net_chan_limit_mode->GetInt() != NETCHANLIMIT_WARN &&
+ strcmp(R2::g_pLocalPlayerUserID, sender->m_UID))
+ {
+ R2::CBaseClient__Disconnect(sender, 1, "Exceeded net channel processing limit");
+ return false;
+ }
+ }
+ }
+
+ return ret;
+}
+
+AUTOHOOK(ProcessConnectionlessPacket, engine.dll + 0x117800, bool, , (void* a1, R2::netpacket_t* packet))
+{
+ if (packet->adr.type == R2::NA_IP &&
+ (!(packet->data[4] == 'N' && Cvar_net_datablock_enabled->GetBool()) || !Cvar_net_datablock_enabled->GetBool()))
+ {
+ // bad lookup: optimise later tm
+ UnconnectedPlayerLimitData* sendData = nullptr;
+ for (UnconnectedPlayerLimitData& foundSendData : g_pServerLimits->m_UnconnectedPlayerLimitData)
+ {
+ if (!memcmp(packet->adr.ip, foundSendData.ip, 16))
+ {
+ sendData = &foundSendData;
+ break;
+ }
+ }
+
+ if (!sendData)
+ {
+ sendData = &g_pServerLimits->m_UnconnectedPlayerLimitData.emplace_back();
+ memcpy(sendData->ip, packet->adr.ip, 16);
+ }
+
+ if (Tier0::Plat_FloatTime() < sendData->timeoutEnd)
+ return false;
+
+ if (Tier0::Plat_FloatTime() - sendData->lastQuotaStart >= 1.0)
+ {
+ sendData->lastQuotaStart = Tier0::Plat_FloatTime();
+ sendData->packetCount = 0;
+ }
+
+ sendData->packetCount++;
+
+ if (sendData->packetCount >= g_pServerLimits->Cvar_sv_querylimit_per_sec->GetInt())
+ {
+ spdlog::warn(
+ "Client went over connectionless ratelimit of {} per sec with packet of type {}",
+ g_pServerLimits->Cvar_sv_querylimit_per_sec->GetInt(),
+ packet->data[4]);
+
+ // timeout for a minute
+ sendData->timeoutEnd = Tier0::Plat_FloatTime() + 60.0;
+ return false;
+ }
+ }
+
+ return ProcessConnectionlessPacket(a1, packet);
+}
+
+ON_DLL_LOAD_RELIESON("engine.dll", ServerLimits, ConVar, (HMODULE baseAddress))
+{
+ AUTOHOOK_DISPATCH()
+
+ g_pServerLimits = new ServerLimitsManager;
+
+ g_pServerLimits->CVar_sv_quota_stringcmdspersecond = new ConVar(
+ "sv_quota_stringcmdspersecond",
+ "60",
+ FCVAR_GAMEDLL,
+ "How many string commands per second clients are allowed to submit, 0 to disallow all string commands, -1 to disable");
+ g_pServerLimits->Cvar_net_chan_limit_mode =
+ new ConVar("net_chan_limit_mode", "0", FCVAR_GAMEDLL, "The mode for netchan processing limits: 0 = warn, 1 = kick");
+ g_pServerLimits->Cvar_net_chan_limit_msec_per_sec = new ConVar(
+ "net_chan_limit_msec_per_sec",
+ "0",
+ FCVAR_GAMEDLL,
+ "Netchannel processing is limited to so many milliseconds, abort connection if exceeding budget");
+ g_pServerLimits->Cvar_sv_querylimit_per_sec = new ConVar("sv_querylimit_per_sec", "15", FCVAR_GAMEDLL, "");
+ g_pServerLimits->Cvar_sv_max_chat_messages_per_sec = new ConVar("sv_max_chat_messages_per_sec", "5", FCVAR_GAMEDLL, "");
+
+ Cvar_net_datablock_enabled = R2::g_pCVar->FindVar("net_datablock_enabled");
+} \ No newline at end of file
diff --git a/NorthstarDLL/limits.h b/NorthstarDLL/limits.h
new file mode 100644
index 00000000..2303ba5e
--- /dev/null
+++ b/NorthstarDLL/limits.h
@@ -0,0 +1,44 @@
+#pragma once
+#include "r2server.h"
+#include "convar.h"
+#include <unordered_map>
+
+struct PlayerLimitData
+{
+ double lastClientCommandQuotaStart = -1.0;
+ int numClientCommandsInQuota = 0;
+
+ double lastNetChanProcessingLimitStart = -1.0;
+ double netChanProcessingLimitTime = 0.0;
+
+ double lastSayTextLimitStart = -1.0;
+ int sayTextLimitCount = 0;
+};
+
+struct UnconnectedPlayerLimitData
+{
+ char ip[16];
+ double lastQuotaStart = 0.0;
+ int packetCount = 0;
+ double timeoutEnd = -1.0;
+};
+
+class ServerLimitsManager
+{
+ public:
+ ConVar* CVar_sv_quota_stringcmdspersecond;
+ ConVar* Cvar_net_chan_limit_mode;
+ ConVar* Cvar_net_chan_limit_msec_per_sec;
+ ConVar* Cvar_sv_querylimit_per_sec;
+ ConVar* Cvar_sv_max_chat_messages_per_sec;
+
+ std::unordered_map<R2::CBasePlayer*, PlayerLimitData> m_PlayerLimitData;
+ std::vector<UnconnectedPlayerLimitData> m_UnconnectedPlayerLimitData;
+
+ public:
+ void AddPlayer(R2::CBasePlayer* player);
+ bool CheckStringCommandLimits(R2::CBasePlayer* player);
+ bool CheckChatLimits(R2::CBasePlayer* player);
+};
+
+extern ServerLimitsManager* g_pServerLimits;
diff --git a/NorthstarDLL/localchatwriter.cpp b/NorthstarDLL/localchatwriter.cpp
index 42c72373..7f5e2a0a 100644
--- a/NorthstarDLL/localchatwriter.cpp
+++ b/NorthstarDLL/localchatwriter.cpp
@@ -37,12 +37,12 @@ class vgui_BaseRichText_vtable
void(__fastcall* SetVerticalScrollbar)(vgui_BaseRichText* self, bool state);
void(__fastcall* SetMaximumCharCount)(vgui_BaseRichText* self, int maxChars);
- void(__fastcall* InsertColorChange)(vgui_BaseRichText* self, vgui_Color col);
+ void(__fastcall* InsertColorChange)(vgui_BaseRichText* self, Color col);
void(__fastcall* InsertIndentChange)(vgui_BaseRichText* self, int pixelsIndent);
void(__fastcall* InsertClickableTextStart)(vgui_BaseRichText* self, const char* pchClickAction);
void(__fastcall* InsertClickableTextEnd)(vgui_BaseRichText* self);
void(__fastcall* InsertPossibleURLString)(
- vgui_BaseRichText* self, const char* text, vgui_Color URLTextColor, vgui_Color normalTextColor);
+ vgui_BaseRichText* self, const char* text, Color URLTextColor, Color normalTextColor);
void(__fastcall* InsertFade)(vgui_BaseRichText* self, float flSustain, float flLength);
void(__fastcall* ResetAllFades)(vgui_BaseRichText* self, bool bHold, bool bOnlyExpired, float flNewSustain);
void(__fastcall* SetToFullHeight)(vgui_BaseRichText* self);
@@ -81,25 +81,25 @@ LocalChatWriter::SwatchColor swatchColors[4] = {
LocalChatWriter::NetworkNameColor,
};
-vgui_Color darkColors[8] = {
- vgui_Color {0, 0, 0, 255},
- vgui_Color {205, 49, 49, 255},
- vgui_Color {13, 188, 121, 255},
- vgui_Color {229, 229, 16, 255},
- vgui_Color {36, 114, 200, 255},
- vgui_Color {188, 63, 188, 255},
- vgui_Color {17, 168, 205, 255},
- vgui_Color {229, 229, 229, 255}};
-
-vgui_Color lightColors[8] = {
- vgui_Color {102, 102, 102, 255},
- vgui_Color {241, 76, 76, 255},
- vgui_Color {35, 209, 139, 255},
- vgui_Color {245, 245, 67, 255},
- vgui_Color {59, 142, 234, 255},
- vgui_Color {214, 112, 214, 255},
- vgui_Color {41, 184, 219, 255},
- vgui_Color {255, 255, 255, 255}};
+Color darkColors[8] = {
+ Color {0, 0, 0, 255},
+ Color {205, 49, 49, 255},
+ Color {13, 188, 121, 255},
+ Color {229, 229, 16, 255},
+ Color {36, 114, 200, 255},
+ Color {188, 63, 188, 255},
+ Color {17, 168, 205, 255},
+ Color {229, 229, 229, 255}};
+
+Color lightColors[8] = {
+ Color {102, 102, 102, 255},
+ Color {241, 76, 76, 255},
+ Color {35, 209, 139, 255},
+ Color {245, 245, 67, 255},
+ Color {59, 142, 234, 255},
+ Color {214, 112, 214, 255},
+ Color {41, 184, 219, 255},
+ Color {255, 255, 255, 255}};
class AnsiEscapeParser
{
@@ -144,7 +144,7 @@ class AnsiEscapeParser
LocalChatWriter* m_writer;
Next m_next = Next::ControlType;
- vgui_Color m_expandedColor {0, 0, 0, 0};
+ Color m_expandedColor {0, 0, 0, 0};
Next HandleControlType(unsigned long val)
{
@@ -190,7 +190,7 @@ class AnsiEscapeParser
// Next values are r,g,b
if (val == 2)
{
- m_expandedColor = {0, 0, 0, 255};
+ m_expandedColor.SetColor(0, 0, 0, 255);
return Next::ForegroundR;
}
// Next value is 8-bit swatch color
@@ -220,12 +220,12 @@ class AnsiEscapeParser
unsigned char green = ((code - blue) / 6) % 6;
unsigned char red = (code - blue - (green * 6)) / 36;
m_writer->InsertColorChange(
- vgui_Color {(unsigned char)(red * 51), (unsigned char)(green * 51), (unsigned char)(blue * 51), 255});
+ Color {(unsigned char)(red * 51), (unsigned char)(green * 51), (unsigned char)(blue * 51), 255});
}
else if (val < UCHAR_MAX)
{
unsigned char brightness = (val - 232) * 10 + 8;
- m_writer->InsertColorChange(vgui_Color {brightness, brightness, brightness, 255});
+ m_writer->InsertColorChange(Color {brightness, brightness, brightness, 255});
}
return Next::ControlType;
@@ -236,7 +236,7 @@ class AnsiEscapeParser
if (val >= UCHAR_MAX)
return Next::ControlType;
- m_expandedColor.r = (unsigned char)val;
+ m_expandedColor[0] = (unsigned char)val;
return Next::ForegroundG;
}
@@ -245,7 +245,7 @@ class AnsiEscapeParser
if (val >= UCHAR_MAX)
return Next::ControlType;
- m_expandedColor.g = (unsigned char)val;
+ m_expandedColor[1] = (unsigned char)val;
return Next::ForegroundB;
}
@@ -254,7 +254,7 @@ class AnsiEscapeParser
if (val >= UCHAR_MAX)
return Next::ControlType;
- m_expandedColor.b = (unsigned char)val;
+ m_expandedColor[2] = (unsigned char)val;
m_writer->InsertColorChange(m_expandedColor);
return Next::ControlType;
}
@@ -320,6 +320,8 @@ void LocalChatWriter::InsertChar(wchar_t ch)
void LocalChatWriter::InsertText(const char* str)
{
+ spdlog::info(str);
+
WCHAR messageUnicode[288];
ConvertANSIToUnicode(str, -1, messageUnicode, 274);
@@ -347,7 +349,7 @@ void LocalChatWriter::InsertText(const wchar_t* str)
InsertDefaultFade();
}
-void LocalChatWriter::InsertColorChange(vgui_Color color)
+void LocalChatWriter::InsertColorChange(Color color)
{
for (CHudChat* hud = *CHudChat::allHuds; hud != NULL; hud = hud->next)
{
@@ -358,20 +360,25 @@ void LocalChatWriter::InsertColorChange(vgui_Color color)
}
}
-static vgui_Color GetHudSwatchColor(CHudChat* hud, LocalChatWriter::SwatchColor swatchColor)
+static Color GetHudSwatchColor(CHudChat* hud, LocalChatWriter::SwatchColor swatchColor)
{
switch (swatchColor)
{
case LocalChatWriter::MainTextColor:
return hud->m_mainTextColor;
+
case LocalChatWriter::SameTeamNameColor:
return hud->m_sameTeamColor;
+
case LocalChatWriter::EnemyTeamNameColor:
return hud->m_enemyTeamColor;
+
case LocalChatWriter::NetworkNameColor:
return hud->m_networkNameColor;
+
}
- return vgui_Color {0, 0, 0, 0};
+
+ return Color(0, 0, 0, 0);
}
void LocalChatWriter::InsertSwatchColorChange(SwatchColor swatchColor)
diff --git a/NorthstarDLL/localchatwriter.h b/NorthstarDLL/localchatwriter.h
index e52e4c80..b9183f63 100644
--- a/NorthstarDLL/localchatwriter.h
+++ b/NorthstarDLL/localchatwriter.h
@@ -1,13 +1,6 @@
#pragma once
#include "pch.h"
-
-struct vgui_Color
-{
- unsigned char r;
- unsigned char g;
- unsigned char b;
- unsigned char a;
-};
+#include "color.h"
class vgui_BaseRichText;
@@ -18,10 +11,10 @@ class CHudChat
char unknown1[720];
- vgui_Color m_sameTeamColor;
- vgui_Color m_enemyTeamColor;
- vgui_Color m_mainTextColor;
- vgui_Color m_networkNameColor;
+ Color m_sameTeamColor;
+ Color m_enemyTeamColor;
+ Color m_mainTextColor;
+ Color m_networkNameColor;
char unknown2[12];
@@ -61,7 +54,7 @@ class LocalChatWriter
void InsertChar(wchar_t ch);
void InsertText(const char* str);
void InsertText(const wchar_t* str);
- void InsertColorChange(vgui_Color color);
+ void InsertColorChange(Color color);
void InsertSwatchColorChange(SwatchColor color);
private:
diff --git a/NorthstarDLL/masterserver.cpp b/NorthstarDLL/masterserver.cpp
index 37a67c21..4d5f371b 100644
--- a/NorthstarDLL/masterserver.cpp
+++ b/NorthstarDLL/masterserver.cpp
@@ -32,7 +32,7 @@ ConVar* Cvar_ns_curl_log_enable;
ConVar* Cvar_hostname;
ConVar* Cvar_hostport;
-MasterServerManager* g_MasterServerManager;
+MasterServerManager* g_pMasterServerManager;
// Convert a hex digit char to integer.
inline int hctod(char c)
@@ -578,7 +578,7 @@ void MasterServerManager::AuthenticateWithOwnServer(const char* uid, const char*
goto REQUEST_END_CLEANUP;
}
- AuthData newAuthData {};
+ RemoteAuthData newAuthData {};
strncpy(newAuthData.uid, authInfoJson["id"].GetString(), sizeof(newAuthData.uid));
newAuthData.uid[sizeof(newAuthData.uid) - 1] = 0;
@@ -600,9 +600,9 @@ void MasterServerManager::AuthenticateWithOwnServer(const char* uid, const char*
newAuthData.pdata[i++] = static_cast<char>(byte.GetUint());
}
- std::lock_guard<std::mutex> guard(g_pServerAuthenticationManager->m_authDataMutex);
- g_pServerAuthenticationManager->m_authData.clear();
- g_pServerAuthenticationManager->m_authData.insert(std::make_pair(authInfoJson["authToken"].GetString(), newAuthData));
+ std::lock_guard<std::mutex> guard(g_pServerAuthentication->m_AuthDataMutex);
+ g_pServerAuthentication->m_RemoteAuthenticationData.clear();
+ g_pServerAuthentication->m_RemoteAuthenticationData.insert(std::make_pair(authInfoJson["authToken"].GetString(), newAuthData));
m_bSuccessfullyAuthenticatedWithGameServer = true;
}
@@ -908,8 +908,8 @@ void MasterServerManager::AddSelfToServerList(
// send all registration info so we have all necessary info to reregister our server if masterserver goes down,
// without a restart this isn't threadsafe :terror:
{
- char* escapedNameNew = curl_easy_escape(curl, g_MasterServerManager->m_sUnicodeServerName.c_str(), NULL);
- char* escapedDescNew = curl_easy_escape(curl, g_MasterServerManager->m_sUnicodeServerDesc.c_str(), NULL);
+ char* escapedNameNew = curl_easy_escape(curl, g_pMasterServerManager->m_sUnicodeServerName.c_str(), NULL);
+ char* escapedDescNew = curl_easy_escape(curl, g_pMasterServerManager->m_sUnicodeServerDesc.c_str(), NULL);
char* escapedMapNew = curl_easy_escape(curl, R2::g_pHostState->m_levelName, NULL);
char* escapedPlaylistNew = curl_easy_escape(curl, R2::GetCurrentPlaylistName(), NULL);
char* escapedPasswordNew = curl_easy_escape(curl, Cvar_ns_server_password->GetString(), NULL);
@@ -929,12 +929,12 @@ void MasterServerManager::AddSelfToServerList(
Cvar_ns_masterserver_hostname->GetString(),
m_sOwnServerId,
Cvar_hostport->GetInt(),
- Cvar_ns_player_auth_port->GetInt(),
+ g_pServerAuthentication->Cvar_ns_player_auth_port->GetInt(),
escapedNameNew,
escapedDescNew,
escapedMapNew,
escapedPlaylistNew,
- g_pServerAuthenticationManager->m_additionalPlayerData.size(),
+ g_pServerAuthentication->m_PlayerAuthenticationData.size(),
maxPlayers,
escapedPasswordNew)
.c_str());
@@ -1194,22 +1194,22 @@ void MasterServerManager::RemoveSelfFromServerList()
void ConCommand_ns_fetchservers(const CCommand& args)
{
- g_MasterServerManager->RequestServerList();
+ g_pMasterServerManager->RequestServerList();
}
MasterServerManager::MasterServerManager() : m_pendingConnectionInfo {}, m_sOwnServerId {""}, m_sOwnClientAuthToken {""} {}
ON_DLL_LOAD_RELIESON("engine.dll", MasterServer, ConCommand, (HMODULE baseAddress))
{
- g_MasterServerManager = new MasterServerManager;
+ g_pMasterServerManager = new MasterServerManager;
Cvar_ns_masterserver_hostname = new ConVar("ns_masterserver_hostname", "127.0.0.1", FCVAR_NONE, "");
Cvar_ns_server_name = new ConVar("ns_server_name", "Unnamed Northstar Server", FCVAR_GAMEDLL, "This server's description", false, 0, false, 0, [](ConVar* cvar, const char* pOldValue, float flOldValue) {
- g_MasterServerManager->m_sUnicodeServerName = unescape_unicode(Cvar_ns_server_name->GetString());
+ g_pMasterServerManager->m_sUnicodeServerName = unescape_unicode(Cvar_ns_server_name->GetString());
});
Cvar_ns_server_desc = new ConVar("ns_server_desc", "Default server description", FCVAR_GAMEDLL, "This server's name", false, 0, false, 0, [](ConVar* cvar, const char* pOldValue, float flOldValue) {
- g_MasterServerManager->m_sUnicodeServerName = unescape_unicode(Cvar_ns_server_desc->GetString());
+ g_pMasterServerManager->m_sUnicodeServerDesc = unescape_unicode(Cvar_ns_server_desc->GetString());
});
Cvar_ns_server_password = new ConVar("ns_server_password", "", FCVAR_GAMEDLL, "This server's password");
diff --git a/NorthstarDLL/masterserver.h b/NorthstarDLL/masterserver.h
index bb2348ca..ae5167df 100644
--- a/NorthstarDLL/masterserver.h
+++ b/NorthstarDLL/masterserver.h
@@ -148,6 +148,6 @@ class MasterServerManager
};
std::string unescape_unicode(const std::string& str);
-extern MasterServerManager* g_MasterServerManager;
+extern MasterServerManager* g_pMasterServerManager;
extern ConVar* Cvar_ns_masterserver_hostname;
extern ConVar* Cvar_ns_server_password;
diff --git a/NorthstarDLL/misccommands.cpp b/NorthstarDLL/misccommands.cpp
index 55c0a147..dd1b9d65 100644
--- a/NorthstarDLL/misccommands.cpp
+++ b/NorthstarDLL/misccommands.cpp
@@ -21,22 +21,22 @@ void ConCommand_force_newgame(const CCommand& arg)
void ConCommand_ns_start_reauth_and_leave_to_lobby(const CCommand& arg)
{
// hack for special case where we're on a local server, so we erase our own newly created auth data on disconnect
- g_MasterServerManager->m_bNewgameAfterSelfAuth = true;
- g_MasterServerManager->AuthenticateWithOwnServer(R2::g_pLocalPlayerUserID, g_MasterServerManager->m_sOwnClientAuthToken);
+ g_pMasterServerManager->m_bNewgameAfterSelfAuth = true;
+ g_pMasterServerManager->AuthenticateWithOwnServer(R2::g_pLocalPlayerUserID, g_pMasterServerManager->m_sOwnClientAuthToken);
}
void ConCommand_ns_end_reauth_and_leave_to_lobby(const CCommand& arg)
{
R2::Cbuf_AddText(
R2::Cbuf_GetCurrentPlayer(),
- fmt::format("serverfilter {}", g_pServerAuthenticationManager->m_authData.begin()->first).c_str(),
+ fmt::format("serverfilter {}", g_pServerAuthentication->m_RemoteAuthenticationData.begin()->first).c_str(),
R2::cmd_source_t::kCommandSrcCode);
R2::Cbuf_Execute();
// weird way of checking, but check if client script vm is initialised, mainly just to allow players to cancel this
if (g_pClientSquirrel->sqvm)
{
- g_pServerAuthenticationManager->m_bNeedLocalAuthForNewgame = true;
+ g_pServerAuthentication->m_bNeedLocalAuthForNewgame = true;
// this won't set playlist correctly on remote clients, don't think they can set playlist until they've left which sorta
// fucks things should maybe set this in HostState_NewGame?
diff --git a/NorthstarDLL/miscserverfixes.cpp b/NorthstarDLL/miscserverfixes.cpp
index b5eebac8..926779b7 100644
--- a/NorthstarDLL/miscserverfixes.cpp
+++ b/NorthstarDLL/miscserverfixes.cpp
@@ -8,8 +8,4 @@ ON_DLL_LOAD("server.dll", MiscServerFixes, (HMODULE baseAddress))
// nop out call to VGUI shutdown since it crashes the game when quitting from the console
NSMem::NOP(ba + 0x154A96, 5);
-
- // ret at the start of CServerGameClients::ClientCommandKeyValues as it has no benefit and is forwarded to client (i.e. security issue)
- // this prevents the attack vector of client=>server=>client, however server=>client also has clientside patches
- NSMem::BytePatch(ba + 0x153920, "C3");
} \ No newline at end of file
diff --git a/NorthstarDLL/miscserverscript.cpp b/NorthstarDLL/miscserverscript.cpp
index 25a0cd1a..12ab5708 100644
--- a/NorthstarDLL/miscserverscript.cpp
+++ b/NorthstarDLL/miscserverscript.cpp
@@ -1,44 +1,33 @@
#include "pch.h"
-#include "miscserverscript.h"
#include "squirrel.h"
#include "masterserver.h"
#include "serverauthentication.h"
#include "r2client.h"
+#include "r2server.h"
-// annoying helper function because i can't figure out getting players or entities from sqvm rn
-// wish i didn't have to do it like this, but here we are
-void* GetPlayerByIndex(int playerIndex)
-{
- const int PLAYER_ARRAY_OFFSET = 0x12A53F90;
- const int PLAYER_SIZE = 0x2D728;
-
- void* playerArrayBase = (char*)GetModuleHandleA("engine.dll") + PLAYER_ARRAY_OFFSET;
- void* player = (char*)playerArrayBase + (playerIndex * PLAYER_SIZE);
-
- return player;
-}
+#include <filesystem>
// void function NSEarlyWritePlayerIndexPersistenceForLeave( int playerIndex )
SQRESULT SQ_EarlyWritePlayerIndexPersistenceForLeave(void* sqvm)
{
int playerIndex = g_pServerSquirrel->getinteger(sqvm, 1);
- void* player = GetPlayerByIndex(playerIndex);
+ R2::CBasePlayer* player = R2::UTIL_PlayerByIndex(playerIndex);
- if (!g_pServerAuthenticationManager->m_additionalPlayerData.count(player))
+ if (!g_pServerAuthentication->m_PlayerAuthenticationData.count(player))
{
g_pServerSquirrel->raiseerror(sqvm, fmt::format("Invalid playerindex {}", playerIndex).c_str());
return SQRESULT_ERROR;
}
- g_pServerAuthenticationManager->m_additionalPlayerData[player].needPersistenceWriteOnLeave = false;
- g_pServerAuthenticationManager->WritePersistentData(player);
+ g_pServerAuthentication->m_PlayerAuthenticationData[player].needPersistenceWriteOnLeave = false;
+ g_pServerAuthentication->WritePersistentData(player);
return SQRESULT_NULL;
}
// bool function NSIsWritingPlayerPersistence()
SQRESULT SQ_IsWritingPlayerPersistence(void* sqvm)
{
- g_pServerSquirrel->pushbool(sqvm, g_MasterServerManager->m_bSavingPersistentData);
+ g_pServerSquirrel->pushbool(sqvm, g_pMasterServerManager->m_bSavingPersistentData);
return SQRESULT_NOTNULL;
}
@@ -46,14 +35,14 @@ SQRESULT SQ_IsWritingPlayerPersistence(void* sqvm)
SQRESULT SQ_IsPlayerIndexLocalPlayer(void* sqvm)
{
int playerIndex = g_pServerSquirrel->getinteger(sqvm, 1);
- void* player = GetPlayerByIndex(playerIndex);
- if (!g_pServerAuthenticationManager->m_additionalPlayerData.count(player))
+ R2::CBasePlayer* player = R2::UTIL_PlayerByIndex(playerIndex);
+ if (!g_pServerAuthentication->m_PlayerAuthenticationData.count(player))
{
g_pServerSquirrel->raiseerror(sqvm, fmt::format("Invalid playerindex {}", playerIndex).c_str());
return SQRESULT_ERROR;
}
- g_pServerSquirrel->pushbool(sqvm, !strcmp(R2::g_pLocalPlayerUserID, (char*)player + 0xF500));
+ g_pServerSquirrel->pushbool(sqvm, !strcmp(R2::g_pLocalPlayerUserID, player->m_UID));
return SQRESULT_NOTNULL;
}
diff --git a/NorthstarDLL/miscserverscript.h b/NorthstarDLL/miscserverscript.h
deleted file mode 100644
index 00b6a0d1..00000000
--- a/NorthstarDLL/miscserverscript.h
+++ /dev/null
@@ -1,2 +0,0 @@
-#pragma once
-void* GetPlayerByIndex(int playerIndex);
diff --git a/NorthstarDLL/modmanager.cpp b/NorthstarDLL/modmanager.cpp
index 3fa6eb14..9ed3ea6f 100644
--- a/NorthstarDLL/modmanager.cpp
+++ b/NorthstarDLL/modmanager.cpp
@@ -539,7 +539,7 @@ void ModManager::LoadMods()
buffer.Clear();
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
modinfoDoc.Accept(writer);
- g_MasterServerManager->m_sOwnModInfoJson = std::string(buffer.GetString());
+ g_pMasterServerManager->m_sOwnModInfoJson = std::string(buffer.GetString());
m_bHasLoadedMods = true;
}
diff --git a/NorthstarDLL/playlist.cpp b/NorthstarDLL/playlist.cpp
index c6bee74d..0eb0e1d2 100644
--- a/NorthstarDLL/playlist.cpp
+++ b/NorthstarDLL/playlist.cpp
@@ -4,6 +4,7 @@
#include "concommand.h"
#include "convar.h"
#include "squirrel.h"
+#include "hoststate.h"
AUTOHOOK_INIT()
@@ -21,9 +22,8 @@ ConVar* Cvar_ns_use_clc_SetPlaylistVarOverride;
AUTOHOOK(clc_SetPlaylistVarOverride__Process, engine.dll + 0x222180,
char,, (void* a1, void* a2))
{
- // the private_match playlist is the only situation where there should be any legitimate sending of this netmessage
- // todo: check map == mp_lobby here too
- if (!Cvar_ns_use_clc_SetPlaylistVarOverride->GetBool() || strcmp(R2::GetCurrentPlaylistName(), "private_match"))
+ // the private_match playlist on mp_lobby is the only situation where there should be any legitimate sending of this netmessage
+ if (!Cvar_ns_use_clc_SetPlaylistVarOverride->GetBool() || strcmp(R2::GetCurrentPlaylistName(), "private_match") || strcmp(R2::g_pHostState->m_levelName, "mp_lobby"))
return 1;
return clc_SetPlaylistVarOverride__Process(a1, a2);
diff --git a/NorthstarDLL/plugins.cpp b/NorthstarDLL/plugins.cpp
index 2d52d4ab..a6087efe 100644
--- a/NorthstarDLL/plugins.cpp
+++ b/NorthstarDLL/plugins.cpp
@@ -193,7 +193,7 @@ SQRESULT SQ_SetConnected(void* sqvm)
SQRESULT SQ_UpdateListenServer(void* sqvm)
{
AcquireSRWLockExclusive(&serverInfoLock);
- serverInfo.id = g_MasterServerManager->m_sOwnServerId;
+ serverInfo.id = g_pMasterServerManager->m_sOwnServerId;
serverInfo.password = Cvar_ns_server_password->GetString();
ReleaseSRWLockExclusive(&serverInfoLock);
return SQRESULT_NOTNULL;
diff --git a/NorthstarDLL/printmaps.cpp b/NorthstarDLL/printmaps.cpp
index af3ea275..bd89946b 100644
--- a/NorthstarDLL/printmaps.cpp
+++ b/NorthstarDLL/printmaps.cpp
@@ -128,7 +128,7 @@ int, __fastcall, (const char const* cmdname, const char const* partial, char com
const int queryLength = strlen(query);
int numMaps = 0;
- for (int i = 0; i < COMMAND_COMPLETION_MAXITEMS && i < vMapList.size(); i++)
+ for (int i = 0; i < vMapList.size() && numMaps < COMMAND_COMPLETION_MAXITEMS; i++)
{
if (!strncmp(query, vMapList[i].name.c_str(), queryLength))
{
diff --git a/NorthstarDLL/r2engine.cpp b/NorthstarDLL/r2engine.cpp
index 8d4390e6..5d063141 100644
--- a/NorthstarDLL/r2engine.cpp
+++ b/NorthstarDLL/r2engine.cpp
@@ -11,6 +11,8 @@ namespace R2
Cbuf_ExecuteType Cbuf_Execute;
CEngine* g_pEngine;
+
+ void (*CBaseClient__Disconnect)(void* self, uint32_t unknownButAlways1, const char* reason, ...);
} // namespace R2
ON_DLL_LOAD("engine.dll", R2Engine, (HMODULE baseAddress))
@@ -20,4 +22,6 @@ ON_DLL_LOAD("engine.dll", R2Engine, (HMODULE baseAddress))
Cbuf_Execute = (Cbuf_ExecuteType)((char*)baseAddress + 0x1204B0);
g_pEngine = *(CEngine**)((char*)baseAddress + 0x7D70C8);
+
+ CBaseClient__Disconnect = (void (*)(void*, uint32_t, const char*, ...))((char*)baseAddress + 0x1012C0);
} \ No newline at end of file
diff --git a/NorthstarDLL/r2engine.h b/NorthstarDLL/r2engine.h
index c31adfd1..b3d118de 100644
--- a/NorthstarDLL/r2engine.h
+++ b/NorthstarDLL/r2engine.h
@@ -99,4 +99,45 @@ namespace R2
};
extern CEngine* g_pEngine;
+
+ extern void (*CBaseClient__Disconnect)(void* self, uint32_t unknownButAlways1, const char* reason, ...);
+
+ #pragma once
+ typedef enum
+ {
+ NA_NULL = 0,
+ NA_LOOPBACK,
+ NA_IP,
+ } netadrtype_t;
+
+ #pragma pack(push, 1)
+ typedef struct netadr_s
+ {
+ netadrtype_t type;
+ unsigned char ip[16]; // IPv6
+ // IPv4's 127.0.0.1 is [::ffff:127.0.0.1], that is:
+ // 00 00 00 00 00 00 00 00 00 00 FF FF 7F 00 00 01
+ unsigned short port;
+ } netadr_t;
+ #pragma pack(pop)
+
+ #pragma pack(push, 1)
+ typedef struct netpacket_s
+ {
+ netadr_t adr; // sender address
+ // int source; // received source
+ char unk[10];
+ double received_time;
+ unsigned char* data; // pointer to raw packet data
+ void* message; // easy bitbuf data access // 'inpacket.message' etc etc (pointer)
+ char unk2[16];
+ int size;
+
+ // bf_read message; // easy bitbuf data access // 'inpacket.message' etc etc (pointer)
+ // int size; // size in bytes
+ // int wiresize; // size in bytes before decompression
+ // bool stream; // was send as stream
+ // struct netpacket_s* pNext; // for internal use, should be NULL in public
+ } netpacket_t;
+ #pragma pack(pop)
} // namespace R2
diff --git a/NorthstarDLL/r2server.cpp b/NorthstarDLL/r2server.cpp
index 7a6ebe90..848104d4 100644
--- a/NorthstarDLL/r2server.cpp
+++ b/NorthstarDLL/r2server.cpp
@@ -7,7 +7,8 @@ using namespace R2;
namespace R2
{
server_state_t* g_pServerState;
- Server_GetEntityByIndexType Server_GetEntityByIndex;
+ void* (*Server_GetEntityByIndex)(int index);
+ CBasePlayer*(__fastcall* UTIL_PlayerByIndex)(int playerIndex);
} // namespace R2
ON_DLL_LOAD("engine.dll", R2EngineServer, (HMODULE baseAddress))
@@ -17,5 +18,6 @@ ON_DLL_LOAD("engine.dll", R2EngineServer, (HMODULE baseAddress))
ON_DLL_LOAD("server.dll", R2GameServer, (HMODULE baseAddress))
{
- Server_GetEntityByIndex = (Server_GetEntityByIndexType)((char*)baseAddress + 0xFB820);
+ Server_GetEntityByIndex = (void*(*)(int))((char*)baseAddress + 0xFB820);
+ UTIL_PlayerByIndex = (CBasePlayer*(__fastcall*)(int))((char*)baseAddress + 0x26AA10);
} \ No newline at end of file
diff --git a/NorthstarDLL/r2server.h b/NorthstarDLL/r2server.h
index 816adc82..c032d722 100644
--- a/NorthstarDLL/r2server.h
+++ b/NorthstarDLL/r2server.h
@@ -14,6 +14,44 @@ namespace R2
extern server_state_t* g_pServerState;
// server entity stuff
- typedef void* (*Server_GetEntityByIndexType)(int index);
- extern Server_GetEntityByIndexType Server_GetEntityByIndex;
+ extern void* (*Server_GetEntityByIndex)(int index);
+
+ const int PERSISTENCE_MAX_SIZE = 0xD000;
+
+ enum class ePersistenceReady : char
+ {
+ NOT_READY,
+ READY = 3,
+ READY_LOCAL = 3,
+ READY_REMOTE
+ };
+
+ #pragma pack(push, 1)
+ struct CBasePlayer
+ {
+ char pad0[0x16];
+
+ // +0x16
+ char m_Name[64];
+ // +0x56
+
+ char pad1[0x44A];
+
+ // +0x4A0
+ ePersistenceReady m_iPersistenceReady;
+ // +0x4A1
+
+ char pad2[0x59];
+
+ // +0x4FA
+ char m_PersistenceBuffer[PERSISTENCE_MAX_SIZE];
+
+ char pad3[0x2006];
+
+ // +0xF500
+ char m_UID[32];
+ };
+ #pragma pack(pop)
+
+ extern CBasePlayer*(__fastcall* UTIL_PlayerByIndex)(int playerIndex);
} // namespace R2 \ No newline at end of file
diff --git a/NorthstarDLL/scriptmainmenupromos.cpp b/NorthstarDLL/scriptmainmenupromos.cpp
index c0fc42bb..5d86c603 100644
--- a/NorthstarDLL/scriptmainmenupromos.cpp
+++ b/NorthstarDLL/scriptmainmenupromos.cpp
@@ -26,100 +26,100 @@ enum eMainMenuPromoDataProperty
// void function NSRequestCustomMainMenuPromos()
SQRESULT SQ_RequestCustomMainMenuPromos(void* sqvm)
{
- g_MasterServerManager->RequestMainMenuPromos();
+ g_pMasterServerManager->RequestMainMenuPromos();
return SQRESULT_NULL;
}
// bool function NSHasCustomMainMenuPromoData()
SQRESULT SQ_HasCustomMainMenuPromoData(void* sqvm)
{
- g_pUISquirrel->pushbool(sqvm, g_MasterServerManager->m_bHasMainMenuPromoData);
+ g_pUISquirrel->pushbool(sqvm, g_pMasterServerManager->m_bHasMainMenuPromoData);
return SQRESULT_NOTNULL;
}
// var function NSGetCustomMainMenuPromoData( int promoDataKey )
SQRESULT SQ_GetCustomMainMenuPromoData(void* sqvm)
{
- if (!g_MasterServerManager->m_bHasMainMenuPromoData)
+ if (!g_pMasterServerManager->m_bHasMainMenuPromoData)
return SQRESULT_NULL;
switch (g_pUISquirrel->getinteger(sqvm, 1))
{
case eMainMenuPromoDataProperty::newInfoTitle1:
{
- g_pUISquirrel->pushstring(sqvm, g_MasterServerManager->m_sMainMenuPromoData.newInfoTitle1.c_str());
+ g_pUISquirrel->pushstring(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.newInfoTitle1.c_str());
break;
}
case eMainMenuPromoDataProperty::newInfoTitle2:
{
- g_pUISquirrel->pushstring(sqvm, g_MasterServerManager->m_sMainMenuPromoData.newInfoTitle2.c_str());
+ g_pUISquirrel->pushstring(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.newInfoTitle2.c_str());
break;
}
case eMainMenuPromoDataProperty::newInfoTitle3:
{
- g_pUISquirrel->pushstring(sqvm, g_MasterServerManager->m_sMainMenuPromoData.newInfoTitle3.c_str());
+ g_pUISquirrel->pushstring(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.newInfoTitle3.c_str());
break;
}
case eMainMenuPromoDataProperty::largeButtonTitle:
{
- g_pUISquirrel->pushstring(sqvm, g_MasterServerManager->m_sMainMenuPromoData.largeButtonTitle.c_str());
+ g_pUISquirrel->pushstring(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.largeButtonTitle.c_str());
break;
}
case eMainMenuPromoDataProperty::largeButtonText:
{
- g_pUISquirrel->pushstring(sqvm, g_MasterServerManager->m_sMainMenuPromoData.largeButtonText.c_str());
+ g_pUISquirrel->pushstring(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.largeButtonText.c_str());
break;
}
case eMainMenuPromoDataProperty::largeButtonUrl:
{
- g_pUISquirrel->pushstring(sqvm, g_MasterServerManager->m_sMainMenuPromoData.largeButtonUrl.c_str());
+ g_pUISquirrel->pushstring(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.largeButtonUrl.c_str());
break;
}
case eMainMenuPromoDataProperty::largeButtonImageIndex:
{
- g_pUISquirrel->pushinteger(sqvm, g_MasterServerManager->m_sMainMenuPromoData.largeButtonImageIndex);
+ g_pUISquirrel->pushinteger(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.largeButtonImageIndex);
break;
}
case eMainMenuPromoDataProperty::smallButton1Title:
{
- g_pUISquirrel->pushstring(sqvm, g_MasterServerManager->m_sMainMenuPromoData.smallButton1Title.c_str());
+ g_pUISquirrel->pushstring(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.smallButton1Title.c_str());
break;
}
case eMainMenuPromoDataProperty::smallButton1Url:
{
- g_pUISquirrel->pushstring(sqvm, g_MasterServerManager->m_sMainMenuPromoData.smallButton1Url.c_str());
+ g_pUISquirrel->pushstring(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.smallButton1Url.c_str());
break;
}
case eMainMenuPromoDataProperty::smallButton1ImageIndex:
{
- g_pUISquirrel->pushinteger(sqvm, g_MasterServerManager->m_sMainMenuPromoData.smallButton1ImageIndex);
+ g_pUISquirrel->pushinteger(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.smallButton1ImageIndex);
break;
}
case eMainMenuPromoDataProperty::smallButton2Title:
{
- g_pUISquirrel->pushstring(sqvm, g_MasterServerManager->m_sMainMenuPromoData.smallButton2Title.c_str());
+ g_pUISquirrel->pushstring(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.smallButton2Title.c_str());
break;
}
case eMainMenuPromoDataProperty::smallButton2Url:
{
- g_pUISquirrel->pushstring(sqvm, g_MasterServerManager->m_sMainMenuPromoData.smallButton2Url.c_str());
+ g_pUISquirrel->pushstring(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.smallButton2Url.c_str());
break;
}
case eMainMenuPromoDataProperty::smallButton2ImageIndex:
{
- g_pUISquirrel->pushinteger(sqvm, g_MasterServerManager->m_sMainMenuPromoData.smallButton2ImageIndex);
+ g_pUISquirrel->pushinteger(sqvm, g_pMasterServerManager->m_sMainMenuPromoData.smallButton2ImageIndex);
break;
}
}
diff --git a/NorthstarDLL/scriptserverbrowser.cpp b/NorthstarDLL/scriptserverbrowser.cpp
index a42e9b14..13f4b7e6 100644
--- a/NorthstarDLL/scriptserverbrowser.cpp
+++ b/NorthstarDLL/scriptserverbrowser.cpp
@@ -10,35 +10,35 @@
// bool function NSIsMasterServerAuthenticated()
SQRESULT SQ_IsMasterServerAuthenticated(void* sqvm)
{
- g_pUISquirrel->pushbool(sqvm, g_MasterServerManager->m_bOriginAuthWithMasterServerDone);
+ g_pUISquirrel->pushbool(sqvm, g_pMasterServerManager->m_bOriginAuthWithMasterServerDone);
return SQRESULT_NOTNULL;
}
// void function NSRequestServerList()
SQRESULT SQ_RequestServerList(void* sqvm)
{
- g_MasterServerManager->RequestServerList();
+ g_pMasterServerManager->RequestServerList();
return SQRESULT_NULL;
}
// bool function NSIsRequestingServerList()
SQRESULT SQ_IsRequestingServerList(void* sqvm)
{
- g_pUISquirrel->pushbool(sqvm, g_MasterServerManager->m_bScriptRequestingServerList);
+ g_pUISquirrel->pushbool(sqvm, g_pMasterServerManager->m_bScriptRequestingServerList);
return SQRESULT_NOTNULL;
}
// bool function NSMasterServerConnectionSuccessful()
SQRESULT SQ_MasterServerConnectionSuccessful(void* sqvm)
{
- g_pUISquirrel->pushbool(sqvm, g_MasterServerManager->m_bSuccessfullyConnected);
+ g_pUISquirrel->pushbool(sqvm, g_pMasterServerManager->m_bSuccessfullyConnected);
return SQRESULT_NOTNULL;
}
// int function NSGetServerCount()
SQRESULT SQ_GetServerCount(void* sqvm)
{
- g_pUISquirrel->pushinteger(sqvm, g_MasterServerManager->m_vRemoteServers.size());
+ g_pUISquirrel->pushinteger(sqvm, g_pMasterServerManager->m_vRemoteServers.size());
return SQRESULT_NOTNULL;
}
@@ -47,19 +47,19 @@ SQRESULT SQ_GetServerName(void* sqvm)
{
SQInteger serverIndex = g_pUISquirrel->getinteger(sqvm, 1);
- if (serverIndex >= g_MasterServerManager->m_vRemoteServers.size())
+ if (serverIndex >= g_pMasterServerManager->m_vRemoteServers.size())
{
g_pUISquirrel->raiseerror(
sqvm,
fmt::format(
"Tried to get name of server index {} when only {} servers are available",
serverIndex,
- g_MasterServerManager->m_vRemoteServers.size())
+ g_pMasterServerManager->m_vRemoteServers.size())
.c_str());
return SQRESULT_ERROR;
}
- g_pUISquirrel->pushstring(sqvm, g_MasterServerManager->m_vRemoteServers[serverIndex].name);
+ g_pUISquirrel->pushstring(sqvm, g_pMasterServerManager->m_vRemoteServers[serverIndex].name);
return SQRESULT_NOTNULL;
}
@@ -68,19 +68,19 @@ SQRESULT SQ_GetServerDescription(void* sqvm)
{
SQInteger serverIndex = g_pUISquirrel->getinteger(sqvm, 1);
- if (serverIndex >= g_MasterServerManager->m_vRemoteServers.size())
+ if (serverIndex >= g_pMasterServerManager->m_vRemoteServers.size())
{
g_pUISquirrel->raiseerror(
sqvm,
fmt::format(
"Tried to get description of server index {} when only {} servers are available",
serverIndex,
- g_MasterServerManager->m_vRemoteServers.size())
+ g_pMasterServerManager->m_vRemoteServers.size())
.c_str());
return SQRESULT_ERROR;
}
- g_pUISquirrel->pushstring(sqvm, g_MasterServerManager->m_vRemoteServers[serverIndex].description.c_str());
+ g_pUISquirrel->pushstring(sqvm, g_pMasterServerManager->m_vRemoteServers[serverIndex].description.c_str());
return SQRESULT_NOTNULL;
}
@@ -89,19 +89,19 @@ SQRESULT SQ_GetServerMap(void* sqvm)
{
SQInteger serverIndex = g_pUISquirrel->getinteger(sqvm, 1);
- if (serverIndex >= g_MasterServerManager->m_vRemoteServers.size())
+ if (serverIndex >= g_pMasterServerManager->m_vRemoteServers.size())
{
g_pUISquirrel->raiseerror(
sqvm,
fmt::format(
"Tried to get map of server index {} when only {} servers are available",
serverIndex,
- g_MasterServerManager->m_vRemoteServers.size())
+ g_pMasterServerManager->m_vRemoteServers.size())
.c_str());
return SQRESULT_ERROR;
}
- g_pUISquirrel->pushstring(sqvm, g_MasterServerManager->m_vRemoteServers[serverIndex].map);
+ g_pUISquirrel->pushstring(sqvm, g_pMasterServerManager->m_vRemoteServers[serverIndex].map);
return SQRESULT_NOTNULL;
}
@@ -110,19 +110,19 @@ SQRESULT SQ_GetServerPlaylist(void* sqvm)
{
SQInteger serverIndex = g_pUISquirrel->getinteger(sqvm, 1);
- if (serverIndex >= g_MasterServerManager->m_vRemoteServers.size())
+ if (serverIndex >= g_pMasterServerManager->m_vRemoteServers.size())
{
g_pUISquirrel->raiseerror(
sqvm,
fmt::format(
"Tried to get playlist of server index {} when only {} servers are available",
serverIndex,
- g_MasterServerManager->m_vRemoteServers.size())
+ g_pMasterServerManager->m_vRemoteServers.size())
.c_str());
return SQRESULT_ERROR;
}
- g_pUISquirrel->pushstring(sqvm, g_MasterServerManager->m_vRemoteServers[serverIndex].playlist);
+ g_pUISquirrel->pushstring(sqvm, g_pMasterServerManager->m_vRemoteServers[serverIndex].playlist);
return SQRESULT_NOTNULL;
}
@@ -131,19 +131,19 @@ SQRESULT SQ_GetServerPlayerCount(void* sqvm)
{
SQInteger serverIndex = g_pUISquirrel->getinteger(sqvm, 1);
- if (serverIndex >= g_MasterServerManager->m_vRemoteServers.size())
+ if (serverIndex >= g_pMasterServerManager->m_vRemoteServers.size())
{
g_pUISquirrel->raiseerror(
sqvm,
fmt::format(
"Tried to get playercount of server index {} when only {} servers are available",
serverIndex,
- g_MasterServerManager->m_vRemoteServers.size())
+ g_pMasterServerManager->m_vRemoteServers.size())
.c_str());
return SQRESULT_ERROR;
}
- g_pUISquirrel->pushinteger(sqvm, g_MasterServerManager->m_vRemoteServers[serverIndex].playerCount);
+ g_pUISquirrel->pushinteger(sqvm, g_pMasterServerManager->m_vRemoteServers[serverIndex].playerCount);
return SQRESULT_NOTNULL;
}
@@ -152,19 +152,19 @@ SQRESULT SQ_GetServerMaxPlayerCount(void* sqvm)
{
SQInteger serverIndex = g_pUISquirrel->getinteger(sqvm, 1);
- if (serverIndex >= g_MasterServerManager->m_vRemoteServers.size())
+ if (serverIndex >= g_pMasterServerManager->m_vRemoteServers.size())
{
g_pUISquirrel->raiseerror(
sqvm,
fmt::format(
"Tried to get max playercount of server index {} when only {} servers are available",
serverIndex,
- g_MasterServerManager->m_vRemoteServers.size())
+ g_pMasterServerManager->m_vRemoteServers.size())
.c_str());
return SQRESULT_ERROR;
}
- g_pUISquirrel->pushinteger(sqvm, g_MasterServerManager->m_vRemoteServers[serverIndex].maxPlayers);
+ g_pUISquirrel->pushinteger(sqvm, g_pMasterServerManager->m_vRemoteServers[serverIndex].maxPlayers);
return SQRESULT_NOTNULL;
}
@@ -173,19 +173,19 @@ SQRESULT SQ_GetServerID(void* sqvm)
{
SQInteger serverIndex = g_pUISquirrel->getinteger(sqvm, 1);
- if (serverIndex >= g_MasterServerManager->m_vRemoteServers.size())
+ if (serverIndex >= g_pMasterServerManager->m_vRemoteServers.size())
{
g_pUISquirrel->raiseerror(
sqvm,
fmt::format(
"Tried to get id of server index {} when only {} servers are available",
serverIndex,
- g_MasterServerManager->m_vRemoteServers.size())
+ g_pMasterServerManager->m_vRemoteServers.size())
.c_str());
return SQRESULT_ERROR;
}
- g_pUISquirrel->pushstring(sqvm, g_MasterServerManager->m_vRemoteServers[serverIndex].id);
+ g_pUISquirrel->pushstring(sqvm, g_pMasterServerManager->m_vRemoteServers[serverIndex].id);
return SQRESULT_NOTNULL;
}
@@ -194,19 +194,19 @@ SQRESULT SQ_ServerRequiresPassword(void* sqvm)
{
SQInteger serverIndex = g_pUISquirrel->getinteger(sqvm, 1);
- if (serverIndex >= g_MasterServerManager->m_vRemoteServers.size())
+ if (serverIndex >= g_pMasterServerManager->m_vRemoteServers.size())
{
g_pUISquirrel->raiseerror(
sqvm,
fmt::format(
"Tried to get hasPassword of server index {} when only {} servers are available",
serverIndex,
- g_MasterServerManager->m_vRemoteServers.size())
+ g_pMasterServerManager->m_vRemoteServers.size())
.c_str());
return SQRESULT_ERROR;
}
- g_pUISquirrel->pushbool(sqvm, g_MasterServerManager->m_vRemoteServers[serverIndex].requiresPassword);
+ g_pUISquirrel->pushbool(sqvm, g_pMasterServerManager->m_vRemoteServers[serverIndex].requiresPassword);
return SQRESULT_NOTNULL;
}
@@ -215,19 +215,19 @@ SQRESULT SQ_GetServerRequiredModsCount(void* sqvm)
{
SQInteger serverIndex = g_pUISquirrel->getinteger(sqvm, 1);
- if (serverIndex >= g_MasterServerManager->m_vRemoteServers.size())
+ if (serverIndex >= g_pMasterServerManager->m_vRemoteServers.size())
{
g_pUISquirrel->raiseerror(
sqvm,
fmt::format(
"Tried to get required mods count of server index {} when only {} servers are available",
serverIndex,
- g_MasterServerManager->m_vRemoteServers.size())
+ g_pMasterServerManager->m_vRemoteServers.size())
.c_str());
return SQRESULT_ERROR;
}
- g_pUISquirrel->pushinteger(sqvm, g_MasterServerManager->m_vRemoteServers[serverIndex].requiredMods.size());
+ g_pUISquirrel->pushinteger(sqvm, g_pMasterServerManager->m_vRemoteServers[serverIndex].requiredMods.size());
return SQRESULT_NOTNULL;
}
@@ -237,31 +237,31 @@ SQRESULT SQ_GetServerRequiredModName(void* sqvm)
SQInteger serverIndex = g_pUISquirrel->getinteger(sqvm, 1);
SQInteger modIndex = g_pUISquirrel->getinteger(sqvm, 2);
- if (serverIndex >= g_MasterServerManager->m_vRemoteServers.size())
+ if (serverIndex >= g_pMasterServerManager->m_vRemoteServers.size())
{
g_pUISquirrel->raiseerror(
sqvm,
fmt::format(
"Tried to get hasPassword of server index {} when only {} servers are available",
serverIndex,
- g_MasterServerManager->m_vRemoteServers.size())
+ g_pMasterServerManager->m_vRemoteServers.size())
.c_str());
return SQRESULT_ERROR;
}
- if (modIndex >= g_MasterServerManager->m_vRemoteServers[serverIndex].requiredMods.size())
+ if (modIndex >= g_pMasterServerManager->m_vRemoteServers[serverIndex].requiredMods.size())
{
g_pUISquirrel->raiseerror(
sqvm,
fmt::format(
"Tried to get required mod name of mod index {} when only {} mod are available",
modIndex,
- g_MasterServerManager->m_vRemoteServers[serverIndex].requiredMods.size())
+ g_pMasterServerManager->m_vRemoteServers[serverIndex].requiredMods.size())
.c_str());
return SQRESULT_ERROR;
}
- g_pUISquirrel->pushstring(sqvm, g_MasterServerManager->m_vRemoteServers[serverIndex].requiredMods[modIndex].Name.c_str());
+ g_pUISquirrel->pushstring(sqvm, g_pMasterServerManager->m_vRemoteServers[serverIndex].requiredMods[modIndex].Name.c_str());
return SQRESULT_NOTNULL;
}
@@ -271,38 +271,38 @@ SQRESULT SQ_GetServerRequiredModVersion(void* sqvm)
SQInteger serverIndex = g_pUISquirrel->getinteger(sqvm, 1);
SQInteger modIndex = g_pUISquirrel->getinteger(sqvm, 2);
- if (serverIndex >= g_MasterServerManager->m_vRemoteServers.size())
+ if (serverIndex >= g_pMasterServerManager->m_vRemoteServers.size())
{
g_pUISquirrel->raiseerror(
sqvm,
fmt::format(
"Tried to get required mod version of server index {} when only {} servers are available",
serverIndex,
- g_MasterServerManager->m_vRemoteServers.size())
+ g_pMasterServerManager->m_vRemoteServers.size())
.c_str());
return SQRESULT_ERROR;
}
- if (modIndex >= g_MasterServerManager->m_vRemoteServers[serverIndex].requiredMods.size())
+ if (modIndex >= g_pMasterServerManager->m_vRemoteServers[serverIndex].requiredMods.size())
{
g_pUISquirrel->raiseerror(
sqvm,
fmt::format(
"Tried to get required mod version of mod index {} when only {} mod are available",
modIndex,
- g_MasterServerManager->m_vRemoteServers[serverIndex].requiredMods.size())
+ g_pMasterServerManager->m_vRemoteServers[serverIndex].requiredMods.size())
.c_str());
return SQRESULT_ERROR;
}
- g_pUISquirrel->pushstring(sqvm, g_MasterServerManager->m_vRemoteServers[serverIndex].requiredMods[modIndex].Version.c_str());
+ g_pUISquirrel->pushstring(sqvm, g_pMasterServerManager->m_vRemoteServers[serverIndex].requiredMods[modIndex].Version.c_str());
return SQRESULT_NOTNULL;
}
// void function NSClearRecievedServerList()
SQRESULT SQ_ClearRecievedServerList(void* sqvm)
{
- g_MasterServerManager->ClearServerList();
+ g_pMasterServerManager->ClearServerList();
return SQRESULT_NULL;
}
@@ -314,28 +314,28 @@ SQRESULT SQ_TryAuthWithServer(void* sqvm)
SQInteger serverIndex = g_pUISquirrel->getinteger(sqvm, 1);
const SQChar* password = g_pUISquirrel->getstring(sqvm, 2);
- if (serverIndex >= g_MasterServerManager->m_vRemoteServers.size())
+ if (serverIndex >= g_pMasterServerManager->m_vRemoteServers.size())
{
g_pUISquirrel->raiseerror(
sqvm,
fmt::format(
"Tried to auth with server index {} when only {} servers are available",
serverIndex,
- g_MasterServerManager->m_vRemoteServers.size())
+ g_pMasterServerManager->m_vRemoteServers.size())
.c_str());
return SQRESULT_ERROR;
}
// send off persistent data first, don't worry about server/client stuff, since m_additionalPlayerData should only have entries when
// we're a local server note: this seems like it could create a race condition, test later
- for (auto& pair : g_pServerAuthenticationManager->m_additionalPlayerData)
- g_pServerAuthenticationManager->WritePersistentData(pair.first);
+ for (auto& pair : g_pServerAuthentication->m_PlayerAuthenticationData)
+ g_pServerAuthentication->WritePersistentData(pair.first);
// do auth
- g_MasterServerManager->AuthenticateWithServer(
+ g_pMasterServerManager->AuthenticateWithServer(
R2::g_pLocalPlayerUserID,
- g_MasterServerManager->m_sOwnClientAuthToken,
- g_MasterServerManager->m_vRemoteServers[serverIndex].id,
+ g_pMasterServerManager->m_sOwnClientAuthToken,
+ g_pMasterServerManager->m_vRemoteServers[serverIndex].id,
(char*)password);
return SQRESULT_NULL;
@@ -344,28 +344,28 @@ SQRESULT SQ_TryAuthWithServer(void* sqvm)
// bool function NSIsAuthenticatingWithServer()
SQRESULT SQ_IsAuthComplete(void* sqvm)
{
- g_pUISquirrel->pushbool(sqvm, g_MasterServerManager->m_bScriptAuthenticatingWithGameServer);
+ g_pUISquirrel->pushbool(sqvm, g_pMasterServerManager->m_bScriptAuthenticatingWithGameServer);
return SQRESULT_NOTNULL;
}
// bool function NSWasAuthSuccessful()
SQRESULT SQ_WasAuthSuccessful(void* sqvm)
{
- g_pUISquirrel->pushbool(sqvm, g_MasterServerManager->m_bSuccessfullyAuthenticatedWithGameServer);
+ g_pUISquirrel->pushbool(sqvm, g_pMasterServerManager->m_bSuccessfullyAuthenticatedWithGameServer);
return SQRESULT_NOTNULL;
}
// void function NSConnectToAuthedServer()
SQRESULT SQ_ConnectToAuthedServer(void* sqvm)
{
- if (!g_MasterServerManager->m_bHasPendingConnectionInfo)
+ if (!g_pMasterServerManager->m_bHasPendingConnectionInfo)
{
g_pUISquirrel->raiseerror(
sqvm, fmt::format("Tried to connect to authed server before any pending connection info was available").c_str());
return SQRESULT_ERROR;
}
- RemoteServerConnectionInfo info = g_MasterServerManager->m_pendingConnectionInfo;
+ RemoteServerConnectionInfo info = g_pMasterServerManager->m_pendingConnectionInfo;
// set auth token, then try to connect
// i'm honestly not entirely sure how silentconnect works regarding ports and encryption so using connect for now
@@ -383,7 +383,7 @@ SQRESULT SQ_ConnectToAuthedServer(void* sqvm)
.c_str(),
R2::cmd_source_t::kCommandSrcCode);
- g_MasterServerManager->m_bHasPendingConnectionInfo = false;
+ g_pMasterServerManager->m_bHasPendingConnectionInfo = false;
return SQRESULT_NULL;
}
@@ -391,7 +391,7 @@ SQRESULT SQ_ConnectToAuthedServer(void* sqvm)
SQRESULT SQ_TryAuthWithLocalServer(void* sqvm)
{
// do auth request
- g_MasterServerManager->AuthenticateWithOwnServer(R2::g_pLocalPlayerUserID, g_MasterServerManager->m_sOwnClientAuthToken);
+ g_pMasterServerManager->AuthenticateWithOwnServer(R2::g_pLocalPlayerUserID, g_pMasterServerManager->m_sOwnClientAuthToken);
return SQRESULT_NULL;
}
@@ -403,7 +403,7 @@ SQRESULT SQ_CompleteAuthWithLocalServer(void* sqvm)
// note: this assumes we have no authdata other than our own
R2::Cbuf_AddText(
R2::Cbuf_GetCurrentPlayer(),
- fmt::format("serverfilter {}", g_pServerAuthenticationManager->m_authData.begin()->first).c_str(),
+ fmt::format("serverfilter {}", g_pServerAuthentication->m_RemoteAuthenticationData.begin()->first).c_str(),
R2::cmd_source_t::kCommandSrcCode);
return SQRESULT_NULL;
diff --git a/NorthstarDLL/serverauthentication.cpp b/NorthstarDLL/serverauthentication.cpp
index 7dc840a1..350999fb 100644
--- a/NorthstarDLL/serverauthentication.cpp
+++ b/NorthstarDLL/serverauthentication.cpp
@@ -1,11 +1,11 @@
#include "pch.h"
#include "serverauthentication.h"
+#include "limits.h"
#include "cvar.h"
#include "convar.h"
#include "masterserver.h"
#include "hoststate.h"
#include "bansystem.h"
-#include "miscserverscript.h"
#include "concommand.h"
#include "dedicated.h"
#include "nsprefix.h"
@@ -26,35 +26,17 @@ AUTOHOOK_INIT()
const char* AUTHSERVER_VERIFY_STRING = "I am a northstar server!";
// global vars
-ServerAuthenticationManager* g_pServerAuthenticationManager;
-
-ConVar* Cvar_ns_player_auth_port;
-ConVar* Cvar_ns_erase_auth_info;
-ConVar* CVar_ns_auth_allow_insecure;
-ConVar* CVar_ns_auth_allow_insecure_write;
-ConVar* CVar_sv_quota_stringcmdspersecond;
-ConVar* Cvar_net_chan_limit_mode;
-ConVar* Cvar_net_chan_limit_msec_per_sec;
-ConVar* Cvar_sv_querylimit_per_sec;
-ConVar* Cvar_sv_max_chat_messages_per_sec;
-
-ConVar* Cvar_net_datablock_enabled;
-
-// use the R2 namespace for game funcs
-namespace R2
-{
- void (*CBaseClient__Disconnect)(void* self, uint32_t unknownButAlways1, const char* reason, ...);
-} // namespace R2
+ServerAuthenticationManager* g_pServerAuthentication;
void ServerAuthenticationManager::StartPlayerAuthServer()
{
- if (m_runningPlayerAuthThread)
+ if (m_bRunningPlayerAuthThread)
{
- spdlog::warn("ServerAuthenticationManager::StartPlayerAuthServer was called while m_runningPlayerAuthThread is true");
+ spdlog::warn("ServerAuthenticationManager::StartPlayerAuthServer was called while m_bRunningPlayerAuthThread is true");
return;
}
- m_runningPlayerAuthThread = true;
+ m_bRunningPlayerAuthThread = true;
// listen is a blocking call so thread this
std::thread serverThread(
@@ -62,19 +44,19 @@ void ServerAuthenticationManager::StartPlayerAuthServer()
{
// this is just a super basic way to verify that servers have ports open, masterserver will try to read this before ensuring
// server is legit
- m_playerAuthServer.Get(
+ m_PlayerAuthServer.Get(
"/verify",
[](const httplib::Request& request, httplib::Response& response)
{ response.set_content(AUTHSERVER_VERIFY_STRING, "text/plain"); });
- m_playerAuthServer.Post(
+ m_PlayerAuthServer.Post(
"/authenticate_incoming_player",
[this](const httplib::Request& request, httplib::Response& response)
{
- if (!request.has_param("id") || !request.has_param("authToken") || request.body.size() >= 65335 ||
+ if (!request.has_param("id") || !request.has_param("authToken") || request.body.size() >= R2::PERSISTENCE_MAX_SIZE ||
!request.has_param("serverAuthToken") ||
strcmp(
- g_MasterServerManager->m_sOwnServerAuthToken,
+ g_pMasterServerManager->m_sOwnServerAuthToken,
request.get_param_value("serverAuthToken")
.c_str()))
{
@@ -82,7 +64,7 @@ void ServerAuthenticationManager::StartPlayerAuthServer()
return;
}
- AuthData newAuthData {};
+ RemoteAuthData newAuthData {};
strncpy(newAuthData.uid, request.get_param_value("id").c_str(), sizeof(newAuthData.uid));
newAuthData.uid[sizeof(newAuthData.uid) - 1] = 0;
@@ -93,13 +75,13 @@ void ServerAuthenticationManager::StartPlayerAuthServer()
newAuthData.pdata = new char[newAuthData.pdataSize];
memcpy(newAuthData.pdata, request.body.c_str(), newAuthData.pdataSize);
- std::lock_guard<std::mutex> guard(m_authDataMutex);
- m_authData.insert(std::make_pair(request.get_param_value("authToken"), newAuthData));
+ std::lock_guard<std::mutex> guard(m_AuthDataMutex);
+ m_RemoteAuthenticationData.insert(std::make_pair(request.get_param_value("authToken"), newAuthData));
response.set_content("{\"success\":true}", "application/json");
});
- m_playerAuthServer.listen("0.0.0.0", Cvar_ns_player_auth_port->GetInt());
+ m_PlayerAuthServer.listen("0.0.0.0", Cvar_ns_player_auth_port->GetInt());
});
serverThread.detach();
@@ -107,27 +89,36 @@ void ServerAuthenticationManager::StartPlayerAuthServer()
void ServerAuthenticationManager::StopPlayerAuthServer()
{
- if (!m_runningPlayerAuthThread)
+ if (!m_bRunningPlayerAuthThread)
{
- spdlog::warn("ServerAuthenticationManager::StopPlayerAuthServer was called while m_runningPlayerAuthThread is false");
+ spdlog::warn("ServerAuthenticationManager::StopPlayerAuthServer was called while m_bRunningPlayerAuthThread is false");
return;
}
- m_runningPlayerAuthThread = false;
- m_playerAuthServer.stop();
+ m_bRunningPlayerAuthThread = false;
+ m_PlayerAuthServer.stop();
+}
+
+void ServerAuthenticationManager::AddPlayerData(R2::CBasePlayer* player, const char* pToken)
+{
+ PlayerAuthenticationData additionalData;
+ additionalData.pdataSize = m_RemoteAuthenticationData[pToken].pdataSize;
+ additionalData.usingLocalPdata = player->m_iPersistenceReady == R2::ePersistenceReady::READY_LOCAL;
+
+ m_PlayerAuthenticationData.insert(std::make_pair(player, additionalData));
}
-char* ServerAuthenticationManager::VerifyPlayerName(void* player, char* authToken, char* name)
+void ServerAuthenticationManager::VerifyPlayerName(R2::CBasePlayer* player, char* authToken, char* name)
{
- std::lock_guard<std::mutex> guard(m_authDataMutex);
+ std::lock_guard<std::mutex> guard(m_AuthDataMutex);
- if (!m_authData.empty() && m_authData.count(std::string(authToken)))
+ if (!m_RemoteAuthenticationData.empty() && m_RemoteAuthenticationData.count(std::string(authToken)))
{
- AuthData authData = m_authData[authToken];
+ RemoteAuthData authData = m_RemoteAuthenticationData[authToken];
bool nameAccepted = (!*authData.username || !strcmp(name, authData.username));
- if (!nameAccepted && g_MasterServerManager->m_bRequireClientAuth && !CVar_ns_auth_allow_insecure->GetInt())
+ if (!nameAccepted && g_pMasterServerManager->m_bRequireClientAuth && !CVar_ns_auth_allow_insecure->GetInt())
{
// limit name length to 64 characters just in case something changes, this technically shouldn't be needed given the master
// server gets usernames from origin but we have it just in case
@@ -135,25 +126,24 @@ char* ServerAuthenticationManager::VerifyPlayerName(void* player, char* authToke
name[63] = 0;
}
}
- return name;
}
-bool ServerAuthenticationManager::AuthenticatePlayer(void* player, int64_t uid, char* authToken)
+bool ServerAuthenticationManager::AuthenticatePlayer(R2::CBasePlayer* player, uint64_t uid, char* authToken)
{
std::string strUid = std::to_string(uid);
- std::lock_guard<std::mutex> guard(m_authDataMutex);
+ std::lock_guard<std::mutex> guard(m_AuthDataMutex);
bool authFail = true;
- if (!m_authData.empty() && m_authData.count(std::string(authToken)))
+ if (!m_RemoteAuthenticationData.empty() && m_RemoteAuthenticationData.count(std::string(authToken)))
{
// use stored auth data
- AuthData authData = m_authData[authToken];
+ RemoteAuthData authData = m_RemoteAuthenticationData[authToken];
if (!strcmp(strUid.c_str(), authData.uid)) // connecting client's uid is the same as auth's uid
{
authFail = false;
// uuid
- strcpy((char*)player + 0xF500, strUid.c_str());
+ strcpy(player->m_UID, strUid.c_str());
// reset from disk if we're doing that
if (m_bForceReadLocalPlayerPersistenceFromDisk && !strcmp(authData.uid, R2::g_pLocalPlayerUserID))
@@ -168,33 +158,35 @@ bool ServerAuthenticationManager::AuthenticatePlayer(void* player, int64_t uid,
pdataStream.seekg(0, pdataStream.beg);
// copy pdata into buffer
- pdataStream.read((char*)player + 0x4FA, length);
+ pdataStream.read(player->m_PersistenceBuffer, length);
}
else // fallback to remote pdata if no local default
- memcpy((char*)player + 0x4FA, authData.pdata, authData.pdataSize);
+ memcpy(player->m_PersistenceBuffer, authData.pdata, authData.pdataSize);
}
else
{
// copy pdata into buffer
- memcpy((char*)player + 0x4FA, authData.pdata, authData.pdataSize);
+ memcpy(player->m_PersistenceBuffer, authData.pdata, authData.pdataSize);
}
- // set persistent data as ready, we use 0x4 internally to mark the client as using remote persistence
- *((char*)player + 0x4a0) = (char)0x4;
+ // set persistent data as ready
+ player->m_iPersistenceReady = R2::ePersistenceReady::READY_REMOTE;
}
}
if (authFail)
{
- // set persistent data as ready, we use 0x3 internally to mark the client as using local persistence
- *((char*)player + 0x4a0) = (char)0x3;
+ // set persistent data as ready
+ player->m_iPersistenceReady = R2::ePersistenceReady::READY_LOCAL;
+ return CVar_ns_auth_allow_insecure->GetBool();
+
- if (!CVar_ns_auth_allow_insecure->GetBool()) // no auth data and insecure connections aren't allowed, so dc the client
- return false;
+ // logic needs an overhaul as it is bad and shit
+ // todo: if need default pdata, we should populate in script using InitPersistentData() and just null it out here
// insecure connections are allowed, try reading from disk
// uuid
- strcpy((char*)player + 0xF500, strUid.c_str());
+ /* strcpy((char*)player + 0xF500, strUid.c_str());
// try reading pdata file for player
std::string pdataPath = GetNorthstarPrefix() + "/playerdata_";
@@ -213,32 +205,32 @@ bool ServerAuthenticationManager::AuthenticatePlayer(void* player, int64_t uid,
// copy pdata into buffer
pdataStream.read((char*)player + 0x4FA, length);
- pdataStream.close();
+ pdataStream.close();*/
}
return true; // auth successful, client stays on
}
-bool ServerAuthenticationManager::RemovePlayerAuthData(void* player)
+bool ServerAuthenticationManager::RemovePlayerAuthData(R2::CBasePlayer* player)
{
- if (!Cvar_ns_erase_auth_info->GetBool())
+ if (!Cvar_ns_erase_auth_info->GetBool()) // keep auth data forever
return false;
// hack for special case where we're on a local server, so we erase our own newly created auth data on disconnect
- if (m_bNeedLocalAuthForNewgame && !strcmp((char*)player + 0xF500, R2::g_pLocalPlayerUserID))
+ if (m_bNeedLocalAuthForNewgame && !strcmp(player->m_UID, R2::g_pLocalPlayerUserID))
return false;
// we don't have our auth token at this point, so lookup authdata by uid
- for (auto& auth : m_authData)
+ for (auto& auth : m_RemoteAuthenticationData)
{
- if (!strcmp((char*)player + 0xF500, auth.second.uid))
+ if (!strcmp(player->m_UID, auth.second.uid))
{
// pretty sure this is fine, since we don't iterate after the erase
// i think if we iterated after it'd be undefined behaviour tho
- std::lock_guard<std::mutex> guard(m_authDataMutex);
+ std::lock_guard<std::mutex> guard(m_AuthDataMutex);
delete[] auth.second.pdata;
- m_authData.erase(auth.first);
+ m_RemoteAuthenticationData.erase(auth.first);
return true;
}
}
@@ -246,13 +238,12 @@ bool ServerAuthenticationManager::RemovePlayerAuthData(void* player)
return false;
}
-void ServerAuthenticationManager::WritePersistentData(void* player)
+void ServerAuthenticationManager::WritePersistentData(R2::CBasePlayer* player)
{
- // we use 0x4 internally to mark clients as using remote persistence
- if (*((char*)player + 0x4A0) == (char)0x4)
+ if (player->m_iPersistenceReady == R2::ePersistenceReady::READY_REMOTE)
{
- g_MasterServerManager->WritePlayerPersistentData(
- (char*)player + 0xF500, (char*)player + 0x4FA, m_additionalPlayerData[player].pdataSize);
+ g_pMasterServerManager->WritePlayerPersistentData(
+ player->m_UID, (const char*)player->m_PersistenceBuffer, m_PlayerAuthenticationData[player].pdataSize);
}
else if (CVar_ns_auth_allow_insecure_write->GetBool())
{
@@ -260,25 +251,10 @@ void ServerAuthenticationManager::WritePersistentData(void* player)
}
}
-bool ServerAuthenticationManager::CheckPlayerChatRatelimit(void* player)
-{
- if (Tier0::Plat_FloatTime() - m_additionalPlayerData[player].lastSayTextLimitStart >= 1.0)
- {
- m_additionalPlayerData[player].lastSayTextLimitStart = Tier0::Plat_FloatTime();
- m_additionalPlayerData[player].sayTextLimitCount = 0;
- }
-
- if (m_additionalPlayerData[player].sayTextLimitCount >= Cvar_sv_max_chat_messages_per_sec->GetInt())
- return false;
-
- m_additionalPlayerData[player].sayTextLimitCount++;
- return true;
-}
-
// auth hooks
// store these in vars so we can use them in CBaseClient::Connect
-// this is fine because ptrs won't decay by the time we use this, just don't use it outside of cbaseclient::connect
+// this is fine because ptrs won't decay by the time we use this, just don't use it outside of calls from cbaseclient::connectclient
char* pNextPlayerToken;
uint64_t iNextPlayerUid;
@@ -310,19 +286,19 @@ void*,, (
}
AUTOHOOK(CBaseClient__Connect, engine.dll + 0x101740,
-bool,, (void* self, char* name, __int64 netchan_ptr_arg, char b_fake_player_arg, __int64 a5, char* Buffer, void* a7))
+bool,, (R2::CBasePlayer* self, char* name, __int64 netchan_ptr_arg, char b_fake_player_arg, __int64 a5, char* Buffer, void* a7))
{
// try changing name before all else
- name = g_pServerAuthenticationManager->VerifyPlayerName(self, pNextPlayerToken, name);
+ g_pServerAuthentication->VerifyPlayerName(self, pNextPlayerToken, name);
// try to auth player, dc if it fails
- // we connect irregardless of auth, because returning bad from this function can fuck client state p bad
+ // we connect regardless of auth, because returning bad from this function can fuck client state p bad
bool ret = CBaseClient__Connect(self, name, netchan_ptr_arg, b_fake_player_arg, a5, Buffer, a7);
if (!ret)
return ret;
- if (!g_ServerBanSystem->IsUIDAllowed(iNextPlayerUid))
+ if (!g_pServerBanSystem->IsUIDAllowed(iNextPlayerUid))
{
R2::CBaseClient__Disconnect(self, 1, "Banned from server");
return ret;
@@ -331,40 +307,34 @@ bool,, (void* self, char* name, __int64 netchan_ptr_arg, char b_fake_player_arg,
if (strlen(name) >= 64) // fix for name overflow bug
R2::CBaseClient__Disconnect(self, 1, "Invalid name");
else if (
- !g_pServerAuthenticationManager->AuthenticatePlayer(self, iNextPlayerUid, pNextPlayerToken) &&
- g_MasterServerManager->m_bRequireClientAuth)
+ !g_pServerAuthentication->AuthenticatePlayer(self, iNextPlayerUid, pNextPlayerToken) &&
+ g_pMasterServerManager->m_bRequireClientAuth)
R2::CBaseClient__Disconnect(self, 1, "Authentication Failed");
- if (!g_pServerAuthenticationManager->m_additionalPlayerData.count(self))
- {
- AdditionalPlayerData additionalData;
- additionalData.pdataSize = g_pServerAuthenticationManager->m_authData[pNextPlayerToken].pdataSize;
- additionalData.usingLocalPdata = *((char*)self + 0x4a0) == (char)0x3;
-
- g_pServerAuthenticationManager->m_additionalPlayerData.insert(std::make_pair(self, additionalData));
- }
+ g_pServerAuthentication->AddPlayerData(self, pNextPlayerToken);
+ g_pServerLimits->AddPlayer(self);
return ret;
}
AUTOHOOK(CBaseClient__ActivatePlayer, engine.dll + 0x100F80,
-void,, (void* self))
+void,, (R2::CBasePlayer* self))
{
// if we're authed, write our persistent data
// RemovePlayerAuthData returns true if it removed successfully, i.e. on first call only, and we only want to write on >= second call
// (since this func is called on map loads)
- if (*((char*)self + 0x4A0) >= (char)0x3 && !g_pServerAuthenticationManager->RemovePlayerAuthData(self))
+ if (self->m_iPersistenceReady >= R2::ePersistenceReady::READY && !g_pServerAuthentication->RemovePlayerAuthData(self))
{
- g_pServerAuthenticationManager->m_bForceReadLocalPlayerPersistenceFromDisk = false;
- g_pServerAuthenticationManager->WritePersistentData(self);
- g_MasterServerManager->UpdateServerPlayerCount(g_pServerAuthenticationManager->m_additionalPlayerData.size());
+ g_pServerAuthentication->m_bForceReadLocalPlayerPersistenceFromDisk = false;
+ g_pServerAuthentication->WritePersistentData(self);
+ g_pMasterServerManager->UpdateServerPlayerCount(g_pServerAuthentication->m_PlayerAuthenticationData.size());
}
CBaseClient__ActivatePlayer(self);
}
AUTOHOOK(_CBaseClient__Disconnect, engine.dll + 0x1012C0,
-void,, (void* self, uint32_t unknownButAlways1, const char* pReason, ...))
+void,, (R2::CBasePlayer* self, uint32_t unknownButAlways1, const char* pReason, ...))
{
// have to manually format message because can't pass varargs to original func
char buf[1024];
@@ -377,184 +347,23 @@ void,, (void* self, uint32_t unknownButAlways1, const char* pReason, ...))
// this reason is used while connecting to a local server, hacky, but just ignore it
if (strcmp(pReason, "Connection closing"))
{
- spdlog::info("Player {} disconnected: \"{}\"", (char*)self + 0x16, buf);
+ spdlog::info("Player {} disconnected: \"{}\"", self->m_Name, buf);
// dcing, write persistent data
- if (g_pServerAuthenticationManager->m_additionalPlayerData[self].needPersistenceWriteOnLeave)
- g_pServerAuthenticationManager->WritePersistentData(self);
- g_pServerAuthenticationManager->RemovePlayerAuthData(self); // won't do anything 99% of the time, but just in case
+ if (g_pServerAuthentication->m_PlayerAuthenticationData[self].needPersistenceWriteOnLeave)
+ g_pServerAuthentication->WritePersistentData(self);
+ g_pServerAuthentication->RemovePlayerAuthData(self); // won't do anything 99% of the time, but just in case
}
- if (g_pServerAuthenticationManager->m_additionalPlayerData.count(self))
+ if (g_pServerAuthentication->m_PlayerAuthenticationData.count(self))
{
- g_pServerAuthenticationManager->m_additionalPlayerData.erase(self);
- g_MasterServerManager->UpdateServerPlayerCount(g_pServerAuthenticationManager->m_additionalPlayerData.size());
+ g_pServerAuthentication->m_PlayerAuthenticationData.erase(self);
+ g_pMasterServerManager->UpdateServerPlayerCount(g_pServerAuthentication->m_PlayerAuthenticationData.size());
}
_CBaseClient__Disconnect(self, unknownButAlways1, buf);
}
-// maybe this should be done outside of auth code, but effort to refactor rn and it sorta fits
-bool (*CCommand__Tokenize)(CCommand& self, const char* pCommandString, R2::cmd_source_t commandSource);
-
-AUTOHOOK(CGameClient__ExecuteStringCommand, engine.dll + 0x1022E0,
-char,, (void* self, uint32_t unknown, const char* pCommandString))
-{
- if (CVar_sv_quota_stringcmdspersecond->GetInt() != -1)
- {
- // note: this isn't super perfect, legit clients can trigger it in lobby, mostly good enough tho imo
- // https://github.com/perilouswithadollarsign/cstrike15_src/blob/f82112a2388b841d72cb62ca48ab1846dfcc11c8/engine/sv_client.cpp#L1513
- if (Tier0::Plat_FloatTime() - g_pServerAuthenticationManager->m_additionalPlayerData[self].lastClientCommandQuotaStart >= 1.0)
- {
- // reset quota
- g_pServerAuthenticationManager->m_additionalPlayerData[self].lastClientCommandQuotaStart = Tier0::Plat_FloatTime();
- g_pServerAuthenticationManager->m_additionalPlayerData[self].numClientCommandsInQuota = 0;
- }
-
- g_pServerAuthenticationManager->m_additionalPlayerData[self].numClientCommandsInQuota++;
- if (g_pServerAuthenticationManager->m_additionalPlayerData[self].numClientCommandsInQuota >
- CVar_sv_quota_stringcmdspersecond->GetInt())
- {
- // too many stringcmds, dc player
- R2::CBaseClient__Disconnect(self, 1, "Sent too many stringcmd commands");
- return false;
- }
- }
-
- // verify the command we're trying to execute is FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS, if it's a concommand
- char* commandBuf[1040]; // assumedly this is the size of CCommand since we don't have an actual constructor
- memset(commandBuf, 0, sizeof(commandBuf));
- CCommand tempCommand = *(CCommand*)&commandBuf;
-
- if (!CCommand__Tokenize(tempCommand, pCommandString, R2::cmd_source_t::kCommandSrcCode) || !tempCommand.ArgC())
- return false;
-
- ConCommand* command = R2::g_pCVar->FindCommand(tempCommand.Arg(0));
-
- // if the command doesn't exist pass it on to ExecuteStringCommand for script clientcommands and stuff
- if (command && !command->IsFlagSet(FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS))
- {
- // ensure FCVAR_GAMEDLL concommands without FCVAR_GAMEDLL_FOR_REMOTE_CLIENTS can't be executed by remote clients
- if (IsDedicatedServer())
- return false;
-
- if (strcmp((char*)self + 0xF500, R2::g_pLocalPlayerUserID))
- return false;
- }
-
- return CGameClient__ExecuteStringCommand(self, unknown, pCommandString);
-}
-
-bool bWasWritingStringTableSuccessful;
-
-AUTOHOOK(CBaseClient__SendServerInfo, engine.dll + 0x104FB0,
-void,, (void* self))
-{
- bWasWritingStringTableSuccessful = true;
- CBaseClient__SendServerInfo(self);
- if (!bWasWritingStringTableSuccessful)
- R2::CBaseClient__Disconnect(
- self, 1, "Overflowed CNetworkStringTableContainer::WriteBaselines, try restarting your client and reconnecting");
-}
-
-AUTOHOOK(CNetChan___ProcessMessages, engine.dll + 0x2140A0,
-char, __fastcall, (void* self, void* buf))
-{
- double startTime = Tier0::Plat_FloatTime();
- char ret = CNetChan___ProcessMessages(self, buf);
-
- // check processing limits, unless we're in a level transition
- if (R2::g_pHostState->m_iCurrentState == R2::HostState_t::HS_RUN && Tier0::ThreadInServerFrameThread())
- {
- // player that sent the message
- void* sender = *(void**)((char*)self + 368);
-
- // if no sender, return
- // relatively certain this is fine?
- if (!sender || !g_pServerAuthenticationManager->m_additionalPlayerData.count(sender))
- return ret;
-
- // reset every second
- if (startTime - g_pServerAuthenticationManager->m_additionalPlayerData[sender].lastNetChanProcessingLimitStart >= 1.0 ||
- g_pServerAuthenticationManager->m_additionalPlayerData[sender].lastNetChanProcessingLimitStart == -1.0)
- {
- g_pServerAuthenticationManager->m_additionalPlayerData[sender].lastNetChanProcessingLimitStart = startTime;
- g_pServerAuthenticationManager->m_additionalPlayerData[sender].netChanProcessingLimitTime = 0.0;
- }
- g_pServerAuthenticationManager->m_additionalPlayerData[sender].netChanProcessingLimitTime +=
- (Tier0::Plat_FloatTime() * 1000) - (startTime * 1000);
-
- if (g_pServerAuthenticationManager->m_additionalPlayerData[sender].netChanProcessingLimitTime >=
- Cvar_net_chan_limit_msec_per_sec->GetInt())
- {
- spdlog::warn(
- "Client {} hit netchan processing limit with {}ms of processing time this second (max is {})",
- (char*)sender + 0x16,
- g_pServerAuthenticationManager->m_additionalPlayerData[sender].netChanProcessingLimitTime,
- Cvar_net_chan_limit_msec_per_sec->GetInt());
-
- // nonzero = kick, 0 = warn, but never kick local player
- if (Cvar_net_chan_limit_mode->GetInt() && strcmp(R2::g_pLocalPlayerUserID, (char*)sender + 0xF500))
- {
- R2::CBaseClient__Disconnect(sender, 1, "Exceeded net channel processing limit");
- return false;
- }
- }
- }
-
- return ret;
-}
-
-AUTOHOOK(ProcessConnectionlessPacket, engine.dll + 0x117800,
-bool,, (void* a1, netpacket_t* packet))
-{
- if (packet->adr.type == NA_IP &&
- (!(packet->data[4] == 'N' && Cvar_net_datablock_enabled->GetBool()) || !Cvar_net_datablock_enabled->GetBool()))
- {
- // bad lookup: optimise later tm
- UnconnectedPlayerSendData* sendData = nullptr;
- for (UnconnectedPlayerSendData& foundSendData : g_pServerAuthenticationManager->m_unconnectedPlayerSendData)
- {
- if (!memcmp(packet->adr.ip, foundSendData.ip, 16))
- {
- sendData = &foundSendData;
- break;
- }
- }
-
- if (!sendData)
- {
- sendData = &g_pServerAuthenticationManager->m_unconnectedPlayerSendData.emplace_back();
- memcpy(sendData->ip, packet->adr.ip, 16);
- }
-
- if (Tier0::Plat_FloatTime() < sendData->timeoutEnd)
- return false;
-
- if (Tier0::Plat_FloatTime() - sendData->lastQuotaStart >= 1.0)
- {
- sendData->lastQuotaStart = Tier0::Plat_FloatTime();
- sendData->packetCount = 0;
- }
-
- sendData->packetCount++;
-
- if (sendData->packetCount >= Cvar_sv_querylimit_per_sec->GetInt())
- {
- spdlog::warn(
- "Client went over connectionless ratelimit of {} per sec with packet of type {}",
- Cvar_sv_querylimit_per_sec->GetInt(),
- packet->data[4]);
-
- // timeout for a minute
- sendData->timeoutEnd = Tier0::Plat_FloatTime() + 60.0;
- return false;
- }
- }
-
- return ProcessConnectionlessPacket(a1, packet);
-}
-
void ConCommand_ns_resetpersistence(const CCommand& args)
{
if (*R2::g_pServerState == R2::server_state_t::ss_active)
@@ -564,49 +373,28 @@ void ConCommand_ns_resetpersistence(const CCommand& args)
}
spdlog::info("resetting persistence on next lobby load...");
- g_pServerAuthenticationManager->m_bForceReadLocalPlayerPersistenceFromDisk = true;
+ g_pServerAuthentication->m_bForceReadLocalPlayerPersistenceFromDisk = true;
}
ON_DLL_LOAD_RELIESON("engine.dll", ServerAuthentication, ConCommand, (HMODULE baseAddress))
{
AUTOHOOK_DISPATCH()
- g_pServerAuthenticationManager = new ServerAuthenticationManager;
+ g_pServerAuthentication = new ServerAuthenticationManager;
- Cvar_ns_erase_auth_info =
+ g_pServerAuthentication->Cvar_ns_player_auth_port = new ConVar("ns_player_auth_port", "8081", FCVAR_GAMEDLL, "");
+ g_pServerAuthentication->Cvar_ns_erase_auth_info =
new ConVar("ns_erase_auth_info", "1", FCVAR_GAMEDLL, "Whether auth info should be erased from this server on disconnect or crash");
- CVar_ns_auth_allow_insecure =
+ g_pServerAuthentication->CVar_ns_auth_allow_insecure =
new ConVar("ns_auth_allow_insecure", "0", FCVAR_GAMEDLL, "Whether this server will allow unauthenicated players to connect");
- CVar_ns_auth_allow_insecure_write = new ConVar(
+ g_pServerAuthentication->CVar_ns_auth_allow_insecure_write = new ConVar(
"ns_auth_allow_insecure_write",
"0",
FCVAR_GAMEDLL,
- "Whether the pdata of unauthenticated clients will be written to disk when changed");
- // literally just stolen from a fix valve used in csgo
- CVar_sv_quota_stringcmdspersecond = new ConVar(
- "sv_quota_stringcmdspersecond",
- "60",
- FCVAR_GAMEDLL,
- "How many string commands per second clients are allowed to submit, 0 to disallow all string commands");
- // https://blog.counter-strike.net/index.php/2019/07/24922/ but different because idk how to check what current tick number is
- Cvar_net_chan_limit_mode =
- new ConVar("net_chan_limit_mode", "0", FCVAR_GAMEDLL, "The mode for netchan processing limits: 0 = log, 1 = kick");
- Cvar_net_chan_limit_msec_per_sec = new ConVar(
- "net_chan_limit_msec_per_sec",
- "0",
- FCVAR_GAMEDLL,
- "Netchannel processing is limited to so many milliseconds, abort connection if exceeding budget");
- Cvar_ns_player_auth_port = new ConVar("ns_player_auth_port", "8081", FCVAR_GAMEDLL, "");
- Cvar_sv_querylimit_per_sec = new ConVar("sv_querylimit_per_sec", "15", FCVAR_GAMEDLL, "");
- Cvar_sv_max_chat_messages_per_sec = new ConVar("sv_max_chat_messages_per_sec", "5", FCVAR_GAMEDLL, "");
-
- Cvar_net_datablock_enabled = R2::g_pCVar->FindVar("net_datablock_enabled");
+ "Whether the pdata of unauthenticated clients will be written to disk when changed");
RegisterConCommand(
"ns_resetpersistence", ConCommand_ns_resetpersistence, "resets your pdata when you next enter the lobby", FCVAR_NONE);
-
- R2::CBaseClient__Disconnect = (void(*)(void*, uint32_t, const char*, ...))((char*)baseAddress + 0x1012C0);
- CCommand__Tokenize = (bool(*)(CCommand&, const char*, R2::cmd_source_t))((char*)baseAddress + 0x418380);
uintptr_t ba = (uintptr_t)baseAddress;
@@ -627,17 +415,4 @@ ON_DLL_LOAD_RELIESON("engine.dll", ServerAuthentication, ConCommand, (HMODULE ba
ba + 0x114510,
"EB" // jz => jmp
);
-
- // patch to set bWasWritingStringTableSuccessful in CNetworkStringTableContainer::WriteBaselines if it fails
- {
- uintptr_t writeAddress = (uintptr_t)(&bWasWritingStringTableSuccessful - (ba + 0x234EDC));
-
- auto addr = ba + 0x234ED2;
- NSMem::BytePatch(addr, "C7 05");
- NSMem::BytePatch(addr + 2, (BYTE*)&writeAddress, sizeof(writeAddress));
-
- NSMem::BytePatch(addr + 6, "00 00 00 00");
-
- NSMem::NOP(addr + 10, 5);
- }
} \ No newline at end of file
diff --git a/NorthstarDLL/serverauthentication.h b/NorthstarDLL/serverauthentication.h
index b70ba2cf..86b4594b 100644
--- a/NorthstarDLL/serverauthentication.h
+++ b/NorthstarDLL/serverauthentication.h
@@ -1,10 +1,11 @@
#pragma once
#include "convar.h"
#include "httplib.h"
+#include "r2server.h"
#include <unordered_map>
#include <string>
-struct AuthData
+struct RemoteAuthData
{
char uid[33];
char username[64];
@@ -14,98 +15,39 @@ struct AuthData
size_t pdataSize;
};
-struct AdditionalPlayerData
+struct PlayerAuthenticationData
{
bool usingLocalPdata;
size_t pdataSize;
bool needPersistenceWriteOnLeave = true;
-
- double lastClientCommandQuotaStart = -1.0;
- int numClientCommandsInQuota = 0;
-
- double lastNetChanProcessingLimitStart = -1.0;
- double netChanProcessingLimitTime = 0.0;
-
- double lastSayTextLimitStart = -1.0;
- int sayTextLimitCount = 0;
-};
-
-#pragma once
-typedef enum
-{
- NA_NULL = 0,
- NA_LOOPBACK,
- NA_IP,
-} netadrtype_t;
-
-#pragma pack(push, 1)
-typedef struct netadr_s
-{
- netadrtype_t type;
- unsigned char ip[16]; // IPv6
- // IPv4's 127.0.0.1 is [::ffff:127.0.0.1], that is:
- // 00 00 00 00 00 00 00 00 00 00 FF FF 7F 00 00 01
- unsigned short port;
-} netadr_t;
-#pragma pack(pop)
-
-#pragma pack(push, 1)
-typedef struct netpacket_s
-{
- netadr_t adr; // sender address
- // int source; // received source
- char unk[10];
- double received_time;
- unsigned char* data; // pointer to raw packet data
- void* message; // easy bitbuf data access // 'inpacket.message' etc etc (pointer)
- char unk2[16];
- int size;
-
- // bf_read message; // easy bitbuf data access // 'inpacket.message' etc etc (pointer)
- // int size; // size in bytes
- // int wiresize; // size in bytes before decompression
- // bool stream; // was send as stream
- // struct netpacket_s* pNext; // for internal use, should be NULL in public
-} netpacket_t;
-#pragma pack(pop)
-
-struct UnconnectedPlayerSendData
-{
- char ip[16];
- double lastQuotaStart = 0.0;
- int packetCount = 0;
- double timeoutEnd = -1.0;
};
class ServerAuthenticationManager
{
private:
- httplib::Server m_playerAuthServer;
+ httplib::Server m_PlayerAuthServer;
public:
- std::mutex m_authDataMutex;
- std::unordered_map<std::string, AuthData> m_authData;
- std::unordered_map<void*, AdditionalPlayerData> m_additionalPlayerData;
- std::vector<UnconnectedPlayerSendData> m_unconnectedPlayerSendData;
- bool m_runningPlayerAuthThread = false;
+ ConVar* Cvar_ns_player_auth_port;
+ ConVar* Cvar_ns_erase_auth_info;
+ ConVar* CVar_ns_auth_allow_insecure;
+ ConVar* CVar_ns_auth_allow_insecure_write;
+
+ std::mutex m_AuthDataMutex;
+ std::unordered_map<std::string, RemoteAuthData> m_RemoteAuthenticationData;
+ std::unordered_map<R2::CBasePlayer*, PlayerAuthenticationData> m_PlayerAuthenticationData;
+ bool m_bRunningPlayerAuthThread = false;
bool m_bNeedLocalAuthForNewgame = false;
bool m_bForceReadLocalPlayerPersistenceFromDisk = false;
public:
void StartPlayerAuthServer();
void StopPlayerAuthServer();
- bool AuthenticatePlayer(void* player, int64_t uid, char* authToken);
- char* VerifyPlayerName(void* player, char* authToken, char* name);
- bool RemovePlayerAuthData(void* player);
- void WritePersistentData(void* player);
- bool CheckPlayerChatRatelimit(void* player);
+ void AddPlayerData(R2::CBasePlayer* player, const char* pToken);
+ bool AuthenticatePlayer(R2::CBasePlayer* player, uint64_t uid, char* authToken);
+ void VerifyPlayerName(R2::CBasePlayer* player, char* authToken, char* name);
+ bool RemovePlayerAuthData(R2::CBasePlayer* player);
+ void WritePersistentData(R2::CBasePlayer* player);
};
-// use the R2 namespace for game funcs
-namespace R2
-{
- extern void (*CBaseClient__Disconnect)(void* self, uint32_t unknownButAlways1, const char* reason, ...);
-} // namespace R2
-
-extern ServerAuthenticationManager* g_pServerAuthenticationManager;
-extern ConVar* Cvar_ns_player_auth_port;
+extern ServerAuthenticationManager* g_pServerAuthentication;
diff --git a/NorthstarDLL/serverchathooks.cpp b/NorthstarDLL/serverchathooks.cpp
index 8340948a..000c6eea 100644
--- a/NorthstarDLL/serverchathooks.cpp
+++ b/NorthstarDLL/serverchathooks.cpp
@@ -1,8 +1,8 @@
#include "pch.h"
#include "serverchathooks.h"
-#include "serverauthentication.h"
+#include "limits.h"
#include "squirrel.h"
-#include "miscserverscript.h"
+#include "r2server.h"
#include <rapidjson/document.h>
#include <rapidjson/stringbuffer.h>
@@ -11,7 +11,6 @@
AUTOHOOK_INIT()
class CServerGameDLL;
-class CBasePlayer;
class CRecipientFilter
{
@@ -23,11 +22,10 @@ CServerGameDLL* g_pServerGameDLL;
void(__fastcall* CServerGameDLL__OnReceivedSayTextMessage)(
CServerGameDLL* self, unsigned int senderPlayerId, const char* text, int channelId);
-CBasePlayer*(__fastcall* UTIL_PlayerByIndex)(int playerIndex);
void(__fastcall* CRecipientFilter__Construct)(CRecipientFilter* self);
void(__fastcall* CRecipientFilter__Destruct)(CRecipientFilter* self);
void(__fastcall* CRecipientFilter__AddAllPlayers)(CRecipientFilter* self);
-void(__fastcall* CRecipientFilter__AddRecipient)(CRecipientFilter* self, const CBasePlayer* player);
+void(__fastcall* CRecipientFilter__AddRecipient)(CRecipientFilter* self, const R2::CBasePlayer* player);
void(__fastcall* CRecipientFilter__MakeReliable)(CRecipientFilter* self);
void(__fastcall* UserMessageBegin)(CRecipientFilter* filter, const char* messagename);
@@ -38,7 +36,7 @@ void(__fastcall* MessageWriteBool)(bool bValue);
bool bShouldCallSayTextHook = false;
-AUTOHOOK(_CServerGameDLL__OnReceivedSayTextMessageHook, server.dll + 0x1595C0,
+AUTOHOOK(_CServerGameDLL__OnReceivedSayTextMessage, server.dll + 0x1595C0,
void,, (CServerGameDLL* self, unsigned int senderPlayerId, const char* text, bool isTeam))
{
// MiniHook doesn't allow calling the base function outside of anywhere but the hook function.
@@ -46,14 +44,14 @@ void,, (CServerGameDLL* self, unsigned int senderPlayerId, const char* text, boo
if (bShouldCallSayTextHook)
{
bShouldCallSayTextHook = false;
- _CServerGameDLL__OnReceivedSayTextMessageHook(self, senderPlayerId, text, isTeam);
+ _CServerGameDLL__OnReceivedSayTextMessage(self, senderPlayerId, text, isTeam);
return;
}
- void* sender = GetPlayerByIndex(senderPlayerId - 1);
+ R2::CBasePlayer* sender = R2::UTIL_PlayerByIndex(senderPlayerId - 1);
// check chat ratelimits
- if (!g_pServerAuthenticationManager->CheckPlayerChatRatelimit(sender))
+ if (!g_pServerLimits->CheckChatLimits(sender))
return;
if (g_pServerSquirrel->setupfunc("CServerGameDLL_ProcessMessageStartThread") != SQRESULT_ERROR)
@@ -64,7 +62,7 @@ void,, (CServerGameDLL* self, unsigned int senderPlayerId, const char* text, boo
g_pServerSquirrel->call(g_pServerSquirrel->sqvm2, 3);
}
else
- _CServerGameDLL__OnReceivedSayTextMessageHook(self, senderPlayerId, text, isTeam);
+ _CServerGameDLL__OnReceivedSayTextMessage(self, senderPlayerId, text, isTeam);
}
void ChatSendMessage(unsigned int playerIndex, const char* text, bool isteam)
@@ -80,10 +78,10 @@ void ChatSendMessage(unsigned int playerIndex, const char* text, bool isteam)
void ChatBroadcastMessage(int fromPlayerIndex, int toPlayerIndex, const char* text, bool isTeam, bool isDead, CustomMessageType messageType)
{
- CBasePlayer* toPlayer = NULL;
+ R2::CBasePlayer* toPlayer = NULL;
if (toPlayerIndex >= 0)
{
- toPlayer = UTIL_PlayerByIndex(toPlayerIndex + 1);
+ toPlayer = R2::UTIL_PlayerByIndex(toPlayerIndex + 1);
if (toPlayer == NULL)
return;
}
@@ -162,11 +160,10 @@ ON_DLL_LOAD_RELIESON("server.dll", ServerChatHooks, ServerSquirrel, (HMODULE bas
AUTOHOOK_DISPATCH_MODULE(server.dll)
CServerGameDLL__OnReceivedSayTextMessage = (void(__fastcall*)(CServerGameDLL*, unsigned int, const char*, int))((char*)baseAddress + 0x1595C0);
- UTIL_PlayerByIndex = (CBasePlayer*(__fastcall*)(int))((char*)baseAddress + 0x26AA10);
CRecipientFilter__Construct = (void(__fastcall*)(CRecipientFilter*))((char*)baseAddress + 0x1E9440);
CRecipientFilter__Destruct = (void(__fastcall*)(CRecipientFilter*))((char*)baseAddress + 0x1E9700);
CRecipientFilter__AddAllPlayers = (void(__fastcall*)(CRecipientFilter*))((char*)baseAddress + 0x1E9940);
- CRecipientFilter__AddRecipient = (void(__fastcall*)(CRecipientFilter*, const CBasePlayer*))((char*)baseAddress + 0x1E9b30);
+ CRecipientFilter__AddRecipient = (void(__fastcall*)(CRecipientFilter*, const R2::CBasePlayer*))((char*)baseAddress + 0x1E9b30);
CRecipientFilter__MakeReliable = (void(__fastcall*)(CRecipientFilter*))((char*)baseAddress + 0x1EA4E0);
UserMessageBegin = (void(__fastcall*)(CRecipientFilter*, const char*))((char*)baseAddress + 0x15C520);