alliedmodders/sourcemod

[L4D2] Wrong ping when hooking functions

Closed this issue · 1 comments

Environment

  • Operating System version: Windows (its on server provider, so probably >= 10)
  • Game/AppID (with version if applicable): Left 4 Dead 2
  • Current SourceMod version: 1.12.0.7158 (tested on 1.11 as well)
  • Current SourceMod snapshot: 1.12.0.7158 (tested on 1.11 as well)
  • Current Metamod: Source snapshot: 2.0.0-dev+1313 (tested on 1.11 and 1.12 as well)

Description

Hooking functions like CEngine::Frame, Host_RunFrame, _Host_RunFrame, CDedicatedServerAPI::RunFrame causes ping to randomly go up or down and stay that way for some time. Some times it resets on new map or round restart, in a same way it can get lower or higher. This happens for everyone on server and for some players at same time is higher and for others lower. In nutshell ping is wrong.

Its also dependent on tickrate how wrong or what direction will go. Example, on 50 tickrate I had it always ~17 higher (when it would get high), while on 59 tickrate I had it ~5 higher or ~10 lower.

This happens if I hook function in extension via CDetour, or plugin via dhooks or MidHook. So happens regardless of method used or is it done in plugin or extension. Also no code needs to be executed in callback function for this to happen.

I couldn't find any solution nor explanation for this.

Problematic Code (or Steps to Reproduce)

 "Games"
{
	"left4dead2"
	{
		"Addresses" 
		{
			"CEngine::Frame"
			{
				"signature" "CEngine::Frame"
			}
		}

		"Signatures" 
		{
			"CEngine::Frame"
			{
				"library" "engine"
				"windows" "\x55\x8B\xEC\x83\xEC\x38\x53\x8B\xD9"
			}
		}
	}
}
#include <sourcemod>
#include <dhooks>

public void OnPluginStart()
{
   // Load gamedata and get CEngine::Frame address.
   Handle gamedata = LoadGameConfigFile("test_data");
   Address engine_frame = GameConfGetAddress(gamedata, "CEngine::Frame");
   CloseHandle(gamedata);
   
   // Create detour and enable pre callbacks.
   Handle detour = DHookCreateDetour(engine_frame, CallConv_THISCALL, ReturnType_Void, ThisPointer_Ignore);
   DHookEnableDetour(detour, false, engine_frame_pre);
}

MRESReturn engine_frame_pre()
{
   return MRES_Ignored;
}

This should be enough to reproduce the problem.

Locking fps to tickrate + 0.5 via ANY-FpsLimiter-extension ended up solving issue for me. Didn't retest all other cases when hooking functions in the above post, but after all this may be the engine issue.