chore: flatten Altoholic-Addon/ wrapper + add standard .gitignore/.gitattributes
Each DataStore_* / Altoholic_* addon now lives at the repo root, matching the Exiles fork-layout convention (one folder per addon, no wrapper dir).
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
------------------------------------------------------------------------
|
||||
r22 | Thaoky | 2010-07-06 16:44:09 +0000 (Tue, 06 Jul 2010) | 1 line
|
||||
Changed paths:
|
||||
M /trunk/DataStore_Containers.lua
|
||||
|
||||
Minor code cleanup.
|
||||
------------------------------------------------------------------------
|
||||
r21 | thaoky | 2010-03-09 10:22:10 +0000 (Tue, 09 Mar 2010) | 1 line
|
||||
Changed paths:
|
||||
M /trunk/DataStore_Containers.lua
|
||||
|
||||
Added GetGuildBankTabIcon()
|
||||
------------------------------------------------------------------------
|
||||
@@ -0,0 +1,845 @@
|
||||
--[[ *** DataStore_Containers ***
|
||||
Written by : Thaoky, EU-Marécages de Zangar
|
||||
June 21st, 2009
|
||||
|
||||
This modules takes care of scanning & storing player bags, bank, & guild banks
|
||||
|
||||
Extended services:
|
||||
- guild communication: at logon, sends guild bank tab info (last visit) to guildmates
|
||||
- triggers events to manage transfers of guild bank tabs
|
||||
--]]
|
||||
if not DataStore then return end
|
||||
|
||||
local addonName = "DataStore_Containers"
|
||||
|
||||
_G[addonName] = LibStub("AceAddon-3.0"):NewAddon(addonName, "AceConsole-3.0", "AceEvent-3.0", "AceComm-3.0", "AceSerializer-3.0", "AceTimer-3.0")
|
||||
|
||||
local addon = _G[addonName]
|
||||
|
||||
local THIS_ACCOUNT = "Default"
|
||||
local commPrefix = "DS_Cont" -- let's keep it a bit shorter than the addon name, this goes on a comm channel, a byte is a byte ffs :p
|
||||
local BI = LibStub("LibBabble-Inventory-3.0"):GetLookupTable()
|
||||
|
||||
local guildMembers = {} -- hash table containing guild member info (tab timestamps)
|
||||
|
||||
-- Func Call Spam Protection
|
||||
local FCSP_timer_table_OnBagUpdate = {}
|
||||
|
||||
-- Message types
|
||||
local MSG_SEND_BANK_TIMESTAMPS = 1 -- broacast at login
|
||||
local MSG_BANK_TIMESTAMPS_REPLY = 2 -- reply to someone else's login
|
||||
local MSG_BANKTAB_REQUEST = 3 -- request bank tab data ..
|
||||
local MSG_BANKTAB_REQUEST_ACK = 4 -- .. ack the request, tell the requester to wait
|
||||
local MSG_BANKTAB_REQUEST_REJECTED = 5 -- .. refuse the request
|
||||
local MSG_BANKTAB_TRANSFER = 6 -- .. or send the data
|
||||
|
||||
local AddonDB_Defaults = {
|
||||
global = {
|
||||
Guilds = {
|
||||
['*'] = { -- ["Account.Realm.Name"]
|
||||
money = nil,
|
||||
faction = nil,
|
||||
Tabs = {
|
||||
['*'] = { -- tabID = table index [1] to [6]
|
||||
name = nil,
|
||||
icon = nil,
|
||||
visitedBy = "",
|
||||
ClientTime = 0, -- since epoch
|
||||
ClientDate = nil,
|
||||
ClientHour = nil,
|
||||
ClientMinute = nil,
|
||||
ServerHour = nil,
|
||||
ServerMinute = nil,
|
||||
ids = {},
|
||||
links = {},
|
||||
counts = {}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
Characters = {
|
||||
['*'] = { -- ["Account.Realm.Name"]
|
||||
lastUpdate = nil,
|
||||
numBagSlots = 0,
|
||||
numFreeBagSlots = 0,
|
||||
numBankSlots = 0,
|
||||
numFreeBankSlots = 0,
|
||||
Containers = {
|
||||
['*'] = { -- Containers["Bag0"]
|
||||
icon = nil, -- Containers's texture
|
||||
link = nil, -- Containers's itemlink
|
||||
size = 0,
|
||||
freeslots = 0,
|
||||
bagtype = 0,
|
||||
ids = {},
|
||||
links = {},
|
||||
counts = {},
|
||||
cooldowns = {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
local function GetDBVersion()
|
||||
return addon.db.global.Version or 0
|
||||
end
|
||||
|
||||
local function SetDBVersion(version)
|
||||
addon.db.global.Version = version
|
||||
end
|
||||
|
||||
local DBUpdaters = {
|
||||
-- Table of functions, each one updates to its index's version
|
||||
-- ex: [3] = the function that upgrades from v2 to v3
|
||||
[1] = function(self)
|
||||
|
||||
local function CopyTable(src, dest)
|
||||
for k, v in pairs (src) do
|
||||
if type(v) == "table" then
|
||||
dest[k] = {}
|
||||
CopyTable(v, dest[k])
|
||||
else
|
||||
dest[k] = v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- This function moves guild bank tabs from the "Guilds/Guildkey" level to the "Guilds/Guildkey/Tabs" sub-table
|
||||
for guildKey, guildTable in pairs(addon.db.global.Guilds) do
|
||||
for tabID = 1, 6 do -- convert the 6 tabs
|
||||
if type(guildTable[tabID]) == "table" then
|
||||
CopyTable(guildTable[tabID], guildTable.Tabs[tabID])
|
||||
wipe(guildTable[tabID])
|
||||
guildTable[tabID] = nil
|
||||
end
|
||||
end
|
||||
guildTable.money = 0
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
local function UpdateDB()
|
||||
local version = GetDBVersion()
|
||||
|
||||
for i = (version+1), #DBUpdaters do -- start from latest version +1 to the very last
|
||||
DBUpdaters[i]()
|
||||
SetDBVersion(i)
|
||||
end
|
||||
|
||||
DBUpdaters = nil
|
||||
GetDBVersion = nil
|
||||
SetDBVersion = nil
|
||||
end
|
||||
|
||||
-- *** Utility functions ***
|
||||
local function GetThisGuild()
|
||||
local guild = GetGuildInfo("player")
|
||||
if guild then
|
||||
local key = format("%s.%s.%s", THIS_ACCOUNT, GetRealmName(), guild)
|
||||
return addon.db.global.Guilds[key]
|
||||
end
|
||||
end
|
||||
|
||||
local function GetBankTimestamps(guild)
|
||||
-- returns a | delimited string containing the list of alts in the same guild
|
||||
guild = guild or GetGuildInfo("player")
|
||||
if not guild then return end
|
||||
|
||||
local thisGuild = GetThisGuild()
|
||||
if not thisGuild then return end
|
||||
|
||||
local out = {}
|
||||
for tabID, tab in pairs(thisGuild.Tabs) do
|
||||
if tab.name then
|
||||
table.insert(out, format("%d:%s:%d:%d:%d", tabID, tab.name, tab.ClientTime, tab.ServerHour, tab.ServerMinute))
|
||||
end
|
||||
end
|
||||
|
||||
return table.concat(out, "|")
|
||||
end
|
||||
|
||||
local function SaveBankTimestamps(sender, timestamps)
|
||||
if strlen(timestamps) == 0 then return end -- sender has no tabs
|
||||
|
||||
guildMembers[sender] = guildMembers[sender] or {}
|
||||
wipe(guildMembers[sender])
|
||||
|
||||
for _, v in pairs( { strsplit("|", timestamps) }) do
|
||||
local id, name, clientTime, serverHour, serverMinute = strsplit(":", v)
|
||||
|
||||
-- ex: guildMembers["Thaoky"]["RaidFood"] = { clientTime = 123, serverHour = ... }
|
||||
guildMembers[sender][name] = {}
|
||||
local tab = guildMembers[sender][name]
|
||||
tab.id = tonumber(id)
|
||||
tab.clientTime = tonumber(clientTime)
|
||||
tab.serverHour = tonumber(serverHour)
|
||||
tab.serverMinute = tonumber(serverMinute)
|
||||
end
|
||||
addon:SendMessage("DATASTORE_GUILD_BANKTABS_UPDATED", sender)
|
||||
end
|
||||
|
||||
local function GuildBroadcast(messageType, ...)
|
||||
local serializedData = addon:Serialize(messageType, ...)
|
||||
addon:SendCommMessage(commPrefix, serializedData, "GUILD")
|
||||
end
|
||||
|
||||
local function GuildWhisper(player, messageType, ...)
|
||||
if DataStore:IsGuildMemberOnline(player) then
|
||||
local serializedData = addon:Serialize(messageType, ...)
|
||||
addon:SendCommMessage(commPrefix, serializedData, "WHISPER", player)
|
||||
end
|
||||
end
|
||||
|
||||
local function IsEnchanted(link)
|
||||
if not link then return end
|
||||
|
||||
if not string.find(link, "0:0:0:0:0:0:0") then
|
||||
-- enchants/jewels store values instead of zeroes in the link, if this string can't be found, there's at least one enchant/jewel
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
local BAGS = 1 -- All bags, 0 to 11, and keyring ( id -2 )
|
||||
local BANK = 2 -- 28 main slots
|
||||
local GUILDBANK = 3 -- 98 main slots
|
||||
|
||||
local ContainerTypes = {
|
||||
[BAGS] = {
|
||||
GetSize = function(self, bagID)
|
||||
return GetContainerNumSlots(bagID)
|
||||
end,
|
||||
GetFreeSlots = function(self, bagID)
|
||||
local freeSlots, bagType = GetContainerNumFreeSlots(bagID)
|
||||
return freeSlots, bagType
|
||||
end,
|
||||
GetLink = function(self, slotID, bagID)
|
||||
return GetContainerItemLink(bagID, slotID)
|
||||
end,
|
||||
GetCount = function(self, slotID, bagID)
|
||||
local _, count = GetContainerItemInfo(bagID, slotID)
|
||||
return count
|
||||
end,
|
||||
GetCooldown = function(self, slotID, bagID)
|
||||
local startTime, duration, isEnabled = GetContainerItemCooldown(bagID, slotID)
|
||||
return startTime, duration, isEnabled
|
||||
end,
|
||||
},
|
||||
[BANK] = {
|
||||
GetSize = function(self)
|
||||
return NUM_BANKGENERIC_SLOTS or 28 -- hardcoded in case the constant is not set
|
||||
end,
|
||||
GetFreeSlots = function(self)
|
||||
local freeSlots, bagType = GetContainerNumFreeSlots(-1) -- -1 = player bank
|
||||
return freeSlots, bagType
|
||||
end,
|
||||
GetLink = function(self, slotID)
|
||||
return GetInventoryItemLink("player", slotID)
|
||||
end,
|
||||
GetCount = function(self, slotID)
|
||||
return GetInventoryItemCount("player", slotID)
|
||||
end,
|
||||
GetCooldown = function(self, slotID)
|
||||
local startTime, duration, isEnabled = GetInventoryItemCooldown("player", slotID)
|
||||
return startTime, duration, isEnabled
|
||||
end,
|
||||
},
|
||||
[GUILDBANK] = {
|
||||
GetSize = function(self)
|
||||
return MAX_GUILDBANK_SLOTS_PER_TAB or 98 -- hardcoded in case the constant is not set
|
||||
end,
|
||||
GetFreeSlots = function(self)
|
||||
return nil, nil
|
||||
end,
|
||||
GetLink = function(self, slotID, tabID)
|
||||
return GetGuildBankItemLink(tabID, slotID)
|
||||
end,
|
||||
GetCount = function(self, slotID, tabID)
|
||||
local _, count = GetGuildBankItemInfo(tabID, slotID)
|
||||
return count
|
||||
end,
|
||||
GetCooldown = function(self, slotID)
|
||||
return nil
|
||||
end,
|
||||
}
|
||||
}
|
||||
|
||||
-- *** Scanning functions ***
|
||||
local function ScanContainer(bagID, containerType)
|
||||
local Container = ContainerTypes[containerType]
|
||||
|
||||
local bag
|
||||
if containerType == GUILDBANK then
|
||||
local thisGuild = GetThisGuild()
|
||||
if not thisGuild then return end
|
||||
|
||||
bag = thisGuild.Tabs[bagID] -- bag is actually the current tab
|
||||
else
|
||||
bag = addon.ThisCharacter.Containers["Bag" .. bagID]
|
||||
wipe(bag.cooldowns) -- does not exist for a guild bank
|
||||
end
|
||||
|
||||
wipe(bag.ids) -- clean existing bag data
|
||||
wipe(bag.counts)
|
||||
wipe(bag.links)
|
||||
|
||||
local link, count
|
||||
local startTime, duration, isEnabled
|
||||
|
||||
bag.size = Container:GetSize(bagID)
|
||||
bag.freeslots, bag.bagtype = Container:GetFreeSlots(bagID)
|
||||
|
||||
-- Scan from 1 to bagsize for normal bags or guild bank tabs, but from 40 to 67 for main bank slots
|
||||
local baseIndex = (containerType == BANK) and 39 or 0
|
||||
local index
|
||||
|
||||
for slotID = baseIndex + 1, baseIndex + bag.size do
|
||||
index = slotID - baseIndex
|
||||
link = Container:GetLink(slotID, bagID)
|
||||
if link then
|
||||
bag.ids[index] = tonumber(link:match("item:(%d+)"))
|
||||
|
||||
if IsEnchanted(link) then
|
||||
bag.links[index] = link
|
||||
end
|
||||
|
||||
count = Container:GetCount(slotID, bagID)
|
||||
if count and count > 1 then
|
||||
bag.counts[index] = count -- only save the count if it's > 1 (to save some space since a count of 1 is extremely redundant)
|
||||
end
|
||||
end
|
||||
|
||||
startTime, duration, isEnabled = Container:GetCooldown(slotID, bagID)
|
||||
if startTime and startTime > 0 then
|
||||
bag.cooldowns[index] = startTime .."|".. duration .. "|" .. 1
|
||||
end
|
||||
end
|
||||
|
||||
addon.ThisCharacter.lastUpdate = time()
|
||||
end
|
||||
|
||||
local function ScanBagSlotsInfo()
|
||||
local char = addon.ThisCharacter
|
||||
|
||||
local numBagSlots = 0
|
||||
local numFreeBagSlots = 0
|
||||
|
||||
for bagID = 0, NUM_BAG_SLOTS do
|
||||
local bag = char.Containers["Bag" .. bagID]
|
||||
numBagSlots = numBagSlots + bag.size
|
||||
numFreeBagSlots = numFreeBagSlots + bag.freeslots
|
||||
end
|
||||
|
||||
char.numBagSlots = numBagSlots
|
||||
char.numFreeBagSlots = numFreeBagSlots
|
||||
end
|
||||
|
||||
local function ScanBankSlotsInfo()
|
||||
local char = addon.ThisCharacter
|
||||
|
||||
local numBankSlots = NUM_BANKGENERIC_SLOTS
|
||||
local numFreeBankSlots = char.Containers["Bag100"].freeslots
|
||||
|
||||
for bagID = NUM_BAG_SLOTS + 1, NUM_BAG_SLOTS + NUM_BANKBAGSLOTS do -- 5 to 11
|
||||
local bag = char.Containers["Bag" .. bagID]
|
||||
|
||||
numBankSlots = numBankSlots + bag.size
|
||||
numFreeBankSlots = numFreeBankSlots + bag.freeslots
|
||||
end
|
||||
|
||||
char.numBankSlots = numBankSlots
|
||||
char.numFreeBankSlots = numFreeBankSlots
|
||||
end
|
||||
|
||||
local function ScanGuildBankInfo()
|
||||
-- only the current tab can be updated
|
||||
local thisGuild = GetThisGuild()
|
||||
local tabID = GetCurrentGuildBankTab()
|
||||
local t = thisGuild.Tabs[tabID] -- t = current tab
|
||||
|
||||
t.name, t.icon = GetGuildBankTabInfo(tabID)
|
||||
t.visitedBy = UnitName("player")
|
||||
t.ClientTime = time()
|
||||
if GetLocale() == "enUS" then -- adjust this test if there's demand
|
||||
t.ClientDate = date("%m/%d/%Y")
|
||||
else
|
||||
t.ClientDate = date("%d/%m/%Y")
|
||||
end
|
||||
t.ClientHour = tonumber(date("%H"))
|
||||
t.ClientMinute = tonumber(date("%M"))
|
||||
t.ServerHour, t.ServerMinute = GetGameTime()
|
||||
end
|
||||
|
||||
local function ScanBag(bagID)
|
||||
if bagID < 0 then return end
|
||||
|
||||
local char = addon.ThisCharacter
|
||||
local bag = char.Containers["Bag" .. bagID]
|
||||
|
||||
if bagID == 0 then -- Bag 0
|
||||
bag.icon = "Interface\\Buttons\\Button-Backpack-Up";
|
||||
bag.link = nil;
|
||||
else -- Bags 1 through 11
|
||||
bag.icon = GetInventoryItemTexture("player", ContainerIDToInventoryID(bagID))
|
||||
bag.link = GetInventoryItemLink("player", ContainerIDToInventoryID(bagID))
|
||||
end
|
||||
ScanContainer(bagID, BAGS)
|
||||
ScanBagSlotsInfo()
|
||||
end
|
||||
|
||||
local function ScanKeyRing()
|
||||
local char = addon.ThisCharacter
|
||||
local bag = char.Containers["Bag" .. KEYRING_CONTAINER]
|
||||
|
||||
bag.icon = "Interface\\Icons\\INV_Misc_Key_14";
|
||||
bag.link = nil
|
||||
ScanContainer(KEYRING_CONTAINER, BAGS)
|
||||
end
|
||||
|
||||
-- *** Event Handlers ***
|
||||
-- local function OnBagUpdate(event, bag)
|
||||
local function OnBagUpdate(arg)
|
||||
local bag = arg
|
||||
|
||||
FCSP_timer_table_OnBagUpdate[bag] = nil -- manual reset (safety redundancy)
|
||||
|
||||
-- if bag < 0 then
|
||||
-- return
|
||||
-- end
|
||||
|
||||
-- if (bag >= 5) and (bag <= 11) and not addon.isBankOpen then
|
||||
-- return
|
||||
-- end
|
||||
|
||||
-- print("DataStore_Containers.lua -- OnBagUpdate(event, ",bag,")", DEBUG_CNT, format("%.3f",GetTime()%100)) -- DEBUG 2025 07 21 - 2
|
||||
|
||||
if bag == 0 then -- bag is 0 for both the keyring and the original backpack
|
||||
ScanKeyRing()
|
||||
end
|
||||
ScanBag(bag)
|
||||
end
|
||||
local function FCSP_OnBagUpdate(event, bag)
|
||||
-- this function limits calls to "OnBagUpdate" to max 1 every second
|
||||
|
||||
-- old limitations from "OnBagUpdate"
|
||||
if bag < 0 then
|
||||
return
|
||||
end
|
||||
if (bag >= 5) and (bag <= 11) and not addon.isBankOpen then
|
||||
return
|
||||
end
|
||||
|
||||
if FCSP_timer_table_OnBagUpdate[bag] then return end
|
||||
-- FCSP_timer_table_OnBagUpdate[bag] = addon:ScheduleTimer(OnBagUpdate, 1, event, bag)
|
||||
FCSP_timer_table_OnBagUpdate[bag] = addon:ScheduleTimer(OnBagUpdate, 1, bag)
|
||||
|
||||
end
|
||||
|
||||
local function OnBankFrameClosed()
|
||||
addon.isBankOpen = nil
|
||||
addon:UnregisterEvent("BANKFRAME_CLOSED")
|
||||
addon:UnregisterEvent("PLAYERBANKSLOTS_CHANGED")
|
||||
end
|
||||
|
||||
local function OnPlayerBankSlotsChanged(event, slotID)
|
||||
-- from top left to bottom right, slotID = 1 to 28for main slots, and 29 to 35 for the additional bags
|
||||
if (slotID >= 29) and (slotID <= 35) then
|
||||
ScanBag(slotID - 24) -- bagID for bank bags goes from 5 to 11, so slotID - 24
|
||||
else
|
||||
ScanContainer(100, BANK)
|
||||
ScanBankSlotsInfo()
|
||||
end
|
||||
end
|
||||
|
||||
local function OnBankFrameOpened()
|
||||
addon.isBankOpen = true
|
||||
for bagID = NUM_BAG_SLOTS + 1, NUM_BAG_SLOTS + NUM_BANKBAGSLOTS do -- 5 to 11
|
||||
ScanBag(bagID)
|
||||
end
|
||||
ScanContainer(100, BANK)
|
||||
ScanBankSlotsInfo()
|
||||
addon:RegisterEvent("BANKFRAME_CLOSED", OnBankFrameClosed)
|
||||
addon:RegisterEvent("PLAYERBANKSLOTS_CHANGED", OnPlayerBankSlotsChanged)
|
||||
end
|
||||
|
||||
local function OnGuildBankFrameClosed()
|
||||
addon:UnregisterEvent("GUILDBANKFRAME_CLOSED")
|
||||
addon:UnregisterEvent("GUILDBANKBAGSLOTS_CHANGED")
|
||||
|
||||
local guildName = GetGuildInfo("player")
|
||||
if guildName then
|
||||
GuildBroadcast(MSG_SEND_BANK_TIMESTAMPS, GetBankTimestamps(guildName))
|
||||
end
|
||||
end
|
||||
|
||||
local function OnGuildBankBagSlotsChanged()
|
||||
ScanContainer(GetCurrentGuildBankTab(), GUILDBANK)
|
||||
ScanGuildBankInfo()
|
||||
end
|
||||
|
||||
local function OnGuildBankFrameOpened()
|
||||
addon:RegisterEvent("GUILDBANKFRAME_CLOSED", OnGuildBankFrameClosed)
|
||||
addon:RegisterEvent("GUILDBANKBAGSLOTS_CHANGED", OnGuildBankBagSlotsChanged)
|
||||
|
||||
local thisGuild = GetThisGuild()
|
||||
if thisGuild then
|
||||
thisGuild.money = GetGuildBankMoney()
|
||||
thisGuild.faction = UnitFactionGroup("player")
|
||||
end
|
||||
end
|
||||
|
||||
-- ** Mixins **
|
||||
local function _GetContainer(character, containerID)
|
||||
-- containerID can be number or string
|
||||
return character.Containers["Bag" .. containerID]
|
||||
end
|
||||
|
||||
local function _GetContainers(character)
|
||||
return character.Containers
|
||||
end
|
||||
|
||||
local BagTypeStrings = {
|
||||
[1] = BI["Quiver"],
|
||||
[2] = BI["Ammo Pouch"],
|
||||
[4] = BI["Soul Bag"],
|
||||
[8] = BI["Leatherworking Bag"],
|
||||
[16] = BI["Inscription Bag"],
|
||||
[32] = BI["Herb Bag"],
|
||||
[64] = BI["Enchanting Bag"],
|
||||
[128] = BI["Engineering Bag"],
|
||||
[512] = BI["Gem Bag"],
|
||||
[1024] = BI["Mining Bag"],
|
||||
}
|
||||
|
||||
local function _GetContainerInfo(character, containerID)
|
||||
local bag = _GetContainer(character, containerID)
|
||||
return bag.icon, bag.link, bag.size, bag.freeslots, BagTypeStrings[bag.bagtype]
|
||||
end
|
||||
|
||||
local function _GetContainerSize(character, containerID)
|
||||
-- containerID can be number or string
|
||||
return character.Containers["Bag" .. containerID].size
|
||||
end
|
||||
|
||||
local function _GetSlotInfo(bag, slotID)
|
||||
assert(type(bag) == "table") -- this is the pointer to a bag table, obtained through addon:GetContainer()
|
||||
assert(type(slotID) == "number")
|
||||
|
||||
-- return itemID, itemLink, itemCount
|
||||
return bag.ids[slotID], bag.links[slotID], bag.counts[slotID] or 1
|
||||
end
|
||||
|
||||
local function _GetContainerCooldownInfo(bag, slotID)
|
||||
assert(type(bag) == "table") -- this is the pointer to a bag table, obtained through addon:GetContainer()
|
||||
assert(type(slotID) == "number")
|
||||
|
||||
local cd = bag.cooldowns[slotID]
|
||||
if cd then
|
||||
local startTime, duration, isEnabled = strsplit("|", bag.cooldowns[slotID])
|
||||
local remaining = duration - (GetTime() - startTime)
|
||||
|
||||
if remaining > 0 then -- valid cd ? return it
|
||||
return tonumber(startTime), tonumber(duration), tonumber(isEnabled)
|
||||
end
|
||||
-- cooldown expired ? clean it from the db
|
||||
bag.cooldowns[slotID] = nil
|
||||
end
|
||||
end
|
||||
|
||||
local function _GetContainerItemCount(character, searchedID)
|
||||
local bagCount = 0
|
||||
local bankCount = 0
|
||||
local id
|
||||
|
||||
for containerName, container in pairs(character.Containers) do
|
||||
for slotID=1, container.size do
|
||||
id = container.ids[slotID]
|
||||
|
||||
if (id) and (id == searchedID) then
|
||||
local itemCount = container.counts[slotID] or 1
|
||||
|
||||
if (containerName == "Bag100") then
|
||||
bankCount = bankCount + itemCount
|
||||
elseif (containerName == "Bag-2") then
|
||||
bagCount = bagCount + itemCount
|
||||
else
|
||||
local bagNum = tonumber(string.sub(containerName, 4))
|
||||
if (bagNum >= 0) and (bagNum <= 4) then
|
||||
bagCount = bagCount + itemCount
|
||||
else
|
||||
bankCount = bankCount + itemCount
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return bagCount, bankCount
|
||||
end
|
||||
|
||||
local function _GetNumBagSlots(character)
|
||||
return character.numBagSlots
|
||||
end
|
||||
|
||||
local function _GetNumFreeBagSlots(character)
|
||||
return character.numFreeBagSlots
|
||||
end
|
||||
|
||||
local function _GetNumBankSlots(character)
|
||||
return character.numBankSlots
|
||||
end
|
||||
|
||||
local function _GetNumFreeBankSlots(character)
|
||||
return character.numFreeBankSlots
|
||||
end
|
||||
|
||||
local function _DeleteGuild(name, realm, account)
|
||||
realm = realm or GetRealmName()
|
||||
account = account or THIS_ACCOUNT
|
||||
|
||||
local key = format("%s.%s.%s", account, realm, name)
|
||||
addon.db.global.Guilds[key] = nil
|
||||
end
|
||||
|
||||
local function _GetGuildBankItemCount(guild, searchedID)
|
||||
local count = 0
|
||||
for _, container in pairs(guild.Tabs) do
|
||||
for slotID, id in pairs(container.ids) do
|
||||
if (id == searchedID) then
|
||||
count = count + (container.counts[slotID] or 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
||||
local function _GetGuildBankTab(guild, tabID)
|
||||
return guild.Tabs[tabID]
|
||||
end
|
||||
|
||||
local function _GetGuildBankTabName(guild, tabID)
|
||||
return guild.Tabs[tabID].name
|
||||
end
|
||||
|
||||
local function _GetGuildBankTabIcon(guild, tabID)
|
||||
return guild.Tabs[tabID].icon
|
||||
end
|
||||
|
||||
local function _GetGuildBankTabItemCount(guild, tabID, searchedID)
|
||||
local count = 0
|
||||
local container = guild.Tabs[tabID]
|
||||
|
||||
for slotID, id in pairs(container.ids) do
|
||||
if (id == searchedID) then
|
||||
count = count + (container.counts[slotID] or 1)
|
||||
end
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
||||
local function _GetGuildBankTabLastUpdate(guild, tabID)
|
||||
return guild.Tabs[tabID].ClientTime
|
||||
end
|
||||
|
||||
local function _GetGuildBankMoney(guild)
|
||||
return guild.money
|
||||
end
|
||||
|
||||
local function _GetGuildBankFaction(guild)
|
||||
return guild.faction
|
||||
end
|
||||
|
||||
local function _ImportGuildBankTab(guild, tabID, data)
|
||||
wipe(guild.Tabs[tabID]) -- clear existing data
|
||||
guild.Tabs[tabID] = data
|
||||
end
|
||||
|
||||
local function _GetGuildBankTabSuppliers()
|
||||
return guildMembers
|
||||
end
|
||||
|
||||
local function _GetGuildMemberBankTabInfo(member, tabName)
|
||||
-- for the current guild, return the guild member's data about a given tab
|
||||
if guildMembers[member] then
|
||||
if guildMembers[member][tabName] then
|
||||
local tab = guildMembers[member][tabName]
|
||||
return tab.clientTime, tab.serverHour, tab.serverMinute
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function _RequestGuildMemberBankTab(member, tabName)
|
||||
GuildWhisper(member, MSG_BANKTAB_REQUEST, tabName)
|
||||
end
|
||||
|
||||
local function _RejectBankTabRequest(member)
|
||||
GuildWhisper(member, MSG_BANKTAB_REQUEST_REJECTED)
|
||||
end
|
||||
|
||||
local function _SendBankTabToGuildMember(member, tabName)
|
||||
-- send the actual content of a bank tab to a guild member
|
||||
local thisGuild = GetThisGuild()
|
||||
if thisGuild then
|
||||
local tabID
|
||||
if guildMembers[member] then
|
||||
if guildMembers[member][tabName] then
|
||||
tabID = guildMembers[member][tabName].id
|
||||
end
|
||||
end
|
||||
|
||||
if tabID then
|
||||
GuildWhisper(member, MSG_BANKTAB_TRANSFER, thisGuild.Tabs[tabID])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local PublicMethods = {
|
||||
GetContainer = _GetContainer,
|
||||
GetContainers = _GetContainers,
|
||||
GetContainerInfo = _GetContainerInfo,
|
||||
GetContainerSize = _GetContainerSize,
|
||||
GetSlotInfo = _GetSlotInfo,
|
||||
GetContainerCooldownInfo = _GetContainerCooldownInfo,
|
||||
GetContainerItemCount = _GetContainerItemCount,
|
||||
GetNumBagSlots = _GetNumBagSlots,
|
||||
GetNumFreeBagSlots = _GetNumFreeBagSlots,
|
||||
GetNumBankSlots = _GetNumBankSlots,
|
||||
GetNumFreeBankSlots = _GetNumFreeBankSlots,
|
||||
DeleteGuild = _DeleteGuild,
|
||||
GetGuildBankItemCount = _GetGuildBankItemCount,
|
||||
GetGuildBankTab = _GetGuildBankTab,
|
||||
GetGuildBankTabName = _GetGuildBankTabName,
|
||||
GetGuildBankTabIcon = _GetGuildBankTabIcon,
|
||||
GetGuildBankTabItemCount = _GetGuildBankTabItemCount,
|
||||
GetGuildBankTabLastUpdate = _GetGuildBankTabLastUpdate,
|
||||
GetGuildBankMoney = _GetGuildBankMoney,
|
||||
GetGuildBankFaction = _GetGuildBankFaction,
|
||||
ImportGuildBankTab = _ImportGuildBankTab,
|
||||
GetGuildMemberBankTabInfo = _GetGuildMemberBankTabInfo,
|
||||
RequestGuildMemberBankTab = _RequestGuildMemberBankTab,
|
||||
RejectBankTabRequest = _RejectBankTabRequest,
|
||||
SendBankTabToGuildMember = _SendBankTabToGuildMember,
|
||||
GetGuildBankTabSuppliers = _GetGuildBankTabSuppliers,
|
||||
}
|
||||
|
||||
-- *** Guild Comm ***
|
||||
--[[ *** Protocol ***
|
||||
|
||||
At login:
|
||||
Broadcast of guild bank timers on the guild channel
|
||||
After the guild bank frame is closed:
|
||||
Broadcast of guild bank timers on the guild channel
|
||||
|
||||
Client addon calls: DataStore:RequestGuildMemberBankTab()
|
||||
Client Server
|
||||
|
||||
==> MSG_BANKTAB_REQUEST
|
||||
<== MSG_BANKTAB_REQUEST_ACK (immediate ack)
|
||||
|
||||
<== MSG_BANKTAB_REQUEST_REJECTED (stop)
|
||||
or
|
||||
<== MSG_BANKTAB_TRANSFER (actual data transfer)
|
||||
--]]
|
||||
|
||||
local function OnAnnounceLogin(self, guildName)
|
||||
-- when the main DataStore module sends its login info, share the guild bank last visit time across guild members
|
||||
local timestamps = GetBankTimestamps(guildName)
|
||||
if timestamps then -- nil if guild bank hasn't been visited yet, so don't broadcast anything
|
||||
GuildBroadcast(MSG_SEND_BANK_TIMESTAMPS, timestamps)
|
||||
end
|
||||
end
|
||||
|
||||
local function OnGuildMemberOffline(self, member)
|
||||
guildMembers[member] = nil
|
||||
addon:SendMessage("DATASTORE_GUILD_BANKTABS_UPDATED", member)
|
||||
end
|
||||
|
||||
local GuildCommCallbacks = {
|
||||
[MSG_SEND_BANK_TIMESTAMPS] = function(sender, timestamps)
|
||||
if sender ~= UnitName("player") then -- don't send back to self
|
||||
local timestamps = GetBankTimestamps()
|
||||
if timestamps then
|
||||
GuildWhisper(sender, MSG_BANK_TIMESTAMPS_REPLY, timestamps) -- reply by sending my own data..
|
||||
end
|
||||
end
|
||||
SaveBankTimestamps(sender, timestamps)
|
||||
end,
|
||||
[MSG_BANK_TIMESTAMPS_REPLY] = function(sender, timestamps)
|
||||
SaveBankTimestamps(sender, timestamps)
|
||||
end,
|
||||
[MSG_BANKTAB_REQUEST] = function(sender, tabName)
|
||||
-- trigger the event only, actual response (ack or not) must be handled by client addons
|
||||
GuildWhisper(sender, MSG_BANKTAB_REQUEST_ACK) -- confirm that the request has been received
|
||||
addon:SendMessage("DATASTORE_BANKTAB_REQUESTED", sender, tabName)
|
||||
end,
|
||||
[MSG_BANKTAB_REQUEST_ACK] = function(sender)
|
||||
addon:SendMessage("DATASTORE_BANKTAB_REQUEST_ACK", sender)
|
||||
end,
|
||||
[MSG_BANKTAB_REQUEST_REJECTED] = function(sender)
|
||||
addon:SendMessage("DATASTORE_BANKTAB_REQUEST_REJECTED", sender)
|
||||
end,
|
||||
[MSG_BANKTAB_TRANSFER] = function(sender, data)
|
||||
local guildName = GetGuildInfo("player")
|
||||
local guild = GetThisGuild()
|
||||
|
||||
for tabID, tab in pairs(guild.Tabs) do
|
||||
if tab.name == data.name then -- this is the tab being updated
|
||||
_ImportGuildBankTab(guild, tabID, data)
|
||||
addon:SendMessage("DATASTORE_BANKTAB_UPDATE_SUCCESS", sender, guildName, data.name, tabID)
|
||||
GuildBroadcast(MSG_SEND_BANK_TIMESTAMPS, GetBankTimestamps(guildName))
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
|
||||
function addon:OnInitialize()
|
||||
addon.db = LibStub("AceDB-3.0"):New(addonName .. "DB", AddonDB_Defaults)
|
||||
UpdateDB()
|
||||
|
||||
DataStore:RegisterModule(addonName, addon, PublicMethods)
|
||||
DataStore:SetGuildCommCallbacks(commPrefix, GuildCommCallbacks)
|
||||
|
||||
DataStore:SetCharacterBasedMethod("GetContainer")
|
||||
DataStore:SetCharacterBasedMethod("GetContainers")
|
||||
DataStore:SetCharacterBasedMethod("GetContainerInfo")
|
||||
DataStore:SetCharacterBasedMethod("GetContainerSize")
|
||||
DataStore:SetCharacterBasedMethod("GetContainerItemCount")
|
||||
DataStore:SetCharacterBasedMethod("GetNumBagSlots")
|
||||
DataStore:SetCharacterBasedMethod("GetNumFreeBagSlots")
|
||||
DataStore:SetCharacterBasedMethod("GetNumBankSlots")
|
||||
DataStore:SetCharacterBasedMethod("GetNumFreeBankSlots")
|
||||
|
||||
DataStore:SetGuildBasedMethod("GetGuildBankItemCount")
|
||||
DataStore:SetGuildBasedMethod("GetGuildBankTab")
|
||||
DataStore:SetGuildBasedMethod("GetGuildBankTabName")
|
||||
DataStore:SetGuildBasedMethod("GetGuildBankTabIcon")
|
||||
DataStore:SetGuildBasedMethod("GetGuildBankTabItemCount")
|
||||
DataStore:SetGuildBasedMethod("GetGuildBankTabLastUpdate")
|
||||
DataStore:SetGuildBasedMethod("GetGuildBankMoney")
|
||||
DataStore:SetGuildBasedMethod("GetGuildBankFaction")
|
||||
DataStore:SetGuildBasedMethod("ImportGuildBankTab")
|
||||
|
||||
addon:RegisterMessage("DATASTORE_ANNOUNCELOGIN", OnAnnounceLogin)
|
||||
addon:RegisterMessage("DATASTORE_GUILD_MEMBER_OFFLINE", OnGuildMemberOffline)
|
||||
addon:RegisterComm(commPrefix, DataStore:GetGuildCommHandler())
|
||||
end
|
||||
|
||||
function addon:OnEnable()
|
||||
-- manually update bags 0 to 4, then register the event, this avoids reacting to the flood of BAG_UPDATE events at login
|
||||
for bagID = 0, NUM_BAG_SLOTS do
|
||||
ScanBag(bagID)
|
||||
end
|
||||
ScanKeyRing()
|
||||
|
||||
-- addon:RegisterEvent("BAG_UPDATE", OnBagUpdate)
|
||||
addon:RegisterEvent("BAG_UPDATE", FCSP_OnBagUpdate)
|
||||
addon:RegisterEvent("BANKFRAME_OPENED", OnBankFrameOpened)
|
||||
addon:RegisterEvent("GUILDBANKFRAME_OPENED", OnGuildBankFrameOpened)
|
||||
end
|
||||
|
||||
function addon:OnDisable()
|
||||
addon:UnregisterEvent("BAG_UPDATE")
|
||||
addon:UnregisterEvent("BANKFRAME_OPENED")
|
||||
addon:UnregisterEvent("GUILDBANKFRAME_OPENED")
|
||||
end
|
||||
@@ -0,0 +1,18 @@
|
||||
## Interface: 30300
|
||||
## Title: DataStore_Containers
|
||||
## Notes: Stores information about character bags, bank, and guild banks
|
||||
## Author: Thaoky (EU-Marécages de Zangar)
|
||||
## Version: 3.3.001
|
||||
## Dependencies: DataStore
|
||||
## OptionalDeps: Ace3
|
||||
## SavedVariables: DataStore_ContainersDB
|
||||
## X-Category: Interface Enhancements
|
||||
## X-Embeds: Ace3
|
||||
## X-Curse-Packaged-Version: r22
|
||||
## X-Curse-Project-Name: DataStore_Containers
|
||||
## X-Curse-Project-ID: datastore_containers
|
||||
## X-Curse-Repository-ID: wow/datastore_containers/mainline
|
||||
|
||||
embeds.xml
|
||||
|
||||
DataStore_Containers.lua
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
All Rights Reserved unless otherwise explicitly stated.
|
||||
@@ -0,0 +1,5 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\FrameXML\UI.xsd">
|
||||
|
||||
<Include file="libs\LibBabble-Inventory-3.0\lib.xml"/>
|
||||
</Ui>
|
||||
@@ -0,0 +1,292 @@
|
||||
-- LibBabble-3.0 is hereby placed in the Public Domain
|
||||
-- Credits: ckknight
|
||||
local LIBBABBLE_MAJOR, LIBBABBLE_MINOR = "LibBabble-3.0", 2
|
||||
|
||||
local LibBabble = LibStub:NewLibrary(LIBBABBLE_MAJOR, LIBBABBLE_MINOR)
|
||||
if not LibBabble then
|
||||
return
|
||||
end
|
||||
|
||||
local data = LibBabble.data or {}
|
||||
for k,v in pairs(LibBabble) do
|
||||
LibBabble[k] = nil
|
||||
end
|
||||
LibBabble.data = data
|
||||
|
||||
local tablesToDB = {}
|
||||
for namespace, db in pairs(data) do
|
||||
for k,v in pairs(db) do
|
||||
tablesToDB[v] = db
|
||||
end
|
||||
end
|
||||
|
||||
local function warn(message)
|
||||
local _, ret = pcall(error, message, 3)
|
||||
geterrorhandler()(ret)
|
||||
end
|
||||
|
||||
local lookup_mt = { __index = function(self, key)
|
||||
local db = tablesToDB[self]
|
||||
local current_key = db.current[key]
|
||||
if current_key then
|
||||
self[key] = current_key
|
||||
return current_key
|
||||
end
|
||||
local base_key = db.base[key]
|
||||
local real_MAJOR_VERSION
|
||||
for k,v in pairs(data) do
|
||||
if v == db then
|
||||
real_MAJOR_VERSION = k
|
||||
break
|
||||
end
|
||||
end
|
||||
if not real_MAJOR_VERSION then
|
||||
real_MAJOR_VERSION = LIBBABBLE_MAJOR
|
||||
end
|
||||
if base_key then
|
||||
warn(("%s: Translation %q not found for locale %q"):format(real_MAJOR_VERSION, key, GetLocale()))
|
||||
rawset(self, key, base_key)
|
||||
return base_key
|
||||
end
|
||||
warn(("%s: Translation %q not found."):format(real_MAJOR_VERSION, key))
|
||||
rawset(self, key, key)
|
||||
return key
|
||||
end }
|
||||
|
||||
local function initLookup(module, lookup)
|
||||
local db = tablesToDB[module]
|
||||
for k in pairs(lookup) do
|
||||
lookup[k] = nil
|
||||
end
|
||||
setmetatable(lookup, lookup_mt)
|
||||
tablesToDB[lookup] = db
|
||||
db.lookup = lookup
|
||||
return lookup
|
||||
end
|
||||
|
||||
local function initReverse(module, reverse)
|
||||
local db = tablesToDB[module]
|
||||
for k in pairs(reverse) do
|
||||
reverse[k] = nil
|
||||
end
|
||||
for k,v in pairs(db.current) do
|
||||
reverse[v] = k
|
||||
end
|
||||
tablesToDB[reverse] = db
|
||||
db.reverse = reverse
|
||||
db.reverseIterators = nil
|
||||
return reverse
|
||||
end
|
||||
|
||||
local prototype = {}
|
||||
local prototype_mt = {__index = prototype}
|
||||
|
||||
--[[---------------------------------------------------------------------------
|
||||
Notes:
|
||||
* If you try to access a nonexistent key, it will warn but allow the code to pass through.
|
||||
Returns:
|
||||
A lookup table for english to localized words.
|
||||
Example:
|
||||
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want.
|
||||
local BL = B:GetLookupTable()
|
||||
assert(BL["Some english word"] == "Some localized word")
|
||||
DoSomething(BL["Some english word that doesn't exist"]) -- warning!
|
||||
-----------------------------------------------------------------------------]]
|
||||
function prototype:GetLookupTable()
|
||||
local db = tablesToDB[self]
|
||||
|
||||
local lookup = db.lookup
|
||||
if lookup then
|
||||
return lookup
|
||||
end
|
||||
return initLookup(self, {})
|
||||
end
|
||||
--[[---------------------------------------------------------------------------
|
||||
Notes:
|
||||
* If you try to access a nonexistent key, it will return nil.
|
||||
Returns:
|
||||
A lookup table for english to localized words.
|
||||
Example:
|
||||
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want.
|
||||
local B_has = B:GetUnstrictLookupTable()
|
||||
assert(B_has["Some english word"] == "Some localized word")
|
||||
assert(B_has["Some english word that doesn't exist"] == nil)
|
||||
-----------------------------------------------------------------------------]]
|
||||
function prototype:GetUnstrictLookupTable()
|
||||
local db = tablesToDB[self]
|
||||
|
||||
return db.current
|
||||
end
|
||||
--[[---------------------------------------------------------------------------
|
||||
Notes:
|
||||
* If you try to access a nonexistent key, it will return nil.
|
||||
* This is useful for checking if the base (English) table has a key, even if the localized one does not have it registered.
|
||||
Returns:
|
||||
A lookup table for english to localized words.
|
||||
Example:
|
||||
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want.
|
||||
local B_hasBase = B:GetBaseLookupTable()
|
||||
assert(B_hasBase["Some english word"] == "Some english word")
|
||||
assert(B_hasBase["Some english word that doesn't exist"] == nil)
|
||||
-----------------------------------------------------------------------------]]
|
||||
function prototype:GetBaseLookupTable()
|
||||
local db = tablesToDB[self]
|
||||
|
||||
return db.base
|
||||
end
|
||||
--[[---------------------------------------------------------------------------
|
||||
Notes:
|
||||
* If you try to access a nonexistent key, it will return nil.
|
||||
* This will return only one English word that it maps to, if there are more than one to check, see :GetReverseIterator("word")
|
||||
Returns:
|
||||
A lookup table for localized to english words.
|
||||
Example:
|
||||
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want.
|
||||
local BR = B:GetReverseLookupTable()
|
||||
assert(BR["Some localized word"] == "Some english word")
|
||||
assert(BR["Some localized word that doesn't exist"] == nil)
|
||||
-----------------------------------------------------------------------------]]
|
||||
function prototype:GetReverseLookupTable()
|
||||
local db = tablesToDB[self]
|
||||
|
||||
local reverse = db.reverse
|
||||
if reverse then
|
||||
return reverse
|
||||
end
|
||||
return initReverse(self, {})
|
||||
end
|
||||
local blank = {}
|
||||
local weakVal = {__mode='v'}
|
||||
--[[---------------------------------------------------------------------------
|
||||
Arguments:
|
||||
string - the localized word to chek for.
|
||||
Returns:
|
||||
An iterator to traverse all English words that map to the given key
|
||||
Example:
|
||||
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want.
|
||||
for word in B:GetReverseIterator("Some localized word") do
|
||||
DoSomething(word)
|
||||
end
|
||||
-----------------------------------------------------------------------------]]
|
||||
function prototype:GetReverseIterator(key)
|
||||
local db = tablesToDB[self]
|
||||
local reverseIterators = db.reverseIterators
|
||||
if not reverseIterators then
|
||||
reverseIterators = setmetatable({}, weakVal)
|
||||
db.reverseIterators = reverseIterators
|
||||
elseif reverseIterators[key] then
|
||||
return pairs(reverseIterators[key])
|
||||
end
|
||||
local t
|
||||
for k,v in pairs(db.current) do
|
||||
if v == key then
|
||||
if not t then
|
||||
t = {}
|
||||
end
|
||||
t[k] = true
|
||||
end
|
||||
end
|
||||
reverseIterators[key] = t or blank
|
||||
return pairs(reverseIterators[key])
|
||||
end
|
||||
--[[---------------------------------------------------------------------------
|
||||
Returns:
|
||||
An iterator to traverse all translations English to localized.
|
||||
Example:
|
||||
local B = LibStub("LibBabble-Module-3.0") -- where Module is what you want.
|
||||
for english, localized in B:Iterate() do
|
||||
DoSomething(english, localized)
|
||||
end
|
||||
-----------------------------------------------------------------------------]]
|
||||
function prototype:Iterate()
|
||||
local db = tablesToDB[self]
|
||||
|
||||
return pairs(db.current)
|
||||
end
|
||||
|
||||
-- #NODOC
|
||||
-- modules need to call this to set the base table
|
||||
function prototype:SetBaseTranslations(base)
|
||||
local db = tablesToDB[self]
|
||||
local oldBase = db.base
|
||||
if oldBase then
|
||||
for k in pairs(oldBase) do
|
||||
oldBase[k] = nil
|
||||
end
|
||||
for k, v in pairs(base) do
|
||||
oldBase[k] = v
|
||||
end
|
||||
base = oldBase
|
||||
else
|
||||
db.base = base
|
||||
end
|
||||
for k,v in pairs(base) do
|
||||
if v == true then
|
||||
base[k] = k
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function init(module)
|
||||
local db = tablesToDB[module]
|
||||
if db.lookup then
|
||||
initLookup(module, db.lookup)
|
||||
end
|
||||
if db.reverse then
|
||||
initReverse(module, db.reverse)
|
||||
end
|
||||
db.reverseIterators = nil
|
||||
end
|
||||
|
||||
-- #NODOC
|
||||
-- modules need to call this to set the current table. if current is true, use the base table.
|
||||
function prototype:SetCurrentTranslations(current)
|
||||
local db = tablesToDB[self]
|
||||
if current == true then
|
||||
db.current = db.base
|
||||
else
|
||||
local oldCurrent = db.current
|
||||
if oldCurrent then
|
||||
for k in pairs(oldCurrent) do
|
||||
oldCurrent[k] = nil
|
||||
end
|
||||
for k, v in pairs(current) do
|
||||
oldCurrent[k] = v
|
||||
end
|
||||
current = oldCurrent
|
||||
else
|
||||
db.current = current
|
||||
end
|
||||
end
|
||||
init(self)
|
||||
end
|
||||
|
||||
for namespace, db in pairs(data) do
|
||||
setmetatable(db.module, prototype_mt)
|
||||
init(db.module)
|
||||
end
|
||||
|
||||
-- #NODOC
|
||||
-- modules need to call this to create a new namespace.
|
||||
function LibBabble:New(namespace, minor)
|
||||
local module, oldminor = LibStub:NewLibrary(namespace, minor)
|
||||
if not module then
|
||||
return
|
||||
end
|
||||
|
||||
if not oldminor then
|
||||
local db = {
|
||||
module = module,
|
||||
}
|
||||
data[namespace] = db
|
||||
tablesToDB[module] = db
|
||||
else
|
||||
for k,v in pairs(module) do
|
||||
module[k] = nil
|
||||
end
|
||||
end
|
||||
|
||||
setmetatable(module, prototype_mt)
|
||||
|
||||
return module
|
||||
end
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,16 @@
|
||||
## Interface: 30300
|
||||
## LoadOnDemand: 1
|
||||
## Title: Lib: Babble-Inventory-3.0
|
||||
## Notes: A library to help with localization of item types and subtypes.
|
||||
## Notes-esES: Una libreria para ayudar con la traduccion de tipos y subtipos de objetos.
|
||||
## Author: ckknight
|
||||
## X-eMail: ckknight@gmail.com
|
||||
## X-Category: Library
|
||||
## X-License: MIT
|
||||
## X-Curse-Packaged-Version: r101
|
||||
## X-Curse-Project-Name: LibBabble-Inventory-3.0
|
||||
## X-Curse-Project-ID: libbabble-inventory-3-0
|
||||
## X-Curse-Repository-ID: wow/libbabble-inventory-3-0/mainline
|
||||
|
||||
LibStub\LibStub.lua
|
||||
lib.xml
|
||||
@@ -0,0 +1,30 @@
|
||||
-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/wiki/LibStub for more info
|
||||
-- LibStub is hereby placed in the Public Domain Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
|
||||
local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
|
||||
local LibStub = _G[LIBSTUB_MAJOR]
|
||||
|
||||
if not LibStub or LibStub.minor < LIBSTUB_MINOR then
|
||||
LibStub = LibStub or {libs = {}, minors = {} }
|
||||
_G[LIBSTUB_MAJOR] = LibStub
|
||||
LibStub.minor = LIBSTUB_MINOR
|
||||
|
||||
function LibStub:NewLibrary(major, minor)
|
||||
assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
|
||||
minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
|
||||
|
||||
local oldminor = self.minors[major]
|
||||
if oldminor and oldminor >= minor then return nil end
|
||||
self.minors[major], self.libs[major] = minor, self.libs[major] or {}
|
||||
return self.libs[major], oldminor
|
||||
end
|
||||
|
||||
function LibStub:GetLibrary(major, silent)
|
||||
if not self.libs[major] and not silent then
|
||||
error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
|
||||
end
|
||||
return self.libs[major], self.minors[major]
|
||||
end
|
||||
|
||||
function LibStub:IterateLibraries() return pairs(self.libs) end
|
||||
setmetatable(LibStub, { __call = LibStub.GetLibrary })
|
||||
end
|
||||
@@ -0,0 +1,5 @@
|
||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||
..\FrameXML\UI.xsd">
|
||||
<Script file="LibBabble-3.0.lua" />
|
||||
<Script file="LibBabble-Inventory-3.0.lua" />
|
||||
</Ui>
|
||||
Reference in New Issue
Block a user