Originally Posted by QuadroTony
nothing "not possible" for a good programmer =)
|
http://en.wikipedia.org/wiki/Halting_problem
More seriously, we are limited by the API. The game itself loads the whole file, so we can't change that unless we work at Zenimax and can access the game code.
Originally Posted by zgrssd
I have several reasons not to do it:
First, it is alot of work and a lot of added complexity.
Second, I also propably need some sub-division (like the namespaces) so the programmer can reset part of the data without affecting others. Doing this account or even Character wide is not granular enough.
Third and most importantly: It is pretty trivial to make versionoing yourself. Once you started making your own (for more advanced cases like migrating applicable settings from previous versions), those extra checks built into the function will be a resource drain.
I might add it later. But I don't see the need to hardcode this personally.
|
1. If this is intended to replace, I feel it should at a minimum mimic functionality.
2. I don't see the need for namespaces, as the library doesn't try for namespaces from the API. I can't come up with a decent use case of why that'd be needed either, so guess you'd need to elaborate.
3a. If it's trivial, that seems to me more argument to put it in library to limit code re-use.
3b. It's called once on the library call which should only be done for an individual bucket once per /reloadui, so it's negligible cost on setup. If someone's calling ZO_SavedVars or this every frame update (when it would have an impact), that's bad usage and should be changed regardless.
It almost seems you're trying to build in something more advanced than the ZO_SavedVars versioning, then declaring that's too much and saying no versioning is needed.I was trying to think of how to lay it out clearer, and ended up pretty much dry-coding the whole thing...
Lua Code:
--Register with LibStub
local asv = LibStub:NewLibrary("LibASV-1.0", 0.1)
if not asv then return end --the same or newer version of this lib is already loaded into memory
-- Local constants
local acctWide = "libASV_AccountWide"
local osWide = "libASV_OS_wide"
-- Utility functions
---
-- @param t - Saved variables table
-- Table has reserved field t._version for current version
-- @param version - expected version for the table
-- @param upgradeFunction - If NIL will just copy in default values. Expected f(version, table) and upgrade in-place
-- @param defaults - NOT nillable. Used to reset in case upgradeFunction is NIL
--
local function versionControl(t, version, upgradeFunction, defaults)
--t is passed in by reference, so it's changed in-place and no return needed
if version ~= t._version then
if upgradeFunction then
upgradeFunction(t._version, t)
--_version is reserved, so we want to make sure it's a good value
t._version = version
else
ZO_DeepTableCopy(defaults, t)
end
end
end
--- Utility function to access sub-table
-- @param table
-- @param key
local function accessNonNull(table, key)
if table[key] == nil then
table[key] = {}
end
return table[key]
end
-- API functions
---
-- @param savedVar (required) name used for the SavedVariables field in the manifest file
-- @param version (required) version of the saved variable
-- @param defaults (optional) defaults to use on initialization. Defaults to {}
-- @param upgradeFunction (optional) what to call if different saved variable version.
-- Default behavior is replace with defaults
-- @return (table reference) to the OS-wide saved variables
---
function asv:AccessOSUserWide(savedVar, version, defaults, upgradeFunction)
defaults = defaults or {}
--Check if initialized
if not savedVar[osWide] then
return ZO_DeepTableCopy(defaults, savedVar[osWide])
end
versionControl(savedVar[osWide], version, upgradeFunction, defaults)
return t
end
---
-- @param savedVar (required) name used for the SavedVariables field in the manifest file
-- @param version (required) version of the saved variable
-- @param defaults (optional) defaults to use on initialization. Defaults to {}
-- @param upgradeFunction (optional) what to call if different saved variable version.
-- Default behavior is replace with defaults
-- @param accountOverride (optional) which account to use. Defaults to current
-- @param characterOverride (optional) which character to use. Defaults to current
-- @return (table reference) to the saved variables for that character
---
function asv:AccessCharacterWide(savedVar, version, defaults, upgradeFunction, accountOverride, characterOverride)
accountOverride = accountOverride or GetDisplayName() --Or the more robust 'GetDisplayName' from DisplayNameFix
characterOverride = characterOverride or GetUnitName("player")
if not savedVar[accountOverride] then
savedVar[accountOverride] = {}
end
local accountTable = savedVar[accountOverride]
if not accountTable[characterOverride] then
return ZO_DeepTableCopy(defaults, accountTable[characterOverride])
end
versionControl(accountTable[characterOverride], version, upgradeFunction, defaults)
return t
end
---
-- @param savedVar (required) name used for the SavedVariables field in the manifest file
-- @param version (required) version of the saved variable
-- @param defaults (optional) defaults to use on initialization. Defaults to {}
-- @param upgradeFunction (optional) what to call if different saved variable version.
-- Default behavior is replace with defaults
-- @param accountOverride (optional) which account to use. Defaults to current
-- @return (table reference) to the saved variables for that account
---
function asv:AccessAccountWide(savedVar, version, defaults, upgradeFunction, accountOverride)
return self:AccessCharacterWide(savedVar, version, defaults, upgradeFunction, accountOverride, acctWide)
end
---
-- @param savedVar (required) name used for the SavedVariables field in the manifest file
-- @param accountOverride (optional) which account to use. Defaults to current account
-- @return array list of all characters with saved variables for the account
---
function asv:AllCharacters(savedVar, accountOverride)
accountOverride = accountOverride or GetDisplayName() --Or the more robust 'GetDisplayName' from DisplayNameFix
local accountTable = savedVar[accountOverride]
if not accountTable then
return {}
end
local chars = {}
for k in pairs(accountTable) do
if k ~= acctWide then
table.append(chars, k)
end
end
return chars
end
Sample upgrade function, showing it upgrade in-place.
Lua Code:
function upgrade(version, table)
if version < 2 then --Set new field foo to default
table.foo = 20
end
if version < 3 then -- Set new field bar to default
table.bar = 30 end
end
end
asv:AccessOSUserWide(mySavedVar, 3, { a=1,b=2, foo=20, bar=30 }, upgrade)