local _, db = ...; local Shared = db:Register('Shared', CPAPI.CreateEventHandler({'Frame', '$parentShared', ConsolePort}, { 'PLAYER_LOGOUT'; }, { Data = {}; })) db:Save('Shared/Data', 'ConsolePortShared') --------------------------------------------------------------- -- Shared metatable --------------------------------------------------------------- local sharedMeta = { __index = function(self, key) if Shared[key] then local k, v = Shared[key]() rawset(self, k, setmetatable(rawget(self, k) or v, getmetatable(self))) return rawget(self, k); end rawset(self, key, setmetatable({}, getmetatable(self))) return rawget(self, key); end; }; --------------------------------------------------------------- -- Entry generation --------------------------------------------------------------- Shared[''] = function() local name = GetUnitName('player') local specID, specName, _, icon = CPAPI.GetCharacterMetadata() return -- guid, preset ('%s (%s) %s'):format(name, specName, GetRealmName()), { Meta = { Type = db.Gamepad:GetActiveDeviceName(); Class = select(2, UnitClass('player')); Spec = specID; Icon = icon; Name = name; }; } end --------------------------------------------------------------- -- API --------------------------------------------------------------- function Shared:SavePlayerData(set, newData, unique) if unique then local cmp = db.table.compare; for character, data in pairs(self.Data) do if data[set] and cmp(data[set], newData) then return false; end end end self.Data[''][set] = db.table.copy(newData); return true; end function Shared:SaveData(idx, set, newData, unique) if unique then local cmp = db.table.compare; for owner, data in pairs(self.Data) do if data[set] and cmp(data[set], newData) then return false; end end end self.Data[idx][set] = db.table.copy(newData); end function Shared:SaveBindings(bindings) self:SavePlayerData('Bindings', bindings, true) end --------------------------------------------------------------- -- Collect garbage --------------------------------------------------------------- function Shared:PLAYER_LOGOUT() self:CollectGarbageRecursive(self.Data) self:CollectCharacterGarbage() end function Shared:CollectCharacterGarbage() local charactersToCollect = {}; for character, data in pairs(self.Data) do local meta = data.Meta; data.Meta = nil; if not next(data) then charactersToCollect[character] = true; else data.Meta = meta; end end for character in pairs(charactersToCollect) do self.Data[character] = nil; end end function Shared:CollectGarbageRecursive(tbl) for k, v in pairs(tbl) do if (type(v) == 'table') then self:CollectGarbageRecursive(v) if (next(v) == nil) then tbl[k] = nil; end end end end function Shared:OnDataLoaded() db:Load('Shared/Data', 'ConsolePortShared') db:RegisterCallback('OnNewBindings', self.SaveBindings, self) setmetatable(self.Data, sharedMeta) end