-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcore.lua
More file actions
313 lines (257 loc) · 9.9 KB
/
Copy pathcore.lua
File metadata and controls
313 lines (257 loc) · 9.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
--[[ Stash --------------------------------------------------------------------
Remembers what is in your bank (and guild bank, where the client has one) so
you can look at it from anywhere.
Nothing here draws a bank. The cached contents are poured into whichever bank
window you already use - Blizzard's BankFrame, Bagnon's Banknon, anything else
registered as a backend - so the cached bank looks exactly like the real one.
For windows that have no cache of their own, the data reaches them by wrapping
the container and inventory API: while the cached view is up,
GetContainerItemInfo and friends answer from the cache for bank containers.
Any bag addon asking the usual questions therefore sees it too.
Files
core.lua saved variables, shared helpers, slash commands
cache.lua captures the bank when it is opened, changed and closed
shim.lua the container/inventory API wrappers
tooltip.lua the same for GameTooltip, which reads slots inside the client
backends.lua the bank windows that can be opened, and picking between them
viewer.lua turns the cached view on and off
guildbank.lua the same for the guild bank, if this client has one
minimap.lua the button
-----------------------------------------------------------------------------]]
Stash = {}
-- Every file registers itself here. Vanilla only enumerates an addon's files
-- when the client starts, so a newly added file stays missing until a full
-- restart even though /reload brings back the edited ones. Checking at login
-- turns that silent half-load into a message that says what to do.
Stash.modules = {}
Stash.required = { "cache", "shim", "tooltip", "backends", "viewer", "minimap" }
local pairs, ipairs = pairs, ipairs
local getn, sort = table.getn, table.sort
Stash.version = "1.0.1"
-- Containers that make up the bank. -1 is the bank window itself, and the
-- purchasable bank bags follow it starting at 5.
--
-- Stock 1.12 has six of them, but derived clients do not all agree - this one
-- draws seven bag buttons. FrameXML is loaded before addons, so counting the
-- buttons the client actually has is more reliable than trusting a constant.
Stash.BANK_CONTAINER = -1
Stash.FIRST_BANK_BAG = 5
local function CountBankBags()
local buttons = 0
while getglobal("BankFrameBag" .. (buttons + 1)) do
buttons = buttons + 1
if buttons > 24 then
break
end
end
local declared = NUM_BANKBAGSLOTS or 0
local count = buttons > declared and buttons or declared
return count > 0 and count or 6
end
Stash.NUM_BANK_BAGS = CountBankBags()
Stash.LAST_BANK_BAG = Stash.FIRST_BANK_BAG + Stash.NUM_BANK_BAGS - 1
Stash.bankbags = { [Stash.BANK_CONTAINER] = true }
for bag = Stash.FIRST_BANK_BAG, Stash.LAST_BANK_BAG do
Stash.bankbags[bag] = true
end
-- --------------------------------------------------------------------------
-- saved variables
-- --------------------------------------------------------------------------
local DBVERSION = 1
function Stash:InitDB()
if not StashDB or StashDB.version ~= DBVERSION then
StashDB = { version = DBVERSION, realms = {} }
end
-- There is no player unit yet while addons are loading, so both of these can
-- come back nil at ADDON_LOADED. Indexing a table with nil is an error, so
-- leave the database alone and let the PLAYER_LOGIN pass finish the job.
local realm = GetRealmName()
local player = UnitName("player")
if not realm or realm == "" or not player or player == "" then
return nil
end
StashDB.realms[realm] = StashDB.realms[realm] or { chars = {}, guilds = {} }
local chars = StashDB.realms[realm].chars
if not chars[player] then
chars[player] = { containers = {} }
end
local _, class = UnitClass("player")
chars[player].class = class
return chars[player]
end
function Stash:GetRealm()
local realm = GetRealmName()
return StashDB and StashDB.realms and StashDB.realms[realm]
end
-- The cache entry for a character, defaulting to the one that is logged in.
function Stash:GetChar(name)
local realm = Stash:GetRealm()
if not realm then
return nil
end
return realm.chars[name or UnitName("player")]
end
function Stash:GetCharNames()
local names = {}
local realm = Stash:GetRealm()
if realm then
for name in pairs(realm.chars) do
names[getn(names) + 1] = name
end
sort(names)
end
return names
end
-- --------------------------------------------------------------------------
-- output
-- --------------------------------------------------------------------------
function Stash:Print(msg)
DEFAULT_CHAT_FRAME:AddMessage("|cffffcc00Stash|r: " .. msg)
end
function Stash:Error(msg)
DEFAULT_CHAT_FRAME:AddMessage("|cffffcc00Stash|r: |cffff5555" .. msg .. "|r")
end
-- --------------------------------------------------------------------------
-- helpers
-- --------------------------------------------------------------------------
-- true while the player is standing at a real bank
function Stash:AtBank()
return Stash.atbank and true or nil
end
-- The cached container record for a bank bag, or nil when nothing is stored.
function Stash:GetContainer(bag, name)
local char = Stash:GetChar(name or Stash.viewing)
if not char or not char.containers then
return nil
end
return char.containers[bag]
end
function Stash:CountItems(name)
local char = Stash:GetChar(name)
if not char or not char.containers then
return 0, 0
end
local items, slots = 0, 0
for _, container in pairs(char.containers) do
slots = slots + (container.size or 0)
for _ in pairs(container.items or {}) do
items = items + 1
end
end
return items, slots
end
-- Chains a frame's OnHide so leaving the window leaves the cached view too.
-- 1.12 has no HookScript, so the old handler is called by hand. Lives here
-- rather than in backends.lua because the fallback path needs it too.
function Stash:HookClose(frame)
if not frame or frame.stashhooked then
return
end
local orig = frame:GetScript("OnHide")
frame:SetScript("OnHide", function()
if orig then
orig()
end
Stash:EndOffline()
end)
frame.stashhooked = true
end
function Stash:CheckModules()
local missing = {}
for _, name in ipairs(Stash.required) do
if not Stash.modules[name] then
missing[getn(missing) + 1] = name .. ".lua"
end
end
if getn(missing) > 0 then
Stash:Error("these files did not load: " .. table.concat(missing, ", "))
Stash:Error("exit the game completely and start it again - /reload does not pick up newly added addon files.")
end
return getn(missing) == 0
end
-- --------------------------------------------------------------------------
-- slash commands
-- --------------------------------------------------------------------------
SLASH_STASH1 = "/stash"
SlashCmdList["STASH"] = function(msg)
msg = string.lower(msg or "")
local _, _, cmd, rest = string.find(msg, "^(%a*)%s*(.*)$")
if cmd == "" or cmd == "bank" then
Stash:ShowBank(rest ~= "" and rest or nil)
elseif cmd == "guild" then
Stash:ShowGuildBank()
elseif cmd == "list" then
local names = Stash:GetCharNames()
if getn(names) == 0 then
Stash:Print("nothing cached yet - visit a bank once.")
end
for _, name in ipairs(names) do
local items, slots = Stash:CountItems(name)
Stash:Print(name .. ": |cff33ff33" .. items .. "|r items in " .. slots .. " slots")
end
elseif cmd == "ui" then
Stash:SetBackendCommand(rest)
elseif cmd == "probe" then
Stash:ProbeGuildBank()
elseif cmd == "reset" then
StashDB = nil
Stash:InitDB()
Stash:Print("cache cleared.")
else
Stash:Print("commands:")
Stash:Print(" |cffffcc00/stash|r - show your cached bank")
Stash:Print(" |cffffcc00/stash bank <name>|r - show another character's cached bank")
Stash:Print(" |cffffcc00/stash guild|r - show the cached guild bank")
Stash:Print(" |cffffcc00/stash list|r - what is cached")
Stash:Print(" |cffffcc00/stash ui|r - choose which bank window to open")
Stash:Print(" |cffffcc00/stash probe|r - report this client's guild bank support")
Stash:Print(" |cffffcc00/stash reset|r - wipe the cache")
end
end
-- Picks which bag addon's bank window the cached view uses. With no argument
-- it reports what is available and which one is in use.
function Stash:SetBackendCommand(name)
local current = Stash:GetBackend()
if name == "" then
Stash:Print("bank window: |cff33ff33" .. (current and current.label or "none") .. "|r"
.. (StashDB.ui and " (pinned)" or " (auto)"))
for _, available in ipairs(Stash:ListBackends()) do
local backend = Stash.backends[available]
local state = backend.detect() and "|cff33ff33loaded|r" or "|cff888888not loaded|r"
Stash:Print(" |cffffcc00" .. available .. "|r - " .. backend.label .. ", " .. state)
end
Stash:Print("use |cffffcc00/stash ui <name>|r, or |cffffcc00/stash ui auto|r to pick automatically.")
return
end
if name == "auto" then
StashDB.ui = nil
local picked = Stash:GetBackend()
Stash:Print("bank window: automatic (" .. (picked and picked.label or "none") .. ").")
return
end
if not Stash.backends[name] then
Stash:Error("no bank window called '" .. name .. "'. Try |cffffcc00/stash ui|r.")
return
end
StashDB.ui = name
Stash:Print("bank window pinned to " .. Stash.backends[name].label .. ".")
if not Stash.backends[name].detect() then
Stash:Print("|cffff5555that addon is not loaded right now; falling back until it is.|r")
end
end
-- --------------------------------------------------------------------------
-- init
-- --------------------------------------------------------------------------
local init = CreateFrame("Frame")
init:RegisterEvent("ADDON_LOADED")
init:RegisterEvent("PLAYER_LOGIN")
init:SetScript("OnEvent", function()
if event == "ADDON_LOADED" and arg1 ~= "Stash" then
return
end
Stash:InitDB()
if event == "PLAYER_LOGIN" then
Stash:CaptureMoney()
Stash:CheckModules()
end
end)