diff --git a/lua/entities/gmod_wire_expression2/init.lua b/lua/entities/gmod_wire_expression2/init.lua index 08fd5fb976..1362b8b14f 100644 --- a/lua/entities/gmod_wire_expression2/init.lua +++ b/lua/entities/gmod_wire_expression2/init.lua @@ -9,6 +9,7 @@ e2_hardquota = nil e2_tickquota = nil e2_timequota = nil e2_timeaverage = nil +e2_globalmax = nil do local wire_expression2_unlimited = GetConVar("wire_expression2_unlimited") @@ -16,6 +17,7 @@ do local wire_expression2_quotahard = GetConVar("wire_expression2_quotahard") local wire_expression2_quotatick = GetConVar("wire_expression2_quotatick") local wire_expression2_quotatime = GetConVar("wire_expression2_quotatime") + local wire_expression2_quota_global = GetConVar("wire_expression2_quota_global") local wire_expression2_quota_average = GetConVar("wire_expression2_quota_average") local function updateQuotas() @@ -24,11 +26,13 @@ do e2_hardquota = 1000000 e2_tickquota = 100000 e2_timequota = -1 + e2_globalmax = -1 else e2_softquota = wire_expression2_quotasoft:GetFloat() e2_hardquota = wire_expression2_quotahard:GetFloat() e2_tickquota = wire_expression2_quotatick:GetFloat() e2_timequota = wire_expression2_quotatime:GetFloat() * 0.001 + e2_globalmax = wire_expression2_quota_global:GetFloat() * 0.001 end e2_timeaverage = 1 / wire_expression2_quota_average:GetFloat() @@ -39,6 +43,7 @@ do cvars.AddChangeCallback("wire_expression2_quotatick", updateQuotas) cvars.AddChangeCallback("wire_expression2_quotatime", updateQuotas) cvars.AddChangeCallback("wire_expression2_quota_average", updateQuotas) + cvars.AddChangeCallback("wire_expression2_quota_global", updateQuotas) updateQuotas() end @@ -359,6 +364,8 @@ function PlayerChips:checkCpuTime() break end end + + return total_time end local GlobalChips = {} @@ -392,12 +399,55 @@ function GlobalChips:remove(remove_chip) end end +function GlobalChips:findMaxTimeChip(chips) + local max_chip, max_time = nil, 0 + + for _, chip in ipairs(chips) do + local tab = chip:GetTable() + if tab.error then continue end + + local context = tab.context + if not context then continue end + + if context.timebench > max_time then + max_time = context.timebench + max_chip = chip + end + end + + return max_chip, max_time +end + E2Lib.PlayerChips = E2Lib.PlayerChips or setmetatable({}, GlobalChips) hook.Add("Think", "E2_Think", function() + local global_time = 0 + if e2_timequota > 0 then for ply, chips in pairs(E2Lib.PlayerChips) do - chips:checkCpuTime() + global_time = global_time + chips:checkCpuTime() + end + else + for ply, chips in pairs(E2Lib.PlayerChips) do + global_time = global_time + chips:getTotalTime() + end + end + + if e2_globalmax > 0 and global_time > e2_globalmax then + -- It will be faster to just iterate over all chips from now on + local chips = ents.FindByClass("gmod_wire_expression2") + + while global_time > e2_globalmax do + local max_chip, max_time = E2Lib.PlayerChips:findMaxTimeChip(chips) + + if max_chip then + global_time = global_time - max_time + max_chip:Error("Expression 2 (" .. max_chip.name .. "): Global time quota exceeded", "global time quota exceeded") + max_chip:Destruct() + else + -- It shouldn't happen, but if something breaks, it will prevent an infinity loop + break + end end end end) diff --git a/lua/entities/gmod_wire_expression2/shared.lua b/lua/entities/gmod_wire_expression2/shared.lua index c79499979b..bbd844e088 100644 --- a/lua/entities/gmod_wire_expression2/shared.lua +++ b/lua/entities/gmod_wire_expression2/shared.lua @@ -17,6 +17,7 @@ CreateConVar("wire_expression2_quotasoft", "10000", {FCVAR_REPLICATED}) CreateConVar("wire_expression2_quotahard", "100000", {FCVAR_REPLICATED}) CreateConVar("wire_expression2_quotatick", "25000", {FCVAR_REPLICATED}) CreateConVar("wire_expression2_quotatime", "-1", {FCVAR_REPLICATED}, "Time in (ms) that all E2s of one player can consume before killing (-1 is infinite)") +CreateConVar("wire_expression2_quota_global", "-1", {FCVAR_REPLICATED}, "The maximum amount of time all E2s on server can consume before killing the highest one (-1 is infinite)") CreateConVar("wire_expression2_quota_average", "100", {FCVAR_REPLICATED}, "The chip load window width in ticks (smaller is roughly, larger is smooth)") include("core/e2lib.lua")