Skip to content

Commit 3622aa3

Browse files
Cheater_Detection: performance fix
1 parent 390f3a0 commit 3622aa3

2 files changed

Lines changed: 73 additions & 2 deletions

File tree

Cheater_Detection/Main.lua

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@ local function OnCreateMove(cmd)
384384

385385
-- Pre-filter active players into a flat list (reuse module-level table)
386386
Profiler.Begin("PlayerScan_Loop")
387+
Profiler.Begin("PlayerScan_BuildActive")
387388
for k = 1, #activePlayers do activePlayers[k] = nil end
388389
for id, existingState in pairs(stateTable) do
389390
local pdata = existingState.pdata
@@ -423,6 +424,7 @@ local function OnCreateMove(cmd)
423424
activePlayers[#activePlayers + 1] = existingState
424425
::continue::
425426
end
427+
Profiler.End("PlayerScan_BuildActive")
426428

427429
if enableSilent then
428430
Profiler.Begin("History_SilentAim")
@@ -434,14 +436,15 @@ local function OnCreateMove(cmd)
434436
if enableChoke or enableDoubleTap then
435437
Profiler.Begin("History_Simtime")
436438
for _, pState in ipairs(activePlayers) do
437-
DetectionConfig.RecordHistory(pState.wrap, "Simtime")
439+
HistoryManager.RecordSimtimeTick(pState.id, pState.pdata.simTime)
438440
end
439441
Profiler.End("History_Simtime")
440442
end
441443

442444
-- ValveCheck runs via scheduler + DirtySystem "checks" (once per player per map)
443445
-- Auto-disconnect enforcement still runs every tick for confirmed Valve employees
444446
if enableValveCheck then
447+
Profiler.Begin("ValveCheck")
445448
for _, pState in ipairs(activePlayers) do
446449
enforceValveAutoDisconnect(pState)
447450
if sessionState.valveDisconnectTriggered then
@@ -450,6 +453,7 @@ local function OnCreateMove(cmd)
450453
return
451454
end
452455
end
456+
Profiler.End("ValveCheck")
453457
end
454458

455459
if enableSilent then

Cheater_Detection/Utils/HistoryManager.lua

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,22 @@ local function simtimeToTicks(deltaSec)
8787
return math.floor(deltaSec / globals.TickInterval() + 0.5)
8888
end
8989

90+
local function getPreviousRecord(history)
91+
if not history or history._count < 2 then
92+
return nil
93+
end
94+
local prevIdx = history._head - 1
95+
if prevIdx < 1 then
96+
prevIdx = prevIdx + maxRetentionTicks
97+
end
98+
return history[prevIdx]
99+
end
100+
90101
-- Stored on each ring slot when it becomes head: gap to the previous simtime sample (ticks).
91102
local function writeSimDeltaTicks(history, record)
92103
local simField = HistoryManager.Fields.SimulationTime
93104
local simNew = record[simField]
94-
local older = HistoryManager.GetRecordAt(history, 1)
105+
local older = getPreviousRecord(history)
95106
if not simNew or not older then
96107
record._sim_delta_ticks = nil
97108
return
@@ -285,6 +296,62 @@ function HistoryManager.RequestField(player, field)
285296
return record[field]
286297
end
287298

299+
--- Fast simtime ring write: uses pdata.simTime (no WrappedPlayer / second netprop read).
300+
--- Shares head advance + dedup with RequestField (SilentAim angles on same tick stay in one slot).
301+
function HistoryManager.RecordSimtimeTick(steamID, simTime)
302+
if not initialized or not activeFields[HistoryManager.Fields.SimulationTime] then
303+
return
304+
end
305+
if not steamID or simTime == nil then
306+
return
307+
end
308+
309+
local id = tostring(steamID)
310+
local simField = HistoryManager.Fields.SimulationTime
311+
local curTick = globals.TickCount()
312+
313+
local stored = _storedFieldsByPlayer[id]
314+
if stored and stored[simField] == curTick then
315+
return
316+
end
317+
318+
local history = playerHistories[id]
319+
if not history then
320+
history = { _head = 0, _count = 0, _lastTick = -1 }
321+
playerHistories[id] = history
322+
end
323+
324+
if history._lastTick ~= curTick then
325+
history._head = (history._head % maxRetentionTicks) + 1
326+
if history._count < maxRetentionTicks then
327+
history._count = history._count + 1
328+
end
329+
history._lastTick = curTick
330+
if stored then
331+
for f in pairs(stored) do
332+
stored[f] = nil
333+
end
334+
end
335+
end
336+
337+
local head = history._head
338+
local record = history[head]
339+
if type(record) ~= "table" then
340+
record = {}
341+
history[head] = record
342+
end
343+
344+
record[simField] = simTime
345+
writeSimDeltaTicks(history, record)
346+
record._tick = curTick
347+
348+
if not stored then
349+
stored = {}
350+
_storedFieldsByPlayer[id] = stored
351+
end
352+
stored[simField] = curTick
353+
end
354+
288355
function HistoryManager.RequestFields(player, fields)
289356
if not fields then return end
290357
for i = 1, #fields do

0 commit comments

Comments
 (0)