from retail

This commit is contained in:
NoM0Re
2025-01-25 23:37:36 +01:00
parent 4a326118da
commit 667a2f3f50
34 changed files with 788 additions and 242 deletions
+14 -9
View File
@@ -598,19 +598,24 @@ local function firstLine(string)
end
local function CreateFunctionCache(exec_env)
local cache = {}
cache.Load = function(self, string)
if self[string] then
return self[string]
local cache = {
funcs = setmetatable({}, {__mode = "v"})
}
cache.Load = function(self, string, silent)
if self.funcs[string] then
return self.funcs[string]
else
local loadedFunction, errorString = loadstring(string, firstLine(string))
if errorString then
print(errorString)
else
if not silent then
print(errorString)
end
return nil, errorString
elseif loadedFunction then
setfenv(loadedFunction, exec_env)
local success, func = pcall(assert(loadedFunction))
if success then
self[string] = func
self.funcs[string] = func
return func
end
end
@@ -626,8 +631,8 @@ function WeakAuras.LoadFunction(string)
return function_cache_custom:Load(string)
end
function Private.LoadFunction(string)
return function_cache_builtin:Load(string)
function Private.LoadFunction(string, silent)
return function_cache_builtin:Load(string, silent)
end
function Private.GetSanitizedGlobal(key)
+4 -3
View File
@@ -2443,7 +2443,7 @@ function BuffTrigger.Add(data)
local effectiveIgnoreDead = groupTrigger and trigger.ignoreDead
local effectiveIgnoreDisconnected = groupTrigger and trigger.ignoreDisconnected
local effectiveIgnoreInvisible = groupTrigger and trigger.ignoreInvisible
local effectiveHostility = trigger.unit == "nameplate" and trigger.useHostility and trigger.hostility
local effectiveHostility = (groupTrigger or trigger.unit == "nameplate") and trigger.useHostility and trigger.hostility
local effectiveNameCheck = groupTrigger and trigger.useUnitName and trigger.unitName
local effectiveNpcId = trigger.unit == "nameplate" and trigger.useNpcId and Private.ExecEnv.ParseStringCheck(trigger.npcId)
@@ -3465,7 +3465,8 @@ function BuffTrigger.InitMultiAura()
end
function BuffTrigger.HandleMultiEvent(frame, event, ...)
Private.StartProfileSystem("bufftrigger2 - multi")
local system = "bufftrigger2 - multi - " .. event
Private.StartProfileSystem(system)
if event == "COMBAT_LOG_EVENT_UNFILTERED" then
CombatLog(...)
elseif event == "UNIT_TARGET" then
@@ -3498,7 +3499,7 @@ function BuffTrigger.HandleMultiEvent(frame, event, ...)
end
wipe(matchDataMulti)
end
Private.StopProfileSystem("bufftrigger2 - multi")
Private.StopProfileSystem(system)
end
function BuffTrigger.GetTriggerDescription(data, triggernum, namestable)
+3
View File
@@ -52,6 +52,9 @@ local function formatValueForAssignment(vType, value, pathToCustomFunction, path
elseif vType == "progressSource" then
if type(value) == "table" then
local progressSource = Private.AddProgressSourceMetaData(data, value)
if not progressSource then
return "{}"
end
local trigger = progressSource[1] or -1
local progressType = progressSource[2] or "auto"
local property = progressSource[3]
+64
View File
@@ -0,0 +1,64 @@
if not WeakAuras.IsLibsOK() then return end
local AddonName, Private = ...
Private.DiscordList = {
[=[007bb]=],
[=[AcidWeb]=],
[=[aelen]=],
[=[Aishuu]=],
[=[Ariani Continuity]=],
[=[Azortharion]=],
[=[BadBrain]=],
[=[Bart]=],
[=[Boneshock]=],
[=[Boxthor]=],
[=[Burlis]=],
[=[Causese]=],
[=[Chab]=],
[=[cheswick]=],
[=[Darian]=],
[=[Desik]=],
[=[DjinnFish]=],
[=[exality]=],
[=[Fatpala]=],
[=[Fels]=],
[=[Fenchurch]=],
[=[Guffin]=],
[=[Ifor]=],
[=[Ironi]=],
[=[Jiberish]=],
[=[Jods]=],
[=[kanegasi]=],
[=[Koxy]=],
[=[Listefano]=],
[=[Luckyone]=],
[=[Luxthos]=],
[=[m33shoq]=],
[=[maddin]=],
[=[Max rdv 2026 pour TBC cla]=],
[=[MetalMusicMan]=],
[=[Murph]=],
[=[Mynze]=],
[=[Nona]=],
[=[NostraDumAzz]=],
[=[Ocelots]=],
[=[Oi]=],
[=[Ora]=],
[=[phoenix7700]=],
[=[Pseiko]=],
[=[Reloe]=],
[=[Shwinsta]=],
[=[Slurp]=],
[=[Spaten]=],
[=[Tollo]=],
[=[update]=],
[=[vozochris]=],
[=[Wizeowel]=],
[=[Xepheris]=],
[=[Мектран]=],
}
Private.DiscordListCJ = {
}
Private.DiscordListK = {
}
+15 -9
View File
@@ -703,6 +703,9 @@ local function RunTriggerFunc(allStates, data, id, triggernum, event, arg1, arg2
elseif (data.statesParameter == "unit") then
if arg1 then
if Private.multiUnitUnits[data.trigger.unit] then
if data.trigger.unit == "group" and IsInRaid() and Private.multiUnitUnits.party[arg1] then
return
end
unitForUnitTrigger = arg1
cloneIdForUnitTrigger = arg1
else
@@ -1149,8 +1152,8 @@ function HandleEvent(frame, event, arg1, arg2, ...)
if (event == "PLAYER_ENTERING_WORLD") then
timer:ScheduleTimer(function()
HandleEvent(frame, "WA_DELAYED_PLAYER_ENTERING_WORLD");
Private.StartProfileSystem("generictrigger WA_DELAYED_PLAYER_ENTERING_WORLD");
Private.ScanForLoads(nil, "WA_DELAYED_PLAYER_ENTERING_WORLD")
Private.StartProfileSystem("generictrigger WA_DELAYED_PLAYER_ENTERING_WORLD");
Private.CheckCooldownReady();
Private.StopProfileSystem("generictrigger WA_DELAYED_PLAYER_ENTERING_WORLD");
Private.PreShowModels()
@@ -1843,7 +1846,7 @@ function GenericTrigger.Add(data, region)
end
if warnAboutCLEUEvents then
Private.AuraWarnings.UpdateWarning(data.uid, "spammy_event_warning", "warning",
Private.AuraWarnings.UpdateWarning(data.uid, "spammy_event_warning", "error",
L["COMBAT_LOG_EVENT_UNFILTERED with no filter can trigger frame drops in raid environment. Find more information:\nhttps://github.com/WeakAuras/WeakAuras2/wiki/Deprecated-CLEU"])
else
Private.AuraWarnings.UpdateWarning(data.uid, "spammy_event_warning")
@@ -2199,19 +2202,21 @@ do
end,
Schedule = function(self, expirationTime, id)
if (not self.expirationTime[id] or expirationTime < self.expirationTime[id]) and expirationTime > 0 then
if self.handles[id] then
timer:CancelTimer(self.handles[id])
self.handles[id] = nil
self.expirationTime[id] = nil
end
self:Cancel(id)
local duration = expirationTime - GetTime()
if duration > 0 then
self.handles[id] = timer:ScheduleTimer(self.Recheck, duration, self, id)
self.expirationTime[id] = expirationTime
end
end
end
end,
Cancel = function(self, id)
if self.handles[id] then
timer:CancelTimer(self.handles[id])
self.handles[id] = nil
self.expirationTime[id] = nil
end
end,
}
local function FetchSpellCooldown(self, id)
@@ -2226,6 +2231,7 @@ do
local nowReady = false
local time = GetTime()
if self.expirationTime[id] and self.expirationTime[id] <= time and self.expirationTime[id] ~= 0 then
self.readyTime[id] = self.expirationTime[id]
self.duration[id] = 0
self.expirationTime[id] = 0
changed = true
@@ -1,5 +1,4 @@
Digitized data copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A.
with Reserved Font Name < Fira >,
Digitized data copyright 2012-2018: The Mozilla Foundation, Telefonica S.A., Carrois Corporate GbR and bBox Type GmbH.
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
@@ -19,7 +18,7 @@ with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+95
View File
@@ -0,0 +1,95 @@
Copyright (c) 2018, Paratype Inc (https://paratype.com),
Copyright (c) 2018, Paratype Ltd,
with Reserved Font Name "PT Sans".
This Font Software is licensed under the SIL Open Font License, Version 1.1.
This license is copied below, and is also available with a FAQ at:
http://scripts.sil.org/OFL
-----------------------------------------------------------
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
-----------------------------------------------------------
PREAMBLE
The goals of the Open Font License (OFL) are to stimulate worldwide
development of collaborative font projects, to support the font creation
efforts of academic and linguistic communities, and to provide a free and
open framework in which fonts may be shared and improved in partnership
with others.
The OFL allows the licensed fonts to be used, studied, modified and
redistributed freely as long as they are not sold by themselves. The
fonts, including any derivative works, can be bundled, embedded,
redistributed and/or sold with any software provided that any reserved
names are not used by derivative works. The fonts and derivatives,
however, cannot be released under any other type of license. The
requirement for fonts to remain under this license does not apply
to any document created using the fonts or their derivatives.
DEFINITIONS
"Font Software" refers to the set of files released by the Copyright
Holder(s) under this license and clearly marked as such. This may
include source files, build scripts and documentation.
"Reserved Font Name" refers to any names specified as such after the
copyright statement(s).
"Original Version" refers to the collection of Font Software components as
distributed by the Copyright Holder(s).
"Modified Version" refers to any derivative made by adding to, deleting,
or substituting -- in part or in whole -- any of the components of the
Original Version, by changing formats or by porting the Font Software to a
new environment.
"Author" refers to any designer, engineer, programmer, technical
writer or other person who contributed to the Font Software.
PERMISSION & CONDITIONS
Permission is hereby granted, free of charge, to any person obtaining
a copy of the Font Software, to use, study, copy, merge, embed, modify,
redistribute, and sell modified and unmodified copies of the Font
Software, subject to the following conditions:
1) Neither the Font Software nor any of its individual components,
in Original or Modified Versions, may be sold by itself.
2) Original or Modified Versions of the Font Software may be bundled,
redistributed and/or sold with any software, provided that each copy
contains the above copyright notice and this license. These can be
included either as stand-alone text files, human-readable headers or
in the appropriate machine-readable metadata fields within text or
binary files as long as those fields can be easily viewed by the user.
3) No Modified Version of the Font Software may use the Reserved Font
Name(s) unless explicit written permission is granted by the corresponding
Copyright Holder. This restriction only applies to the primary font name as
presented to the users.
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
Software shall not be used to promote, endorse or advertise any
Modified Version, except to acknowledge the contribution(s) of the
Copyright Holder(s) and the Author(s) or with their explicit written
permission.
5) The Font Software, modified or unmodified, in part or in whole,
must be distributed entirely under this license, and must not be
distributed under any other license. The requirement for fonts to
remain under this license does not apply to any document created
using the Font Software.
TERMINATION
This license becomes null and void if any of the above conditions are
not met.
DISCLAIMER
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
OTHER DEALINGS IN THE FONT SOFTWARE.
Binary file not shown.
+170
View File
@@ -1533,6 +1533,176 @@ function Private.Modernize(data, oldSnapshot)
end
end
if data.internalVersion < 76 then
local function removeHoles(t)
local keys = {}
for key in pairs(t) do
table.insert(keys, key)
end
if #keys ~= #t then
table.sort(keys)
local newTable = {}
for i, key in ipairs(keys) do
newTable[i] = t[key]
end
return newTable
else
return t
end
end
local trigger_migration = {
["Spell Cast Succeeded"] = {
"spellId",
},
["Unit Characteristics"] = {
"level",
},
["Power"] = {
"power",
"percentpower",
"deficit",
"maxpower",
},
["Combat Log"] = {
"spellId",
"spellName",
},
["Health"] = {
"health",
"percenthealth",
"deficit",
"maxhealth",
},
["Location"] = {
"zone",
"subzone",
},
["Threat Situation"] = {
"threatpct",
"rawthreatpct",
"threatvalue",
},
["Character Stats"] = {
"strength",
"agility",
"stamina",
"intellect",
"spirit",
"attackpower",
"spellpower",
"rangedattackpower",
"criticalrating",
"criticalpercent",
"hitrating",
"hitpercent",
"hasterating",
"hastepercent",
"expertiserating",
"expertisebonus",
"armorpenrating",
"armorpenpercent",
"spellpenpercent",
"resiliencerating",
"resiliencepercent",
"expertisebonus",
"expertiserating",
"resistancefire",
"resistancenature",
"resistancefrost",
"resistanceshadow",
"resistancearcane",
"movespeedpercent",
"dodgerating",
"dodgepercent",
"parryrating",
"parrypercent",
"blockpercent",
"blockvalue",
"armorrating",
"armorpercent",
},
["Cast"] = {
"spellNames",
"spellIds",
},
}
for _, triggerData in ipairs(data.triggers) do
local trigger = triggerData.trigger
local fieldsToMigrate = trigger_migration[trigger.event]
if fieldsToMigrate then
for _, field in ipairs(fieldsToMigrate) do
if type(trigger[field]) == "table" then
trigger[field] = removeHoles(trigger[field])
end
end
end
end
end
--[[if data.internalVersion < 77 then
-- fix data broken by wago export
local triggerFix = {
talent = {
multi = true
},
herotalent = {
multi = true
},
form = {
multi = true
},
specId = {
multi = true
},
actualSpec = true,
arena_spec = true
}
local loadFix = {
talent = {
multi = true
},
talent2 = {
multi = true
},
talent3 = {
multi = true
},
herotalent = {
multi = true
},
class_and_spec = {
multi = true
}
}
local function fixData(data, fields)
for k, v in pairs(fields) do
if v == true and type(data[k]) == "table" then
-- fix field k
local tofix = {}
for key in pairs(data[k]) do
if type(key) == "string" then
table.insert(tofix, key)
end
end
for _, oldkey in ipairs(tofix) do
local newkey = tonumber(oldkey)
if newkey then
data[k][newkey] = data[k][oldkey]
end
data[k][oldkey] = nil
end
elseif type(v) == "table" and type(data[k]) == "table" then
-- recurse
fixData(data[k], fields[k])
end
end
end
for _, triggerData in ipairs(data.triggers) do
fixData(triggerData.trigger, triggerFix)
end
fixData(data.load, loadFix)
end]]
data.internalVersion = max(data.internalVersion or 0, WeakAuras.InternalVersion())
end
+19 -4
View File
@@ -711,8 +711,8 @@ end
function WeakAuras.ValidateNumericOrPercent(info, val)
if val ~= nil and val ~= "" then
local percent = string.match(val, "(%d+)%%")
local number = percent and tonumber(percent) or tonumber(val)
local index = val:find("%% *$")
local number = index and tonumber(val:sub(1, index-1)) or tonumber(val)
if(not number or number >= 2^31) then
return false;
end
@@ -965,6 +965,15 @@ Private.load_prototype = {
optional = true,
events = {"VEHICLE_UPDATE", "UNIT_ENTERED_VEHICLE", "UNIT_EXITED_VEHICLE"}
},
{ -- broken, fix later COMPANION_UPDATE fires too early for an check, needs some custom stuff
name = "mounted",
display = L["Mounted"],
type = "tristate",
init = "arg",
width = WeakAuras.normalWidth,
optional = true,
--events = {"PLAYER_MOUNT_DISPLAY_CHANGED"}
},
{
name ="playerTitle",
display = L["Player"],
@@ -3810,7 +3819,13 @@ Private.event_prototypes = {
test = "true",
conditionType = "bool",
conditionTest = function(state, needle)
return state and state.show and (UnitExists('target') and IsItemInRange(state.itemname, 'target')) == (needle == 1)
if not state or not state.show or not UnitExists('target') then
return false
end
if InCombatLockdown() and not UnitCanAttack('player', 'target') then
return false
end
return IsItemInRange(state.itemname, 'target') == (needle == 1)
end,
conditionEvents = {
"PLAYER_TARGET_CHANGED",
@@ -4419,7 +4434,7 @@ Private.event_prototypes = {
return { "SPELL_COOLDOWN_CHANGED:" .. spellName }
end,
force_events = "SPELL_UPDATE_USABLE",
name = L["Action Usable"],
name = L["Spell Usable"],
statesParameter = "one",
loadFunc = function(trigger)
trigger.spellName = trigger.spellName or 0;
+2 -2
View File
@@ -449,7 +449,7 @@ local centeredIndexerStart = {
if maxIndex >= 3 then
return maxIndex - maxIndex % 2
else
return maxIndex
return maxIndex > 0 and maxIndex or nil
end
end,
-- Center -> Right -> Left, e.g: 3 1 2 4
@@ -457,7 +457,7 @@ local centeredIndexerStart = {
if maxIndex % 2 == 1 then
return maxIndex
else
return maxIndex - 1
return maxIndex > 0 and maxIndex - 1 or nil
end
end
}
+6 -4
View File
@@ -344,8 +344,9 @@ local function SetProgressSource(self, progressSource)
self:UpdateProgress()
end
local function SetAdjustedMin(self, adjustedMin)
local percent = string.match(adjustedMin, "(%d+)%%")
if percent then
local index = adjustedMin:find("%% *$")
if index then
local percent = adjustedMin:sub(1, index-1)
self.adjustedMinRelPercent = tonumber(percent) / 100
self.adjustedMin = nil
else
@@ -355,8 +356,9 @@ local function SetAdjustedMin(self, adjustedMin)
self:UpdateProgress()
end
local function SetAdjustedMax(self, adjustedMax)
local percent = string.match(adjustedMax, "(%d+)%%")
if percent then
local index = adjustedMax:find("%% *$")
if index then
local percent = adjustedMax:sub(1, index-1)
self.adjustedMaxRelPercent = tonumber(percent) / 100
else
self.adjustedMax = tonumber(adjustedMax)
+4 -3
View File
@@ -2377,8 +2377,8 @@ end
-- register options font
LSM:Register("font", "Fira Mono Medium", "Interface\\Addons\\WeakAuras\\Media\\Fonts\\FiraMono-Medium.ttf", LSM.LOCALE_BIT_western + LSM.LOCALE_BIT_ruRU)
-- Other Fira fonts
LSM:Register("font", "Fira Sans Black", "Interface\\Addons\\WeakAuras\\Media\\Fonts\\FiraSans-Black.ttf", LSM.LOCALE_BIT_western + LSM.LOCALE_BIT_ruRU)
LSM:Register("font", "Fira Sans Condensed Black", "Interface\\Addons\\WeakAuras\\Media\\Fonts\\FiraSansCondensed-Black.ttf", LSM.LOCALE_BIT_western + LSM.LOCALE_BIT_ruRU)
LSM:Register("font", "Fira Sans Black", "Interface\\Addons\\WeakAuras\\Media\\Fonts\\FiraSans-Heavy.ttf", LSM.LOCALE_BIT_western + LSM.LOCALE_BIT_ruRU)
LSM:Register("font", "Fira Sans Condensed Black", "Interface\\Addons\\WeakAuras\\Media\\Fonts\\FiraSansCondensed-Heavy.ttf", LSM.LOCALE_BIT_western + LSM.LOCALE_BIT_ruRU)
LSM:Register("font", "Fira Sans Condensed Medium", "Interface\\Addons\\WeakAuras\\Media\\Fonts\\FiraSansCondensed-Medium.ttf", LSM.LOCALE_BIT_western + LSM.LOCALE_BIT_ruRU)
LSM:Register("font", "Fira Sans Medium", "Interface\\Addons\\WeakAuras\\Media\\Fonts\\FiraSans-Medium.ttf", LSM.LOCALE_BIT_western + LSM.LOCALE_BIT_ruRU)
LSM:Register("font", "PT Sans Narrow Regular", "Interface\\Addons\\WeakAuras\\Media\\Fonts\\PTSansNarrow-Regular.ttf", LSM.LOCALE_BIT_western + LSM.LOCALE_BIT_ruRU)
@@ -2606,7 +2606,8 @@ Private.update_categories = {
"url",
"desc",
"version",
"semver"
"semver",
"wagoID", -- i don't *love* that we're so closely tied to wago, but eh
},
default = true,
label = L["Meta Data"],
+143 -97
View File
@@ -1,6 +1,6 @@
local AddonName, Private = ...
local internalVersion = 75
local internalVersion = 78
-- Lua APIs
local insert = table.insert
@@ -183,6 +183,8 @@ function SlashCmdList.WEAKAURAS(input)
WeakAuras.PrintProfile();
elseif msg == "pcancel" then
WeakAuras.CancelScheduledProfile()
elseif msg == "pshow" or msg == "profiling" then
WeakAuras.RealTimeProfilingWindow:Toggle()
elseif msg == "minimap" then
Private.ToggleMinimap();
elseif msg == "help" then
@@ -1075,21 +1077,20 @@ function Private.LoginMessage()
return loginMessage
end
function Private.Login(initialTime, takeNewSnapshots)
function Private.Login(takeNewSnapshots)
local loginThread = coroutine.create(function()
Private.Pause();
coroutine.yield(100)
if db.history then
local histRepo = WeakAuras.LoadFromArchive("Repository", "history")
local migrationRepo = WeakAuras.LoadFromArchive("Repository", "migration")
for uid, hist in pairs(db.history) do
local histStore = histRepo:Set(uid, hist.data)
local migrationStore = migrationRepo:Set(uid, hist.migration)
coroutine.yield()
coroutine.yield(1000, "login move old history")
end
-- history is now in archive so we can shrink WeakAurasSaved
db.history = nil
coroutine.yield();
end
local toAdd = {};
@@ -1103,14 +1104,15 @@ function Private.Login(initialTime, takeNewSnapshots)
tinsert(toAdd, data);
end
coroutine.yield();
coroutine.yield(8000);
Private.AddMany(toAdd, takeNewSnapshots);
coroutine.yield();
coroutine.yield(1000);
Private.RegisterLoadEvents();
coroutine.yield(10000);
Private.Resume();
coroutine.yield();
coroutine.yield(100);
local nextCallback = loginQueue[1];
while nextCallback do
@@ -1120,7 +1122,7 @@ function Private.Login(initialTime, takeNewSnapshots)
else
nextCallback()
end
coroutine.yield();
coroutine.yield(1000, "login post login callbacks");
nextCallback = loginQueue[1];
end
@@ -1129,31 +1131,12 @@ function Private.Login(initialTime, takeNewSnapshots)
for _, region in pairs(Private.regions) do
if (region.region and region.region.RunDelayedActions) then
region.region:RunDelayedActions();
coroutine.yield()
coroutine.yield(500, "login delayed region actions");
end
end
end)
if initialTime then
local startTime = debugprofilestop()
local finishTime = debugprofilestop()
local ok, msg
-- hard limit seems to be 19 seconds. We'll do 15 for now.
while coroutine.status(loginThread) ~= 'dead' and finishTime - startTime < 15000 do
ok, msg = coroutine.resume(loginThread)
finishTime = debugprofilestop()
end
if coroutine.status(loginThread) ~= 'dead' then
Private.dynFrame:AddAction('login', loginThread)
end
if not ok then
loginMessage = L["WeakAuras has encountered an error during the login process. Please report this issue at https://github.com/WeakAuras/Weakauras2/issues/new."]
.. "\nMessage:" .. msg
geterrorhandler()(msg .. '\n' .. debugstack(loginThread))
end
else
Private.dynFrame:AddAction('login', loginThread)
end
Private.Threads:Immediate('login', loginThread, 15000, 1000)
end
local WeakAurasFrame = CreateFrame("Frame", "WeakAurasFrame", UIParent);
@@ -1194,7 +1177,8 @@ loadedFrame:SetScript("OnEvent", function(self, event, addon)
if db.lastArchiveClear == nil then
db.lastArchiveClear = time();
elseif db.lastArchiveClear < time() - 86400 then
elseif db.lastArchiveClear < time() - 2505600 --[[29 days]] then
db.lastArchiveClear = time();
Private.CleanArchive(db.historyCutoff, db.migrationCutoff);
end
db.minimap = db.minimap or { hide = false };
@@ -1216,8 +1200,7 @@ loadedFrame:SetScript("OnEvent", function(self, event, addon)
dbIsValid = true
end
if dbIsValid then
-- run login thread for up to 15 seconds, then defer to dynFrame
Private.Login(15000, takeNewSnapshots)
Private.Login(takeNewSnapshots)
else
-- db isn't valid. Request permission to run repair tool before logging in
StaticPopup_Show("WEAKAURAS_CONFIRM_REPAIR", nil, nil, {reason = "downgrade"})
@@ -1412,12 +1395,15 @@ local function scanForLoadsImpl(toCheck, event, arg1, ...)
local vehicleUi = UnitHasVehicleUI("player") or false
local raidMemberType = 0
if UnitIsPartyLeader("player") then
raidMemberType = raidMemberType + 1
elseif UnitIsRaidOfficer("player") then
raidMemberType = raidMemberType + 2
end
local mounted = IsMounted()
local size, difficulty, instanceType = GetInstanceTypeAndSize()
local group = Private.ExecEnv.GroupType()
local groupSize = GetNumGroupMembers()
@@ -1433,8 +1419,8 @@ local function scanForLoadsImpl(toCheck, event, arg1, ...)
if (data and not data.controlledChildren) then
local loadFunc = loadFuncs[id];
local loadOpt = loadFuncsForOptions[id];
shouldBeLoaded = loadFunc and loadFunc("ScanForLoads_Auras", inCombat, alive, pvp, vehicle, vehicleUi, player, realm, class, race, faction, playerLevel, raidRole, group, groupSize, raidMemberType, zone, zoneId, subzone, size, difficulty);
couldBeLoaded = loadOpt and loadOpt("ScanForLoads_Auras", inCombat, alive, pvp, vehicle, vehicleUi, player, realm, class, race, faction, playerLevel, raidRole, group, groupSize, raidMemberType, zone, zoneId, subzone, size, difficulty);
shouldBeLoaded = loadFunc and loadFunc("ScanForLoads_Auras", inCombat, alive, pvp, vehicle, vehicleUi, mounted, player, realm, class, race, faction, playerLevel, raidRole, group, groupSize, raidMemberType, zone, zoneId, subzone, size, difficulty);
couldBeLoaded = loadOpt and loadOpt("ScanForLoads_Auras", inCombat, alive, pvp, vehicle, vehicleUi, mounted, player, realm, class, race, faction, playerLevel, raidRole, group, groupSize, raidMemberType, zone, zoneId, subzone, size, difficulty);
if(shouldBeLoaded and not loaded[id]) then
changed = changed + 1;
@@ -1983,20 +1969,20 @@ function Private.NeedToRepairDatabase()
return db.dbVersion and db.dbVersion > WeakAuras.InternalVersion()
end
local function RepairDatabase(loginAfter)
local function RepairDatabase()
local coro = coroutine.create(function()
Private.SetImporting(true)
-- set db version to current code version
db.dbVersion = WeakAuras.InternalVersion()
-- reinstall snapshots from history
local newDB = WeakAuras.Mixin({}, db.displays)
coroutine.yield()
coroutine.yield(1000)
for id, data in pairs(db.displays) do
local snapshot = Private.GetMigrationSnapshot(data.uid)
if snapshot then
newDB[id] = nil
newDB[snapshot.id] = snapshot
coroutine.yield()
coroutine.yield(1000, "repair get snapshot")
end
end
db.displays = newDB
@@ -2004,7 +1990,7 @@ local function RepairDatabase(loginAfter)
-- finally, login
Private.Login()
end)
Private.dynFrame:AddAction("repair", coro)
Private.Threads:Add("repair", coro, 'urgent')
end
StaticPopupDialogs["WEAKAURAS_CONFIRM_REPAIR"] = {
@@ -2165,9 +2151,9 @@ local function loadOrder(tbl, idtable)
if not(loaded[data.parent]) then
local dependsOut = CopyTable(depends)
dependsOut[data.parent] = true
coroutine.yield()
coroutine.yield(100, "sort deps")
load(data.parent, dependsOut)
coroutine.yield()
coroutine.yield(100, "sort deps")
end
end
else
@@ -2175,15 +2161,15 @@ local function loadOrder(tbl, idtable)
end
end
if not(loaded[id]) then
coroutine.yield();
coroutine.yield(100, "sort deps");
loaded[id] = true;
tinsert(order, idtable[id])
end
end
for id, data in pairs(idtable) do
for id in pairs(idtable) do
load(id, {});
coroutine.yield()
coroutine.yield(100, "sort deps")
end
return order
end
@@ -2207,17 +2193,26 @@ function Private.AddMany(tbl, takeSnapshots)
end
local order = loadOrder(tbl, idtable)
coroutine.yield()
coroutine.yield(5000)
local oldSnapshots = {}
local copies = {}
if takeSnapshots then
for _, data in ipairs(order) do
if Private.ModernizeNeedsOldSnapshot(data) then
oldSnapshots[data.uid] = Private.GetMigrationSnapshot(data.uid)
end
Private.SetMigrationSnapshot(data.uid, data)
coroutine.yield()
copies[data.uid] = CopyTable(data)
coroutine.yield(200, "addmany prepare snapshot")
end
Private.Threads:Add("snapshot", coroutine.create(function()
prettyPrint(L["WeakAuras is creating a rollback snapshot of your auras. This snapshot will allow you to revert to the current state of your auras if something goes wrong. This process may cause your framerate to drop until it is complete."])
for uid, data in pairs(copies) do
Private.SetMigrationSnapshot(uid, data)
coroutine.yield(200, "snapshot")
end
prettyPrint(L["Rollback snapshot is complete. Thank you for your patience!"])
end), 'normal')
end
local groups = {}
@@ -2238,7 +2233,7 @@ function Private.AddMany(tbl, takeSnapshots)
elseif data.regionType == "dynamicgroup" or data.regionType == "group" then
groups[data] = true
end
coroutine.yield()
coroutine.yield(1000, "addmany modernize")
end
end
@@ -2254,13 +2249,14 @@ function Private.AddMany(tbl, takeSnapshots)
end
end
end
coroutine.yield()
coroutine.yield(2000, "addmany add")
end
for id in pairs(anchorTargets) do
local data = idtable[id]
if data and not bads[data.id] and (data.parent == nil or idtable[data.parent].regionType ~= "dynamicgroup") then
Private.EnsureRegion(id)
coroutine.yield(100, "addmany ensure anchor")
end
end
@@ -2274,7 +2270,7 @@ function Private.AddMany(tbl, takeSnapshots)
WeakAuras.Add(data)
end
end
coroutine.yield();
coroutine.yield(1000, "addmany reload dynamic group");
end
end
@@ -3839,78 +3835,128 @@ function WeakAuras.EnsureString(input)
end
-- Handle coroutines
local dynFrame = {};
local threads = {
frame = CreateFrame("Frame"),
size = 0,
---@type table<string, threadPriority>
prios = {},
pools = {
urgent = {},
normal = {},
background = {},
instant = {},
},
};
do
-- Internal data
dynFrame.frame = CreateFrame("Frame");
dynFrame.update = {};
dynFrame.size = 0;
local validPriorities = {
urgent = true,
normal = true,
background = true,
instant = true,
}
-- Add an action to be resumed via OnUpdate
function dynFrame.AddAction(self, name, func)
if not name then
name = string.format("NIL", dynFrame.size+1);
function threads:Add(name, thread, prio)
if not prio or not validPriorities[prio] then
prio = "normal"
end
if type(thread) == "function" then
thread = coroutine.create(thread)
end
if not self.prios[name] then
self.prios[name] = prio
self.pools[prio][name] = {
thread = thread,
sequence = {}
}
self.size = self.size + 1
self.frame:Show()
end
end
if not dynFrame.update[name] then
dynFrame.update[name] = func;
dynFrame.size = dynFrame.size + 1
dynFrame.frame:Show();
function threads:SetPriority(name, prio)
local oldPrio = self.prios[name]
if oldPrio and oldPrio ~= prio then
self.pools[prio][name] = self.pools[oldPrio][name]
self.pools[oldPrio][name] = nil
self.prios[name] = prio
end
end
-- Remove an action from OnUpdate
function dynFrame.RemoveAction(self, name)
if dynFrame.update[name] then
dynFrame.update[name] = nil;
dynFrame.size = dynFrame.size - 1
if dynFrame.size == 0 then
dynFrame.frame:Hide();
function threads:Remove(name)
local prio = self.prios[name]
if prio then
local pool = self.pools[prio]
pool[name] = nil
self.prios[name] = nil
self.size = self.size - 1
if self.size == 0 then
self.frame:Hide()
end
end
end
-- Setup frame
dynFrame.frame:Hide();
dynFrame.frame:SetScript("OnUpdate", function(self, elapsed)
-- Start timing
local start = debugprofilestop();
local hasData = true;
-- Resume as often as possible (Limit to 16ms per frame -> 60 FPS)
while (debugprofilestop() - start < 16 and hasData) do
-- Stop loop without data
hasData = false;
-- Resume all coroutines
for name, func in pairs(dynFrame.update) do
-- Loop has data
hasData = true;
-- Resume or remove
if coroutine.status(func) ~= "dead" then
local ok, msg = coroutine.resume(func)
if not ok then
geterrorhandler()(msg .. '\n' .. debugstack(func))
end
local function runThreadPool(pool, finish, defaultEstimate)
local start = debugprofilestop()
if finish <= start then return end
local estimates = {}
local ok, val1, val2
local continue = false
repeat
continue = false
for name, threadData in pairs(pool) do
local estimate = estimates[name] or defaultEstimate
if debugprofilestop() + estimate > finish then
break
else
dynFrame:RemoveAction(name);
continue = true
ok, val1, val2 = coroutine.resume(threadData.thread)
if not ok then
geterrorhandler()(val1 .. '\n' .. debugstack(threadData.thread))
end
if coroutine.status(threadData.thread) ~= "dead" then
estimates[name] = type(val1) == "number" and val1 or defaultEstimate
local sequence = val2 or ""
threadData.sequence[sequence] = (threadData.sequence[sequence] or 0) + 1
else
threads:Remove(name)
end
end
end
until not continue
end
function threads:Immediate(name, func, limit, defaultEstimate)
self:Add(name, func, "instant")
runThreadPool(self.pools.instant, debugprofilestop() + limit, defaultEstimate or 1000)
if coroutine.status(func) ~= "dead" then
self:SetPriority(name, "urgent")
else
self:Remove(name)
end
end
-- Setup frame
threads.frame:Hide();
threads.frame:SetScript("OnUpdate", function()
local start = debugprofilestop();
runThreadPool(threads.pools.urgent, start + 15000, 1000)
runThreadPool(threads.pools.normal, start + 20, 1)
runThreadPool(threads.pools.background, start + 2, 0.5)
end);
dynFrame.frame:RegisterEvent("PLAYER_REGEN_ENABLED")
dynFrame.frame:RegisterEvent("PLAYER_REGEN_DISABLED")
dynFrame.frame:SetScript("OnEvent", function(self, event)
threads.frame:RegisterEvent("PLAYER_REGEN_ENABLED")
threads.frame:RegisterEvent("PLAYER_REGEN_DISABLED")
threads.frame:SetScript("OnEvent", function(self, event)
if event == "PLAYER_REGEN_ENABLED" and self:IsShown() then
self:Hide()
elseif event == "PLAYER_REGEN_DISABLED" and not self:IsShown() and dynFrame.size > 0 then
elseif event == "PLAYER_REGEN_DISABLED" and not self:IsShown() and threads.size > 0 then
self:Show()
end
end)
end
Private.dynFrame = dynFrame;
Private.Threads = threads;
function WeakAuras.RegisterTriggerSystem(types, triggerSystem)
for _, v in ipairs(types) do
+3
View File
@@ -72,3 +72,6 @@ SubRegionTypes\Border.lua
SubRegionTypes\Glow.lua
SubRegionTypes\Tick.lua
SubRegionTypes\Model.lua
#Misc
DiscordList.lua