Skip to content

Commit fc78960

Browse files
committed
Reordered operations in plugin load and unload as well as adding new hooks and patches
1 parent 92d495a commit fc78960

1 file changed

Lines changed: 117 additions & 25 deletions

File tree

p2sm.cpp

Lines changed: 117 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include "p2sm.hpp"
99
#include "globals.hpp"
10+
#include "sdk.hpp"
1011
#include "scanner.hpp" // Memory scanner
1112

1213
#include "cdll_int.h" // Client interfacing
@@ -72,6 +73,72 @@ bool CP2SMPlusPlusPlugin::Load(CreateInterfaceFn interfaceFactory, CreateInterfa
7273
if (!hWnd)
7374
Log(WARNING, false, "Failed to find game window!");
7475

76+
// big ol' try catch because game has a TerminateProcess handler for exceptions...
77+
// why this wasn't here is mystifying, - 10/2024 NULLderef
78+
try {
79+
80+
Log(INFO, true, "Executing game patches...");
81+
#if _WIN32
82+
// When a player, both client or host, goes through a linked_portal_door entity in multiplayer, the host will crash. This fixes that.
83+
Log(INFO, true, "Fixing linked portal doors for multiplayer...");
84+
Memory::ReplacePattern("server", "0F B6 87 04 05 00 00 8B 16", "EB 14 87 04 05 00 00 8B 16");
85+
86+
// Increase runtime max from 0.03 to 0.05.
87+
// Helps add some more leeway to some things we do in VScript without the engine complaining and shutting down the rest of the script.
88+
Log(INFO, true, "Patching max runtime for VScript...");
89+
Memory::ReplacePattern("vscript", "00 00 00 E0 51 B8 9E 3F", "9a 99 99 99 99 99 a9 3f");
90+
#else // Linux Hooking. Due to the way this plugin is structured, it's currently not possible to compile this for Linux. Literally 1984 I know, but I don't have enough time or experience to figure it out by myself. One day.
91+
#endif
92+
93+
#if _WIN32
94+
// MinHook initialization and hooking.
95+
Log(INFO, true, "Initializing MinHook and hooking functions...");
96+
MH_Initialize();
97+
98+
// Hook the death think function so players can be spawned immediate when the p2sm_instantrespawn ConVar is on.
99+
Log(INFO, true, "Hooking CPortal_Player::PlayerDeathThink...");
100+
MH_CreateHook(
101+
Memory::Scanner::Scan(SERVERDLL, "53 8B DC 83 EC 08 83 E4 F0 83 C4 04 55 8B 6B ?? 89 6C 24 ?? 8B EC A1 ?? ?? ?? ?? F3 0F 10 40 ?? F3 0F 58 05 ?? ?? ?? ?? 83 EC 28 56 57 6A 00 51 8B F1 F3 0F 11 04 24 E8 ?? ?? ?? ?? 6A 03"),
102+
&CPortal_Player__PlayerDeathThink_hook, reinterpret_cast<void**>(&CPortal_Player__PlayerDeathThink_orig)
103+
);
104+
105+
// Hook flashlight functions.
106+
Log(INFO, true, "Hooking CPortal_Player::FlashlightTurnOn...");
107+
MH_CreateHook(
108+
Memory::Scanner::Scan(SERVERDLL, "A1 ?? ?? ?? ?? 8B 50 ?? 83 7A ?? ?? 75"),
109+
&CPortal_Player__FlashlightTurnOn_hook, reinterpret_cast<void**>(&CPortal_Player__FlashlightTurnOn_orig)
110+
);
111+
Log(INFO, true, "Hooking CPortal_Player::FlashlightTurnOff...");
112+
MH_CreateHook(
113+
Memory::Scanner::Scan(SERVERDLL, "A1 ?? ?? ?? ?? 8B 50 ?? 83 7A ?? ?? 74 ?? 8B 81"),
114+
&CPortal_Player__FlashlightTurnOff_hook, reinterpret_cast<void**>(&CPortal_Player__FlashlightTurnOff_orig)
115+
);
116+
117+
// Stop workshop map downloads by not returning false on the download request.
118+
Log(INFO, true, "Hooking CWorkshopManager::CreateFileDownloadRequest...");
119+
MH_CreateHook(
120+
Memory::Scanner::Scan(CLIENTDLL, "55 8B EC 8B 45 ?? 8B 55 ?? 50 8B 45 ?? 52 8B 55 ?? 50 8B 45 ?? 52 8B 55 ?? 50 8B 45"),
121+
&CWorkshopManager__CreateFileDownloadRequest_hook, reinterpret_cast<void**>(&CWorkshopManager__CreateFileDownloadRequest_orig)
122+
);
123+
124+
// Stop env_projectedtexture entities from getting disabled when more than one is active.
125+
//! Engine limit still exists though with a max of eight env_projectedtextures.
126+
//Log(INFO, true, "Hooking CEnvProjectedTexture::EnforceSingleProjectionRules...");
127+
//! Currently crashes, hook is incorrect most likely even though I checked sig is correct and parameters match up with what is in code.
128+
// MH_CreateHook(
129+
// Memory::Scanner::Scan(SERVERDLL, "55 8B EC 83 EC 14 53 56 57 68 B8 6F 5D 10"),
130+
// &CEnvProjectedTexture__EnforceSingleProjectionRules_hook, reinterpret_cast<void**>(&CEnvProjectedTexture__EnforceSingleProjectionRules_orig)
131+
// );
132+
#else // Linux Hooking. Due to the way this plugin is structured, it's currently not possible to compile this for Linux. Literally 1984 I know, but I don't have enough time or experience to figure it out by myself. One day.
133+
#endif // _WIN32
134+
135+
MH_EnableHook(MH_ALL_HOOKS);
136+
} catch (const std::exception& ex) {
137+
Log(INFO, false, "Failed to load plugin! :( Exception: \"%s\"", ex.what());
138+
//this->m_bNoUnload = true;
139+
return false;
140+
}
141+
75142
Log(INFO, true, "Connecting tier libraries...");
76143
MathLib_Init(2.2f, 2.2f, 0.0f, 2.0f);
77144
ConnectTier1Libraries(&interfaceFactory, 1);
@@ -144,31 +211,8 @@ bool CP2SMPlusPlusPlugin::Load(CreateInterfaceFn interfaceFactory, CreateInterfa
144211
if (ConVar* ifuCVar = g_pCVar->FindVar("in_forceuser"))
145212
ifuCVar->RemoveFlags(FCVAR_CHEAT);
146213

147-
// big ol' try catch because game has a TerminateProcess handler for exceptions...
148-
// why this wasn't here is mystifying, - 10/2024 NULLderef
149-
try {
150-
// MinHook initialization and hooking
151-
Log(INFO, true, "Initializing MinHook and hooking functions...");
152-
MH_Initialize();
153-
154-
// STOP THEM WORKSHOP DOWNLOADS: MinHook Edition
155-
#if _WIN32
156-
MH_CreateHook(
157-
Memory::Scanner::Scan(CLIENTDLL, "55 8B EC 81 EC 48 01 00 00 57"),
158-
&CUGCFileRequestManager__Update_hook, reinterpret_cast<void**>(&CUGCFileRequestManager__Update_orig)
159-
);
160-
#else // Linux Hooking. Due to the way this plugin is structured, it's currently not possible to compile this for Linux. Literally 1984 I know, but I don't have enough time or experience to figure it out by myself.
161-
#endif // _WIN32
162-
163-
MH_EnableHook(MH_ALL_HOOKS);
164-
165-
Log(INFO, false, "Loaded plugin! Yay! :D");
166-
m_bPluginLoaded = true;
167-
} catch (const std::exception& ex) {
168-
Log(INFO, false, "Failed to load plugin! :( Exception: \"%s\"", ex.what());
169-
this->m_bNoUnload = true;
170-
return false;
171-
}
214+
Log(INFO, false, "Loaded plugin! Yay! :D");
215+
m_bPluginLoaded = true;
172216

173217
return true;
174218
}
@@ -187,6 +231,54 @@ void CP2SMPlusPlusPlugin::Unload(void)
187231
}
188232

189233
Log(INFO, false, "Unloading Plugin...");
234+
235+
try
236+
{
237+
#if _WIN32
238+
Log(INFO, true, "Un-patching game patches...");
239+
240+
Log(INFO, true, "Un-patching linked portal doors...");
241+
Memory::ReplacePattern("server", "EB 14 87 04 05 00 00 8B 16", "0F B6 87 04 05 00 00 8B 16");
242+
243+
Log(INFO, true, "Un-patching max runtime for VScript...");
244+
Memory::ReplacePattern("vscript", "00 00 00 00 00 00 E0 3F", "00 00 00 E0 51 B8 9E 3F");
245+
246+
Log(INFO, true, "Disconnecting hooked functions and un-initializing MinHook...");
247+
MH_DisableHook(MH_ALL_HOOKS);
248+
MH_Uninitialize();
249+
#else // Linux Hooking. Due to the way this plugin is structured, it's currently not possible to compile this for Linux. Literally 1984 I know, but I don't have enough time or experience to figure it out by myself. One day.
250+
#endif
251+
}
252+
catch (const std::exception& ex)
253+
{
254+
assert(0 && "Failed to fully unload!");
255+
Log(INFO, false, R"(Encountered error when unload plugin! :( Exception: "%s")", ex.what());
256+
Log(ERRORR, false, "P2:MM failed to unload!\nGame has to be shutdown as possibly some other patches/hooks are still connected which can cause issues!");
257+
}
258+
259+
// Turn every ConVar/ConCommand back to normal.
260+
Log(INFO, true, "Reverting changed ConVars and ConCommands...");
261+
262+
Log(INFO, true, "cl_localnetworkbackdoor...");
263+
if (ConVar* lnbCVar = g_pCVar->FindVar("cl_localnetworkbackdoor"))
264+
lnbCVar->SetValue(0);
265+
266+
// Remove the cheat flag on r_drawscreenoverlay and enable it by default to allow maps to easily display screen overlays.
267+
Log(INFO, true, "r_drawscreenoverlay...");
268+
if (ConVar* screenCVar = g_pCVar->FindVar("r_drawscreenoverlay"))
269+
{
270+
screenCVar->RemoveFlags(FCVAR_CHEAT);
271+
screenCVar->SetValue(1);
272+
}
273+
274+
// Make switching between players in splitscreen when testing easier by removing
275+
// the need for cheats to change the current player under control.
276+
Log(INFO, true, "in_forceuser...");
277+
if (ConVar* ifuCVar = g_pCVar->FindVar("in_forceuser"))
278+
ifuCVar->RemoveFlags(FCVAR_CHEAT);
279+
280+
Log(INFO, true, "Unregistering ConVars and ConCommands...");
281+
ConVar_Unregister();
190282

191283
Log(INFO, true, "Disconnecting tier libraries...");
192284
DisconnectTier2Libraries();

0 commit comments

Comments
 (0)