Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a way for auras to save data #3869

Merged
merged 2 commits into from
Oct 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
87 changes: 85 additions & 2 deletions WeakAuras/AuraEnvironment.lua
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ if WeakAuras.IsClassic() then
LCD:RegisterFrame("WeakAuras")
end

local LibSerialize = LibStub("LibSerialize")
local LibDeflate = LibStub:GetLibrary("LibDeflate")

local UnitAura = UnitAura
-- Unit Aura functions that return info about the first Aura matching the spellName or spellID given on the unit.
local WA_GetUnitAura = function(unit, spell, filter)
Expand Down Expand Up @@ -179,6 +182,7 @@ local blockedTables = {
SendMailMoneyGold = true,
MailFrameTab2 = true,
ChatFrame1 = true,
WeakAurasSaved = true,
WeakAurasOptions = true,
WeakAurasOptionsSaved = true
}
Expand All @@ -188,6 +192,7 @@ local aura_environments = {}
-- 1 == config initialized
-- 2 == fully initialized
local environment_initialized = {}
local getDataCallCounts = {}

function Private.IsEnvironmentInitialized(id)
return environment_initialized[id] == 2
Expand All @@ -196,20 +201,86 @@ end
function Private.DeleteAuraEnvironment(id)
aura_environments[id] = nil
environment_initialized[id] = nil
getDataCallCounts[id] = nil
end

function Private.RenameAuraEnvironment(oldid, newid)
aura_environments[oldid], aura_environments[newid] = nil, aura_environments[oldid]
environment_initialized[oldid], environment_initialized[newid] = nil, environment_initialized[oldid]
getDataCallCounts[oldid], getDataCallCounts[newid] = nil, getDataCallCounts[oldid]
end

local current_uid = nil
local current_aura_env = nil
-- Stack of of aura environments/uids, allows use of recursive aura activations through calls to WeakAuras.ScanEvents().
local aura_env_stack = {}


local function UpdateSavedDataWarning(uid, size)
local savedDataWarning = 16 * 1024 * 1024 -- 16 KB, but it's only a warning
if size > savedDataWarning then
Private.AuraWarnings.UpdateWarning(uid, "CustomSavedData", "warning",
L["This aura is saving %s KB of data"]:format(ceil(size / 1024)))
else
Private.AuraWarnings.UpdateWarning(uid, "CustomSavedData")
end
end

function Private.SaveAuraEnvironment(id)
local data = WeakAuras.GetData(id)
if not data then
return
end

local input = aura_environments[id] and aura_environments[id].saved
if input then
local serialized = LibSerialize:SerializeEx({errorOnUnserializableType = false}, input)
-- We use minimal compression, since that already achieves a reasonable compression ratio,
-- but takes significant less time
local compressed = LibDeflate:CompressDeflate(serialized, {level = 1})
local encoded = LibDeflate:EncodeForPrint(compressed)
UpdateSavedDataWarning(data.uid, #encoded)
data.information.saved = encoded
else
data.information.saved = nil
end
end

function Private.RestoreAuraEnvironment(id)
local data = WeakAuras.GetData(id)
if not data then
return
end

local input = data.information.saved
if input then
local decoded = LibDeflate:DecodeForPrint(input)
local decompressed = LibDeflate:DecompressDeflate(decoded)
local success, deserialized = LibSerialize:Deserialize(decompressed)
if success then
aura_environments[id].saved = deserialized
else
aura_environments[id].saved = nil
end
UpdateSavedDataWarning(data.uid, #input)
else
aura_environments[id].saved = nil
end
end

function Private.ClearAuraEnvironmentSavedData(id)
if environment_initialized[id] then
aura_environments[id].saved = nil
end
end

function Private.ClearAuraEnvironment(id)
environment_initialized[id] = nil;
if environment_initialized[id] then
Private.SaveAuraEnvironment(id)
environment_initialized[id] = nil
aura_environments[id] = nil
getDataCallCounts[id] = nil
end
end

function Private.ActivateAuraEnvironmentForRegion(region, onlyConfig)
Expand Down Expand Up @@ -244,6 +315,7 @@ function Private.ActivateAuraEnvironment(id, cloneId, state, states, onlyConfig)
elseif onlyConfig then
environment_initialized[id] = 1
aura_environments[id] = {}
getDataCallCounts[id] = 0
current_uid = data.uid
current_aura_env = aura_environments[id]
current_aura_env.id = id
Expand All @@ -260,13 +332,15 @@ function Private.ActivateAuraEnvironment(id, cloneId, state, states, onlyConfig)
-- Either this aura environment has not yet been initialized, or it was reset via an edit in WeakaurasOptions
environment_initialized[id] = 2
aura_environments[id] = aura_environments[id] or {}
getDataCallCounts[id] = getDataCallCounts[id] or 0
current_uid = data.uid
current_aura_env = aura_environments[id]
current_aura_env.id = id
current_aura_env.cloneId = cloneId
current_aura_env.state = state
current_aura_env.states = states
current_aura_env.region = region
Private.RestoreAuraEnvironment(id)
-- push new environment onto the stack
tinsert(aura_env_stack, {current_aura_env, data.uid})

Expand Down Expand Up @@ -388,7 +462,16 @@ local FakeWeakAurasMixin = {
},
override = {
me = GetUnitName("player", true),
myGUID = UnitGUID("player")
myGUID = UnitGUID("player"),
GetData = function(id)
local currentId = Private.UIDtoID(current_uid)
getDataCallCounts[currentId] = getDataCallCounts[currentId] + 1
if getDataCallCounts[currentId] > 99 then
Private.AuraWarnings.UpdateWarning(current_uid, "FakeWeakAurasGetData", "warning",
L["This aura calls GetData a lot, which is a slow function."])
end
return CopyTable(WeakAuras.GetData(id))
InfusOnWoW marked this conversation as resolved.
Show resolved Hide resolved
end
},
blocked = blocked,
setBlocked = function()
Expand Down
6 changes: 6 additions & 0 deletions WeakAuras/Types.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2928,6 +2928,9 @@ Private.non_transmissable_fields = {
skipWagoUpdate = true,
ignoreWagoUpdate = true,
preferToUpdate = true,
information = {
saved = true
}
}

-- For nested groups, we do transmit parent + controlledChildren
Expand All @@ -2936,6 +2939,9 @@ Private.non_transmissable_fields_v2000 = {
skipWagoUpdate = true,
ignoreWagoUpdate = true,
preferToUpdate = true,
information = {
saved = true
}
}

WeakAuras.data_stub = {
Expand Down
5 changes: 5 additions & 0 deletions WeakAuras/WeakAuras.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1197,6 +1197,7 @@ local loadedFrame = CreateFrame("Frame");
WeakAuras.frames["Addon Initialization Handler"] = loadedFrame;
loadedFrame:RegisterEvent("ADDON_LOADED");
loadedFrame:RegisterEvent("PLAYER_LOGIN");
loadedFrame:RegisterEvent("PLAYER_LOGOUT")
loadedFrame:RegisterEvent("PLAYER_ENTERING_WORLD");
loadedFrame:RegisterEvent("LOADING_SCREEN_ENABLED");
loadedFrame:RegisterEvent("LOADING_SCREEN_DISABLED");
Expand Down Expand Up @@ -1261,6 +1262,10 @@ loadedFrame:SetScript("OnEvent", function(self, event, addon)
-- db isn't valid. Request permission to run repair tool before logging in
StaticPopup_Show("WEAKAURAS_CONFIRM_REPAIR", nil, nil, {reason = "downgrade"})
end
elseif event == "PLAYER_LOGOUT" then
for id in pairs(db.displays) do
Private.SaveAuraEnvironment(id)
end
elseif(event == "LOADING_SCREEN_ENABLED") then
in_loading_screen = true;
elseif(event == "LOADING_SCREEN_DISABLED") then
Expand Down
46 changes: 46 additions & 0 deletions WeakAurasOptions/InformationOptions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,52 @@ function OptionsPrivate.GetInformationOptions(data)
end
end

-- Saved Data
local savedDataCount = 0
for child in OptionsPrivate.Private.TraverseLeafsOrAura(data) do
OptionsPrivate.Private.SaveAuraEnvironment(data.id)
if child.information.saved then
savedDataCount = savedDataCount + 1
end
end
if savedDataCount > 0 then
args.savedDataTitle = {
type = "header",
name = L["Saved Data"],
width = WeakAuras.doubleWidth,
order = order,
}
order = order + 1

for child in OptionsPrivate.Private.TraverseLeafsOrAura(data) do
if child.information.saved then
args["savedData." .. child.uid] = {
type = "description",
name = L["%s stores around %s KB of data"]:format(child.id, ceil((#child.information.saved) / 1024)),
width = savedDataCount > 1 and WeakAuras.doubleWidth or WeakAuras.normalWidth,
order = order,
}
order = order + 1
end
end

args.savedDataClear = {
type = "execute",
name = L["Clear Saved Data"],
width = savedDataCount > 1 and WeakAuras.doubleWidth or WeakAuras.normalWidth,
order = order,
func = function()
for child in OptionsPrivate.Private.TraverseLeafsOrAura(data) do
OptionsPrivate.Private.ClearAuraEnvironmentSavedData(child.id)
WeakAuras.Add(child)
OptionsPrivate.ClearOptions(child.id)
end
WeakAuras.ClearAndUpdateOptions(data.id)
end
}
order = order + 1
end

-- Debug Log
args.debugLogTitle = {
type = "header",
Expand Down