From c4ecc7f2df2ff1688189b86b05703fe81885b79e Mon Sep 17 00:00:00 2001 From: xen Date: Mon, 16 Mar 2020 13:57:35 +0200 Subject: [PATCH] Update LagCompensation to 1.0.4 --- .../gamedata/LagCompensation.games.txt | 20 ++- LagCompensation/scripting/LagCompensation.sp | 163 +++++++++--------- 2 files changed, 98 insertions(+), 85 deletions(-) diff --git a/LagCompensation/gamedata/LagCompensation.games.txt b/LagCompensation/gamedata/LagCompensation.games.txt index 478bee72..6ba768ad 100644 --- a/LagCompensation/gamedata/LagCompensation.games.txt +++ b/LagCompensation/gamedata/LagCompensation.games.txt @@ -110,6 +110,12 @@ "linux" "8" "windows" "8" } + + "CGameRules::EndGameFrame" + { + "linux" "49" + "windows" "48" + } } } @@ -167,10 +173,6 @@ "signature" "::UTIL_Remove" "return" "void" "callconv" "cdecl" - "windows" - { - "callconv" "fastcall" - } "arguments" { "oldObj" @@ -178,6 +180,10 @@ "type" "objectptr" } } + "windows" + { + "callconv" "fastcall" + } } "CCSGameRules__RestartRound" @@ -232,6 +238,12 @@ "linux" "8" "windows" "8" } + + "CGameRules::EndGameFrame" + { + "linux" "48" + "windows" "47" + } } } } diff --git a/LagCompensation/scripting/LagCompensation.sp b/LagCompensation/scripting/LagCompensation.sp index abcd649e..32f34100 100644 --- a/LagCompensation/scripting/LagCompensation.sp +++ b/LagCompensation/scripting/LagCompensation.sp @@ -5,7 +5,7 @@ #include #include -#define PLUGIN_VERSION "1.0.1" +#define PLUGIN_VERSION "1.0.4" #define SetBit(%1,%2) ((%1)[(%2) >> 5] |= (1 << ((%2) & 31))) #define ClearBit(%1,%2) ((%1)[(%2) >> 5] &= ~(1 << ((%2) & 31))) @@ -19,12 +19,13 @@ public Plugin myinfo = name = "LagCompensation", author = "BotoX", description = "", - version = "1.0", + version = PLUGIN_VERSION, url = "" }; bool g_bLateLoad = false; bool g_bHasPhysHooks = true; +bool g_bHasOnEntitySpawned = false; // Don't change this. #define MAX_EDICTS 2048 @@ -85,6 +86,8 @@ enum struct LagRecord float vecAbsOrigin[3]; float angRotation[3]; float angAbsRotation[3]; + float vecMins[3]; + float vecMaxs[3]; float flSimulationTime; float rgflCoordinateFrame[COORDINATE_FRAME_SIZE]; } @@ -100,7 +103,6 @@ enum struct EntityLagData int iNotMoving; bool bRestore; bool bLateKill; - LagRecord RestoreData; } LagRecord g_aaLagRecords[MAX_ENTITIES][MAX_RECORDS]; @@ -108,18 +110,26 @@ EntityLagData g_aEntityLagData[MAX_ENTITIES]; int g_iNumEntities = 0; bool g_bCleaningUp = true; -bool g_bHasOnEntitySpawned = false; +// Cache +int g_iGameTick; +float g_fTickInterval; +int g_aLerpTicks[MAXPLAYERS + 1]; +// SDKCall Handle g_hCalcAbsolutePosition; Handle g_hMarkPartitionHandleDirty; +// DHooks Detour Handle g_hUTIL_Remove; Handle g_hRestartRound; Handle g_hSetTarget; Handle g_hSetTargetPost; Handle g_hFrameUpdatePostEntityThink; + +// DHooks Virtual Handle g_hActivate; Handle g_hAcceptInput; +Handle g_hEndGameFrame; int g_iNetworkableOuter; int g_iParent; @@ -129,12 +139,13 @@ int g_iSolidFlags; int g_iSolidType; int g_iSurroundType; int g_iEFlags; -int g_iLerpTime = -1; int g_iVecOrigin; int g_iVecAbsOrigin; int g_iAngRotation; int g_iAngAbsRotation; +int g_iVecMins; +int g_iVecMaxs; int g_iSimulationTime; int g_iCoordinateFrame; @@ -253,6 +264,21 @@ public void OnPluginStart() SetFailState("GameConfGetOffset(hGameData, \"CServerNetworkableProperty::m_pOuter\") failed!"); } + + int offset = GameConfGetOffset(hGameData, "CGameRules::EndGameFrame"); + if(offset == -1) + { + delete hGameData; + SetFailState("Failed to find CGameRules::EndGameFrame offset."); + } + + // CGameRules::EndGameFrame + g_hEndGameFrame = DHookCreate(offset, HookType_GameRules, ReturnType_Void, ThisPointer_Ignore, Hook_EndGameFrame); + if(g_hEndGameFrame == INVALID_HANDLE) + { + delete hGameData; + SetFailState("Failed to DHook CGameRules::EndGameFrame."); + } delete hGameData; @@ -260,23 +286,35 @@ public void OnPluginStart() if(!hGameData) SetFailState("Failed to load sdktools gamedata."); - int offset = GameConfGetOffset(hGameData, "Activate"); + offset = GameConfGetOffset(hGameData, "Activate"); if(offset == -1) + { + delete hGameData; SetFailState("Failed to find Activate offset"); + } // CPhysForce::Activate g_hActivate = DHookCreate(offset, HookType_Entity, ReturnType_Void, ThisPointer_CBaseEntity, Hook_CPhysForce_Activate); if(g_hActivate == INVALID_HANDLE) + { + delete hGameData; SetFailState("Failed to DHookCreate Activate"); + } offset = GameConfGetOffset(hGameData, "AcceptInput"); if(offset == -1) + { + delete hGameData; SetFailState("Failed to find AcceptInput offset."); + } // CBaseEntity::AcceptInput( const char *szInputName, CBaseEntity *pActivator, CBaseEntity *pCaller, variant_t Value, int outputID ) - g_hAcceptInput = DHookCreate(offset, HookType_Entity, ReturnType_Bool, ThisPointer_CBaseEntity, OnAcceptInput); + g_hAcceptInput = DHookCreate(offset, HookType_Entity, ReturnType_Bool, ThisPointer_CBaseEntity, Hook_AcceptInput); if(g_hAcceptInput == INVALID_HANDLE) + { + delete hGameData; SetFailState("Failed to DHook AcceptInput."); + } DHookAddParam(g_hAcceptInput, HookParamType_CharPtr); DHookAddParam(g_hAcceptInput, HookParamType_CBaseEntity); @@ -342,8 +380,12 @@ public void OnMapStart() { bool bLate = g_bLateLoad; + DHookGamerules(g_hEndGameFrame, true); + g_bCleaningUp = false; + g_fTickInterval = GetTickInterval(); + g_iParent = FindDataMapInfo(0, "m_pParent"); g_iSpawnFlags = FindDataMapInfo(0, "m_spawnflags"); g_iCollision = FindDataMapInfo(0, "m_Collision"); @@ -356,6 +398,8 @@ public void OnMapStart() g_iVecAbsOrigin = FindDataMapInfo(0, "m_vecAbsOrigin"); g_iAngRotation = FindDataMapInfo(0, "m_angRotation"); g_iAngAbsRotation = FindDataMapInfo(0, "m_angAbsRotation"); + g_iVecMins = FindDataMapInfo(0, "m_vecMins"); + g_iVecMaxs = FindDataMapInfo(0, "m_vecMaxs"); g_iSimulationTime = FindDataMapInfo(0, "m_flSimulationTime"); g_iCoordinateFrame = FindDataMapInfo(0, "m_rgflCoordinateFrame"); @@ -369,7 +413,7 @@ public void OnMapStart() OnClientConnected(client); if(AreClientCookiesCached(client)) OnClientCookiesCached(client); - OnClientPutInServer(client); + OnClientSettingsChanged(client); } } @@ -407,20 +451,11 @@ public void OnClientConnected(int client) public void OnClientCookiesCached(int client) { - char sBuffer[16]; - GetClientCookie(client, g_hCookie_DisableLagComp, sBuffer, sizeof(sBuffer)); - if(sBuffer[0]) - g_bDisableLagComp[client] = true; - else - g_bDisableLagComp[client] = false; -} + if(!IsClientInGame(client)) + return; -public void OnClientPutInServer(int client) -{ - if(g_iLerpTime == -1) - { - g_iLerpTime = FindDataMapInfo(client, "m_fLerpTime"); - } + float fLerpTime = GetEntPropFloat(client, Prop_Data, "m_fLerpTime"); + g_aLerpTicks[client] = RoundToNearest(fLerpTime / g_fTickInterval); } public void OnClientDisconnect(int client) @@ -465,7 +500,7 @@ public void OnEntitySpawned(int entity, const char[] classname) CheckEntityForLagComp(entity, classname); } -public MRESReturn OnAcceptInput(int entity, Handle hReturn, Handle hParams) +public MRESReturn Hook_AcceptInput(int entity, Handle hReturn, Handle hParams) { if(!IsValidEntity(entity)) return MRES_Ignored; @@ -782,65 +817,21 @@ public MRESReturn Detour_OnFrameUpdatePostEntityThink() public void OnRunThinkFunctions(bool simulating) { + g_iGameTick = GetGameTickCount(); BlockTriggerTouchPlayers(g_aBlockTriggerTouchPlayers, false); - - for(int i = 0; i < g_iNumEntities; i++) - { - if(!IsValidEntity(g_aEntityLagData[i].iEntity)) - { - PrintToBoth("!!!!!!!!!!! OnRunThinkFunctions SHIT deleted: %d / %d", i, g_aEntityLagData[i].iEntity); - RemoveRecord(i); - i--; continue; - } - - if(g_aEntityLagData[i].iDeleted) - { - if(g_aEntityLagData[i].iDeleted + MAX_RECORDS <= GetGameTickCount()) - { - // calls OnEntityDestroyed right away - // which calls RemoveRecord - // which moves the next element to our current position - RemoveEdict(g_aEntityLagData[i].iEntity); - i--; continue; - } - continue; - } - - if(g_aEntityLagData[i].iNotMoving >= MAX_RECORDS) - continue; - - RecordDataIntoRecord(g_aEntityLagData[i].iEntity, g_aEntityLagData[i].RestoreData); - } } public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3], float angles[3], int &weapon, int &subtype, int &cmdnum, int &tickcount, int &seed, int mouse[2]) { - if(!IsPlayerAlive(client)) + if(!IsPlayerAlive(client) || IsFakeClient(client)) return Plugin_Continue; + int iTargetTick = tickcount - g_aLerpTicks[client]; + // -1 because the newest record in the list is one tick old // this is because we simulate players first // hence no new entity record was inserted on the current tick - int iGameTick = GetGameTickCount() - 1; - float fTickInterval = GetTickInterval(); - - float fLerpTime = GetEntDataFloat(client, g_iLerpTime); - // -1 lerp ticks was determined by analyzing hits visually at host_timescale 0.01 and debug_touchlinks 1 - int iLerpTicks = RoundToFloor(0.5 + (fLerpTime / fTickInterval)) - 1; - - int iTargetTick = tickcount - iLerpTicks; - int iDelta = iGameTick - iTargetTick; - - float fCorrect = 0.0; - fCorrect += GetClientLatency(client, NetFlow_Outgoing); - fCorrect += iLerpTicks * fTickInterval; - - float fDeltaTime = fCorrect - iDelta * fTickInterval; - if(FloatAbs(fDeltaTime) > 0.2) - { - // difference between cmd time and latency is too big > 200ms, use time correction based on latency - iDelta = RoundToFloor(0.5 + (fCorrect / fTickInterval)); - } + int iDelta = g_iGameTick - iTargetTick - 1; // The player is stupid and doesn't want lag compensation. // To get the original behavior back lets assume they actually have 0 latency. @@ -853,7 +844,7 @@ public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3 if(iDelta > MAX_RECORDS) iDelta = MAX_RECORDS; - int iPlayerSimTick = iGameTick - iDelta; + int iPlayerSimTick = g_iGameTick - iDelta; for(int i = 0; i < g_iNumEntities; i++) { @@ -904,19 +895,28 @@ public void OnPostPlayerThinkFunctions() if(!g_aEntityLagData[i].bRestore) continue; - RestoreEntityFromRecord(g_aEntityLagData[i].iEntity, g_aEntityLagData[i].RestoreData); + RestoreEntityFromRecord(g_aEntityLagData[i].iEntity, g_aaLagRecords[i][g_aEntityLagData[i].iRecordIndex]); g_aEntityLagData[i].bRestore = false; } BlockTriggerTouchPlayers(g_aBlockTriggerTouchPlayers, true); } -public void OnRunThinkFunctionsPost(bool simulating) +public MRESReturn Hook_EndGameFrame() { for(int i = 0; i < g_iNumEntities; i++) { if(g_aEntityLagData[i].iDeleted) { + if(g_aEntityLagData[i].iDeleted + MAX_RECORDS <= g_iGameTick) + { + // calls OnEntityDestroyed right away + // which calls RemoveRecord + // which moves the next element to our current position + RemoveEdict(g_aEntityLagData[i].iEntity); + i--; continue; + } + if(g_aEntityLagData[i].iRecordsValid) { g_aEntityLagData[i].iRecordIndex++; @@ -961,6 +961,8 @@ public void OnRunThinkFunctionsPost(bool simulating) LagRecord_Copy(g_aaLagRecords[i][g_aEntityLagData[i].iRecordIndex], TmpRecord); } + + return MRES_Ignored; } @@ -977,6 +979,8 @@ void RecordDataIntoRecord(int iEntity, LagRecord Record) GetEntDataVector(iEntity, g_iVecAbsOrigin, Record.vecAbsOrigin); GetEntDataVector(iEntity, g_iAngRotation, Record.angRotation); GetEntDataVector(iEntity, g_iAngAbsRotation, Record.angAbsRotation); + GetEntDataVector(iEntity, g_iVecMins, Record.vecMins); + GetEntDataVector(iEntity, g_iVecMaxs, Record.vecMaxs); GetEntDataArray(iEntity, g_iCoordinateFrame, view_as(Record.rgflCoordinateFrame), COORDINATE_FRAME_SIZE); Record.flSimulationTime = GetEntDataFloat(iEntity, g_iSimulationTime); } @@ -1021,11 +1025,6 @@ bool DoesRotationInvalidateSurroundingBox(int iEntity) void InvalidatePhysicsRecursive(int iEntity) { - // NetworkProp()->MarkPVSInformationDirty() - int fStateFlags = GetEdictFlags(iEntity); - fStateFlags |= FL_EDICT_DIRTY_PVS_INFORMATION; - SetEdictFlags(iEntity, fStateFlags); - // CollisionProp()->MarkPartitionHandleDirty(); Address CollisionProp = GetEntityAddress(iEntity) + view_as
(g_iCollision); SDKCall(g_hMarkPartitionHandleDirty, CollisionProp); @@ -1045,6 +1044,8 @@ void RestoreEntityFromRecord(int iEntity, LagRecord Record) SetEntDataVector(iEntity, g_iVecAbsOrigin, Record.vecAbsOrigin); SetEntDataVector(iEntity, g_iAngRotation, Record.angRotation); SetEntDataVector(iEntity, g_iAngAbsRotation, Record.angAbsRotation); + SetEntDataVector(iEntity, g_iVecMins, Record.vecMins); + SetEntDataVector(iEntity, g_iVecMaxs, Record.vecMaxs); SetEntDataArray(iEntity, g_iCoordinateFrame, view_as(Record.rgflCoordinateFrame), COORDINATE_FRAME_SIZE); SetEntDataFloat(iEntity, g_iSimulationTime, Record.flSimulationTime); @@ -1181,8 +1182,6 @@ void EntityLagData_Copy(EntityLagData obj, const EntityLagData other) obj.iNotMoving = other.iNotMoving; obj.bRestore = other.bRestore; obj.bLateKill = other.bLateKill; - - LagRecord_Copy(obj.RestoreData, other.RestoreData); } void LagRecord_Copy(LagRecord obj, const LagRecord other) @@ -1193,6 +1192,8 @@ void LagRecord_Copy(LagRecord obj, const LagRecord other) obj.vecAbsOrigin[i] = other.vecAbsOrigin[i]; obj.angRotation[i] = other.angRotation[i]; obj.angAbsRotation[i] = other.angAbsRotation[i]; + obj.vecMins[i] = other.vecMins[i]; + obj.vecMaxs[i] = other.vecMaxs[i]; } obj.flSimulationTime = other.flSimulationTime;