diff --git a/FurnitureCatalogue.txt b/FurnitureCatalogue.txt index 3073a99..e691ac4 100644 --- a/FurnitureCatalogue.txt +++ b/FurnitureCatalogue.txt @@ -1,6 +1,6 @@ ## Title: FurnitureCatalogue ## Author: manavortex -## Version: 2.4 +## Version: 2.4.1 ## APIVersion: 100022 100023 ## SavedVariables: FurnitureCatalogue_Settings ## OptionalDependsOn: pChat diff --git a/libs/LibAsync/LibAsync.lua b/libs/LibAsync/LibAsync.lua index d5dab4b..6c1cfaa 100644 --- a/libs/LibAsync/LibAsync.lua +++ b/libs/LibAsync/LibAsync.lua @@ -1,4 +1,4 @@ -local MAJOR, MINOR = "LibAsync", 1.3 +local MAJOR, MINOR = "LibAsync", 1.6 local async, oldminor = LibStub:NewLibrary(MAJOR, MINOR) if not async then return end -- the same or newer version of this lib is already loaded into memory @@ -27,12 +27,12 @@ local function DoCallback(job, callstackIndex) job.Error = shouldContinue RemoveCall(job, callstackIndex) - call = job.OnError + call = job.onError if call then pcall(safeCall) else job:Suspend() - error(job) + error(job.Error) end end end @@ -48,8 +48,8 @@ local function DoJob(job) if call then DoCallback(job, index) else - assert(index == 0, "No call on non-empty stack?!") - jobs[job] = nil + -- assert(index == 0, "No call on non-empty stack?!") + jobs[job.name] = nil call = job.finally if call then pcall(safeCall) end end @@ -57,21 +57,32 @@ local function DoJob(job) end -- time we can spend until the next frame must be shown -local frameTimeTarget = 13 +local frameTimeTarget = GetCVar("VSYNC") == "1" and 14 or(tonumber(GetCVar("MinFrameTime.2")) * 1000) + -- we allow a function to use 25% of the frame time before it gets critical local spendTimeDef = frameTimeTarget * 0.75 +local spendTimeDefNoHUD = 15 local spendTime = spendTimeDef local debug = false +local running local GetFrameTimeMilliseconds, GetGameTimeMilliseconds = GetFrameTimeMilliseconds, GetGameTimeMilliseconds -local identifier = "ASYNCTASKS_JOBS" + +local function GetThreshold() + return(HUD_SCENE:IsShowing() or HUD_UI_SCENE:IsShowing()) and spendTimeDef or spendTimeDefNoHUD +end + local job = nil +local cpuLoad = 0 local function Scheduler() + if not running then return end + + job = nil local start = GetFrameTimeMilliseconds() - local runTime = start - if (GetGameTimeMilliseconds() - start) > spendTime then - spendTime = 750 / GetFramerate() + local runTime, cpuLoad = start, GetGameTimeMilliseconds() - start + if cpuLoad > spendTime then + spendTime = math.min(30, spendTime + spendTime * 0.02) if debug then df("initial gap: %ims. skip. new threshold: %ims", GetGameTimeMilliseconds() - start, spendTime) end @@ -80,25 +91,27 @@ local function Scheduler() if debug then df("initial gap: %ims", GetGameTimeMilliseconds() - start) end + local name while (GetGameTimeMilliseconds() - start) <= spendTime do - job = next(jobs, job) or next(jobs) + name, job = next(jobs) if job then runTime = GetGameTimeMilliseconds() DoJob(job) + spendTime = spendTime - 0.001 else -- Finished - em:UnregisterForUpdate(identifier) - spendTime = spendTimeDef + running = false + spendTime = GetThreshold() return end end - spendTime = spendTimeDef + -- spendTime = GetThreshold() if debug and job then local now = GetGameTimeMilliseconds() local freezeTime = now - start if freezeTime >= 16 then runTime = now - runTime - df("%s freeze. used %ims, resulting frametime %ims.", job.name, runTime, freezeTime) + df("%s freeze. allowed: %ims, used %ims, resulting fps %i.", job.name, spendTime, runTime, 1000 / freezeTime) end end end @@ -111,6 +124,10 @@ function async:SetDebug(enabled) debug = enabled end +function async:GetCpuLoad() + return cpuLoad / frameTimeTarget +end + -- Class task local task = async.task or ZO_Object:Subclass() @@ -132,24 +149,24 @@ end -- Resume the execution context. function task:Resume() - jobs[self] = true - em:RegisterForUpdate(identifier, 0, Scheduler) + running = true + jobs[self.name] = self return self end -- Suspend the execution context and allow to resume anytime later. function task:Suspend() - jobs[self] = nil + jobs[self.name] = nil return self end -- Interupt and fully stop the execution context. Can be called from outside to stop everything. function task:Cancel() - if jobs[self] then - ZO_ClearNumericallyIndexedTable(self.callstack) - self.lastCallIndex = 0 + ZO_ClearNumericallyIndexedTable(self.callstack) + self.lastCallIndex = 0 + if jobs[self.name] then if not self.finally then - jobs[self] = nil + jobs[self.name] = nil -- else run job with empty callstack to run finalizer end end @@ -167,7 +184,7 @@ do local insert = table.insert -- Continue your task context execution with the given FuncOfTask after the previous as finished. function task:Then(funcOfTask) - assert(self.lastCallIndex > 0 and self.lastCallIndex <= #self.callstack, "cap!") + -- assert(self.lastCallIndex > 0 and self.lastCallIndex <= #self.callstack, "cap!") insert(self.callstack, self.lastCallIndex, funcOfTask) return self end @@ -277,7 +294,8 @@ do -- repeatly call this function until i >= j return true end - end ):Then( function() + end ) + task:Then( function() if compare(pivot, array[i]) then array[i], array[right] = array[right], array[i] end quicksort(left, i - 1) quicksort(i + 1, right) @@ -330,3 +348,22 @@ end -- async.BREAK is the new 'break' for breaking loops. As Lua would not allowed the keyword 'break' in that context. -- To break a for-loop, return async.BREAK async.BREAK = true + +local function stateChange(oldState, newState) + if newState == SCENE_SHOWN or newState == SCENE_HIDING then + spendTime = GetThreshold() + end +end + +local identifier = "ASYNCTASKS_JOBS" + +HUD_SCENE:RegisterCallback("StateChange", stateChange) +HUD_UI_SCENE:RegisterCallback("StateChange", stateChange) + +function async:Unload() + HUD_SCENE:UnregisterCallback("StateChange", stateChange) + HUD_UI_SCENE:UnregisterCallback("StateChange", stateChange) +end + +em:UnregisterForUpdate(identifier) +em:RegisterForUpdate(identifier, 0, Scheduler)