55#include " EngineDemoPlayer.hpp"
66#include " EngineDemoRecorder.hpp"
77#include " Event.hpp"
8- #include " FileSystem.hpp"
9- #include " InputSystem.hpp"
108#include " Features/AchievementTracker.hpp"
119#include " Features/Camera.hpp"
1210#include " Features/Cvars.hpp"
2119#include " Features/Speedrun/SpeedrunTimer.hpp"
2220#include " Features/Stitcher.hpp"
2321#include " Features/Tas/TasPlayer.hpp"
22+ #include " FileSystem.hpp"
2423#include " Game.hpp"
2524#include " Hook.hpp"
25+ #include " InputSystem.hpp"
2626#include " Interface.hpp"
2727#include " SAR.hpp"
2828#include " Server.hpp"
2929#include " Utils.hpp"
3030#include " Variable.hpp"
3131
32- #include < cstring>
3332#include < cmath>
33+ #include < cstring>
3434
3535#define FPS_CHECK_WINDOW 0 .5f
3636
@@ -51,7 +51,7 @@ Variable sar_pause_at("sar_pause_at", "-1", -1, "Pause at the specified tick. -1
5151Variable sar_pause_for (" sar_pause_for" , " 0" , 0 , " Pause for this amount of ticks.\n " );
5252
5353Variable sar_tick_debug (" sar_tick_debug" , " 0" , 0 , 3 , " Output debugging information to the console related to ticks and frames.\n " );
54- Variable sar_frametime_debug (" sar_frametime_debug" , " 0" , " Output debugging information to the console related to frametime.\n " ); // see also host_print_frame_times
54+ Variable sar_frametime_debug (" sar_frametime_debug" , " 0" , " Output debugging information to the console related to frametime.\n " ); // see also host_print_frame_times
5555Variable sar_frametime_uncap (" sar_frametime_uncap" , " 0" , " EXPERIMENTAL - USE AT OWN RISK. Removes the 10-1000 FPS cap on frametime. More info https://wiki.portal2.sr/Frametime\n " );
5656Variable sar_command_debug (" sar_command_debug" , " 0" , 0 , 2 , " Output debugging information to the console related to commands. **Breaks svar_capture**\n " );
5757
@@ -104,7 +104,7 @@ void Engine::ExecuteCommand(const char *cmd, bool immediately) {
104104 this ->ExecuteClientCmd (this ->engineClient ->ThisPtr (), " " );
105105 }
106106}
107- float Engine::GetIPT () { // IntervalPerTick
107+ float Engine::GetIPT () { // IntervalPerTick
108108 if (this ->interval_per_tick ) {
109109 return *this ->interval_per_tick ;
110110 }
@@ -168,7 +168,6 @@ int Engine::PointToScreen(const Vector &point, Vector &screen) {
168168 return this ->ScreenPosition (nullptr , point, screen);
169169}
170170void Engine::SafeUnload (const char *postCommand) {
171-
172171 // give events some time to execute before plugin is disabled
173172 Event::Trigger<Event::SAR_UNLOAD>({});
174173 this ->ExecuteCommand (" sar_exit" );
@@ -231,7 +230,7 @@ std::string Engine::GetCurrentMapTitle() {
231230bool Engine::IsCoop () {
232231 if (GetCurrentMapName ().size () == 0 ) return false ;
233232 if (client->gamerules && *client->gamerules ) {
234- using _IsMultiplayer = bool (__rescall *)(void *thisptr);
233+ using _IsMultiplayer = bool (__rescall *)(void *thisptr);
235234 return Memory::VMT<_IsMultiplayer>(*client->gamerules , Offsets::IsMultiplayer)(*client->gamerules );
236235 }
237236 return sv_portal_players.GetInt () == 2 || (engine->demoplayer ->IsPlaying () && engine->GetMaxClients () >= 2 );
@@ -289,7 +288,7 @@ ON_EVENT(PRE_TICK) {
289288 if (!engine->IsCoop () || (!engine->IsOrange () && g_orangeReady)) {
290289 if (engine->IsCoop ()) {
291290 g_coop_pausable = Variable (" sv_pausable" ).GetBool ();
292- engine->ExecuteCommand (" stopvideos" ); // loading animation goes over sync screen
291+ engine->ExecuteCommand (" stopvideos" ); // loading animation goes over sync screen
293292 Variable (" sv_pausable" ).SetValue (" 1" );
294293 }
295294 engine->ExecuteCommand (" pause" , true );
@@ -311,7 +310,7 @@ float Engine::GetClientTime() {
311310}
312311
313312float Engine::GetHostTime () {
314- return this ->engineTool ->Original <float (__rescall *)(void *thisptr)>(Offsets::HostTick - 1 )(this ->engineTool ->ThisPtr ());
313+ return this ->engineTool ->Original <float (__rescall *)(void *thisptr)>(Offsets::HostTick - 1 )(this ->engineTool ->ThisPtr ());
315314}
316315
317316// CClientState::Disconnect
@@ -348,7 +347,7 @@ DETOUR_COMMAND(Engine::changelevel2_command) {
348347}
349348
350349// CVEngineServer::ClientCommandKeyValues
351- DETOUR (Engine::ClientCommandKeyValues, void * pEdict, KeyValues* pKeyValues) {
350+ DETOUR (Engine::ClientCommandKeyValues, void * pEdict, KeyValues * pKeyValues) {
352351 AchievementTracker::CheckKeyValuesForAchievement (pKeyValues);
353352 return Engine::ClientCommandKeyValues (thisptr, pEdict, pKeyValues);
354353}
@@ -396,7 +395,7 @@ DETOUR(Engine::Frame) {
396395 Event::Trigger<Event::POST_TICK>({false , session->GetTick ()});
397396 }
398397
399- // demoplayer
398+ // demoplayer
400399 if (engine->demoplayer ->demoQueueSize > 0 && !engine->demoplayer ->IsPlaying () && engine->demoplayer ->IsPlaybackFixReady ()) {
401400 DemoParser parser;
402401 auto name = engine->demoplayer ->demoQueue [engine->demoplayer ->currentDemoID ];
@@ -465,7 +464,7 @@ DETOUR_MID_MH(Engine::ParseSmoothingInfo_Mid) {
465464 cmp eax, 8
466465 jne _orig
467466
468- // Parse stuff that does not get parsed (thanks valve)
467+ // Parse stuff that does not get parsed (thanks valve)
469468 push edi
470469 push edi
471470 mov ecx, esi
@@ -724,9 +723,7 @@ const ConCommandBase *Cmd_ExecuteCommand_Detour(int eTarget, const CCommand &com
724723 cmd.erase (0 , cmd.find_first_not_of (" \t " ));
725724 console->Print (" Cmd_ExecuteCommand (%s) target: %d slot: %d\n " , cmd.c_str (), eTarget, nClientSlot);
726725 }
727- if (command.ArgC () >= 1 && !strcmp (command.Arg (0 ), " restart_level" ) &&
728- engine->IsCoop () && !engine->IsOrange () &&
729- (g_partnerHasSAR && !g_orangeReady)) {
726+ if (command.ArgC () >= 1 && !strcmp (command.Arg (0 ), " restart_level" ) && engine->IsCoop () && !engine->IsOrange () && (g_partnerHasSAR && !g_orangeReady)) {
730727 return 0 ;
731728 }
732729 Cmd_ExecuteCommand_Hook.Disable ();
@@ -778,8 +775,8 @@ void _Host_RunFrame_Render_Detour() {
778775 // in response to portal teleportations (and it probably breaks some
779776 // other stuff too). This would normally be done within
780777 // SCR_UpdateScreen, wrapping the main rendering calls
781- client->ClFrameStageNotify (5 ); // FRAME_RENDER_START
782- client->ClFrameStageNotify (6 ); // FRAME_RENDER_END
778+ client->ClFrameStageNotify (5 ); // FRAME_RENDER_START
779+ client->ClFrameStageNotify (6 ); // FRAME_RENDER_END
783780 } else {
784781 // Just do a normal render
785782 _Host_RunFrame_Render_Hook.Disable ();
@@ -820,8 +817,8 @@ ON_EVENT(FRAME) {
820817
821818static int framesToRun (void *bink) {
822819 // BINK datastructure in bink.h from SE2007 leak
823- // uint32_t nframes = ((uint32_t *)bink)[2];
824- // uint32_t last_frame = ((uint32_t *)bink)[4];
820+ // uint32_t nframes = ((uint32_t *)bink)[2];
821+ // uint32_t last_frame = ((uint32_t *)bink)[4];
825822 double framerate = (double )((uint32_t *)bink)[5 ] / (double )((uint32_t *)bink)[6 ];
826823
827824 double now = engine->GetHostTime ();
@@ -836,16 +833,16 @@ static int framesToRun(void *bink) {
836833 }
837834
838835 double to_run = (now - last) * framerate;
839- // int possible = nframes - last_frame - 1;
836+ // int possible = nframes - last_frame - 1;
840837
841- // if (to_run > possible) return possible;
838+ // if (to_run > possible) return possible;
842839 return (int )to_run;
843840}
844841
845842static void advFrame (void *bink) {
846843 // BINK datastructure in bink.h from SE2007 leak
847- // uint32_t nframes = ((uint32_t *)bink)[2];
848- // uint32_t last_frame = ((uint32_t *)bink)[4];
844+ // uint32_t nframes = ((uint32_t *)bink)[2];
845+ // uint32_t last_frame = ((uint32_t *)bink)[4];
849846 double framerate = (double )((uint32_t *)bink)[5 ] / (double )((uint32_t *)bink)[6 ];
850847
851848 auto it = g_bink_last_frames.find (bink);
@@ -856,7 +853,7 @@ static void advFrame(void *bink) {
856853 }
857854}
858855
859- void (__stdcall *BinkNextFrame)(void *bink);
856+ void (__stdcall *BinkNextFrame)(void *bink);
860857void __stdcall BinkNextFrame_Detour (void *bink);
861858static Hook BinkNextFrame_Hook (&BinkNextFrame_Detour);
862859void __stdcall BinkNextFrame_Detour (void *bink) {
@@ -866,7 +863,7 @@ void __stdcall BinkNextFrame_Detour(void *bink) {
866863 if (g_bink_override_active) advFrame (bink);
867864}
868865
869- int (__stdcall *BinkShouldSkip)(void *bink);
866+ int (__stdcall *BinkShouldSkip)(void *bink);
870867int __stdcall BinkShouldSkip_Detour (void *bink);
871868static Hook BinkShouldSkip_Hook (&BinkShouldSkip_Detour);
872869int __stdcall BinkShouldSkip_Detour (void *bink) {
@@ -880,7 +877,7 @@ int __stdcall BinkShouldSkip_Detour(void *bink) {
880877 }
881878}
882879
883- int (__stdcall *BinkWait)(void *bink);
880+ int (__stdcall *BinkWait)(void *bink);
884881int __stdcall BinkWait_Detour (void *bink);
885882static Hook BinkWait_Hook (&BinkWait_Detour);
886883int __stdcall BinkWait_Detour (void *bink) {
@@ -894,6 +891,53 @@ int __stdcall BinkWait_Detour(void *bink) {
894891 }
895892}
896893
894+ #ifdef _WIN32
895+ bool __cdecl CopyPropData_Impl (void *pDecoder, void *pOut, int iProp, void *arg_4) {
896+ auto ppProp = (SendProp **)(((uintptr_t *)pDecoder)[13 ] + 4 * iProp);
897+
898+ console->Print (" CopyPropData(%p, %p, %d) | ppProp = %p.\n " , pDecoder, pOut, iProp, ppProp);
899+
900+ // if (iProp > 54)
901+ // return false;
902+
903+ // console->Print("pProp = %p.\n", *ppProp);
904+
905+ return true ;
906+ }
907+
908+ void (*CopyPropData)();
909+ void __declspec (naked) CopyPropData_Detour () {
910+ __asm {
911+ pushad
912+ pushfd
913+
914+ mov ecx, dword ptr [esp + 0x20 ] // eax = pDecoder.
915+ mov edx, dword ptr [esp + 0x08 ] // esi = pOut.
916+ mov ebx, dword ptr [esp + 0x28 ] // [esp+4] on entry = pProp.
917+ mov edi, dword ptr [esp + 0x2C ] // [esp+8] on entry = arg_4.
918+
919+ push edi
920+ push ebx
921+ push edx
922+ push ecx
923+ call CopyPropData_Impl
924+ add esp, 16
925+
926+ test eax, eax
927+ jnz orig
928+
929+ popfd
930+ popad
931+ ret 8
932+
933+ orig:
934+ popfd
935+ popad
936+ jmp CopyPropData
937+ }
938+ }
939+ #endif
940+
897941Color Engine::GetLightAtPoint (Vector point) {
898942#ifdef _WIN32
899943 // MSVC bug workaround - COM interfaces apparently don't quite follow
@@ -909,8 +953,7 @@ Color Engine::GetLightAtPoint(Vector point) {
909953 return Color{(uint8_t )(light.x * 255 ), (uint8_t )(light.y * 255 ), (uint8_t )(light.z * 255 ), 255 };
910954}
911955
912- bool Engine::GetPlayerInfo (int ent_num, player_info_t * pInfo)
913- {
956+ bool Engine::GetPlayerInfo (int ent_num, player_info_t *pInfo) {
914957 return this ->GetInfo (this ->engineClient ->ThisPtr (), ent_num, pInfo);
915958}
916959
@@ -1147,15 +1190,15 @@ bool Engine::Init() {
11471190 fps_max = Variable (" fps_max" );
11481191 mat_norendering = Variable (" mat_norendering" );
11491192 mat_filtertextures = Variable (" mat_filtertextures" );
1150- phys_timescale = Variable (" phys_timescale" );
1193+ phys_timescale = Variable (" phys_timescale" );
11511194
11521195 // Dumb fix for valve cutting off convar descriptions at 80
11531196 // characters for some reason
11541197 /* TODO Memory::Scan data segments
11551198 char *s = (char *)Memory::Scan(this->Name(), Offsets::Convar_PrintDescription); // "%-80s - %.80s"
11561199 if (s) {
1157- Memory::UnProtect(s, 11);
1158- strcpy(s, "%-80s - %s");
1200+ Memory::UnProtect(s, 11);
1201+ strcpy(s, "%-80s - %s");
11591202 }*/
11601203
11611204 if (this ->g_physCollision = Interface::Create (MODULE (" vphysics" ), " VPhysicsCollision007" )) {
@@ -1169,15 +1212,21 @@ bool Engine::Init() {
11691212 auto bink_mod = Memory::GetModuleHandleByName (MODULE (" valve_avi" ));
11701213#endif
11711214 if (bink_mod) {
1172- BinkNextFrame = Memory::GetSymbolAddress<void (__stdcall *)(void *bink)>(bink_mod, STDCALL_NAME (" BinkNextFrame" , 4 ));
1215+ BinkNextFrame = Memory::GetSymbolAddress<void (__stdcall *)(void *bink)>(bink_mod, STDCALL_NAME (" BinkNextFrame" , 4 ));
11731216 BinkNextFrame_Hook.SetFunc (BinkNextFrame);
1174- BinkShouldSkip = Memory::GetSymbolAddress<int (__stdcall *)(void *bink)>(bink_mod, STDCALL_NAME (" BinkShouldSkip" , 4 ));
1217+ BinkShouldSkip = Memory::GetSymbolAddress<int (__stdcall *)(void *bink)>(bink_mod, STDCALL_NAME (" BinkShouldSkip" , 4 ));
11751218 BinkShouldSkip_Hook.SetFunc (BinkShouldSkip);
1176- BinkWait = Memory::GetSymbolAddress<int (__stdcall *)(void *bink)>(bink_mod, STDCALL_NAME (" BinkWait" , 4 ));
1219+ BinkWait = Memory::GetSymbolAddress<int (__stdcall *)(void *bink)>(bink_mod, STDCALL_NAME (" BinkWait" , 4 ));
11771220 BinkWait_Hook.SetFunc (BinkWait);
11781221 Memory::CloseModuleHandle (bink_mod);
11791222 }
11801223
1224+ #ifdef _WIN32
1225+ auto CopyPropData_addr = Memory::Scan<void *>(MODULE (" engine" ), " 55 8B EC 8B 48 ? 8B 55" );
1226+ if (MH_CreateHook (CopyPropData_addr, &CopyPropData_Detour, (void **)&CopyPropData) == MH_OK)
1227+ MH_EnableHook (CopyPropData_addr);
1228+ #endif
1229+
11811230 return this ->hasLoaded = this ->engineClient && this ->s_ServerPlugin && this ->demoplayer && this ->demorecorder && this ->engineTrace && this ->engineTraceClient ;
11821231}
11831232void Engine::Shutdown () {
0 commit comments