mckenziemc@16
|
1 -- Core
|
mckenziemc@17
|
2 -- Provides core functionality of Core
|
mckenziemc@17
|
3
|
mckenziemc@17
|
4
|
mckenziemc@17
|
5 -- TODO: disable bootstrap if we load successfully?
|
mckenziemc@17
|
6 -- TODO: implement a feature to disable unneeded libraries when a parent
|
mckenziemc@17
|
7 -- is disabled?
|
mckenziemc@0
|
8
|
mckenziemc@0
|
9
|
mckenziemc@0
|
10 local addonName, addonTable = ...
|
mckenziemc@0
|
11
|
mckenziemc@0
|
12
|
mckenziemc@17
|
13 -- locals
|
mckenziemc@17
|
14 local print = addonTable.print
|
mckenziemc@17
|
15 local debug = addonTable.debug
|
mckenziemc@17
|
16 local classes = addonTable.classes
|
mckenziemc@17
|
17
|
mckenziemc@17
|
18 local AceHook = LibStub("AceHook-3.0")
|
mckenziemc@17
|
19 local LibScriptLink = LibStub("LibScriptLink-1.0")
|
mckenziemc@17
|
20
|
mckenziemc@17
|
21
|
mckenziemc@17
|
22 local Core = addonTable:NewClass("Core")
|
mckenziemc@17
|
23
|
mckenziemc@17
|
24
|
mckenziemc@17
|
25 AceHook:Embed(Core)
|
mckenziemc@17
|
26
|
mckenziemc@17
|
27 Core.queuedEnables = {} -- addons queued to be enabled after PLAYER_LOGIN
|
mckenziemc@17
|
28
|
mckenziemc@17
|
29
|
mckenziemc@17
|
30 -- Does not consider user settings or addon errata.
|
mckenziemc@17
|
31 function Core:IsForceLoadAvailable()
|
mckenziemc@17
|
32 if IsLoggedIn() then
|
mckenziemc@17
|
33 return false
|
mckenziemc@17
|
34 else
|
mckenziemc@17
|
35 return true
|
mckenziemc@17
|
36 end
|
mckenziemc@17
|
37 end
|
mckenziemc@17
|
38
|
mckenziemc@17
|
39
|
mckenziemc@17
|
40 function Core:IsForceLoadAllowed()
|
mckenziemc@17
|
41 -- TODO: check user settings
|
mckenziemc@17
|
42 return true
|
mckenziemc@17
|
43 end
|
mckenziemc@17
|
44
|
mckenziemc@17
|
45
|
mckenziemc@17
|
46 function Core:CanForceLoad()
|
mckenziemc@17
|
47 return self:IsForceLoadAvailable() and self:IsForceLoadAllowed()
|
mckenziemc@17
|
48 end
|
mckenziemc@17
|
49
|
mckenziemc@17
|
50
|
mckenziemc@18
|
51 function Core:CanLoadLate()
|
mckenziemc@18
|
52 -- assume we've already logged in
|
mckenziemc@18
|
53 return true
|
mckenziemc@18
|
54 -- TODO: check user settings
|
mckenziemc@18
|
55 end
|
mckenziemc@18
|
56
|
mckenziemc@18
|
57
|
mckenziemc@17
|
58 -- Enables any dependencies needed by the addons
|
mckenziemc@17
|
59 -- that have already been enabled
|
mckenziemc@17
|
60 function Core:PrepareAllAddons()
|
mckenziemc@17
|
61 for i=1, GetNumAddOns() do
|
mckenziemc@17
|
62 local addon = classes.Addon:Get(i)
|
mckenziemc@17
|
63
|
mckenziemc@17
|
64 -- TODO: what if an addon was loaded but its deps were then disabled?
|
mckenziemc@17
|
65 if addon:IsEnabled() and not addon:IsLoaded() then
|
mckenziemc@17
|
66 self:EnableAddOn(i)
|
mckenziemc@17
|
67 end
|
mckenziemc@17
|
68 end
|
mckenziemc@17
|
69 end
|
mckenziemc@17
|
70
|
mckenziemc@17
|
71
|
mckenziemc@17
|
72 function Core:SetHooks()
|
mckenziemc@17
|
73 self:RawHook("EnableAddOn", true)
|
mckenziemc@17
|
74 self:RawHook("LoadAddOn", true)
|
mckenziemc@17
|
75 end
|
mckenziemc@17
|
76
|
mckenziemc@17
|
77
|
mckenziemc@17
|
78 -- FIXME: use pcall in EnableAddOn and LoadAddOn, so that if my part errors,
|
mckenziemc@17
|
79 -- it can still use the unhooked version
|
mckenziemc@17
|
80
|
mckenziemc@17
|
81 function Core:EnableAddOn(...)
|
mckenziemc@17
|
82 local id = ...
|
mckenziemc@17
|
83
|
mckenziemc@17
|
84 debug("EnableAddOn", ...)
|
mckenziemc@17
|
85
|
mckenziemc@17
|
86 -- even though we know EnableAddOn can cause force-loading before PLAYER_LOGIN,
|
mckenziemc@17
|
87 -- DO NOT attempt to "fix" it: another addon that -does- know about
|
mckenziemc@17
|
88 -- the different behavior might call our hook.
|
mckenziemc@17
|
89
|
mckenziemc@17
|
90 if classes.Addon:Exists(id) then
|
mckenziemc@17
|
91 local addon = classes.Addon:Get(id)
|
mckenziemc@17
|
92 local tree = classes.Tree:Get(addon)
|
mckenziemc@17
|
93
|
mckenziemc@17
|
94 local requestReload = false
|
mckenziemc@17
|
95
|
mckenziemc@17
|
96 if self:CanForceLoad() then
|
mckenziemc@17
|
97 -- NOTE: if we can force-load, then will enabling LoD addons cause them to load too?
|
mckenziemc@17
|
98 -- A: no, they will still wait for LoadAddOn
|
mckenziemc@17
|
99
|
mckenziemc@17
|
100 -- Can the addon be loaded on demand if force-loading is
|
mckenziemc@17
|
101 -- allowed for its dependencies
|
mckenziemc@17
|
102 -- if so, enable all deps and force-load if nec.
|
mckenziemc@17
|
103 -- deps will get enabled if all parents are lod, force-loaded
|
mckenziemc@17
|
104 -- if any parent can't be loaded on demand
|
mckenziemc@17
|
105 -- else
|
mckenziemc@17
|
106 -- if the addon is not loadable on demand but the tree can be
|
mckenziemc@17
|
107 -- force-loaded, then force-load it all
|
mckenziemc@17
|
108 -- deps will all get loaded since req. for root to load
|
mckenziemc@17
|
109 -- else
|
mckenziemc@17
|
110 -- if it can be loaded with a reloadui then prepare after login
|
mckenziemc@17
|
111 -- else
|
mckenziemc@17
|
112 -- it can't be loaded, maybe tell the user
|
mckenziemc@17
|
113
|
mckenziemc@18
|
114 debug("EnableAddOn hook, checking", addon:GetName())
|
mckenziemc@18
|
115
|
mckenziemc@17
|
116 if tree:CanForceLoad() then
|
mckenziemc@17
|
117 if addon:CanLoD() then
|
mckenziemc@17
|
118 tree:PrepareForLoD()
|
mckenziemc@17
|
119 else
|
mckenziemc@17
|
120 tree:ForceLoad()
|
mckenziemc@17
|
121 end
|
mckenziemc@17
|
122 elseif tree:CanLoad() then
|
mckenziemc@17
|
123 tree:PrepareForLoad()
|
mckenziemc@17
|
124 requestReload = true
|
mckenziemc@17
|
125 else
|
mckenziemc@17
|
126 -- TODO: tell user
|
mckenziemc@17
|
127 end
|
mckenziemc@17
|
128
|
mckenziemc@17
|
129
|
mckenziemc@17
|
130 --[[
|
mckenziemc@17
|
131 if tree:CanLoDWithForce() then
|
mckenziemc@17
|
132 tree:PrepareForLoD()
|
mckenziemc@17
|
133 elseif tree:CanForceLoad() then
|
mckenziemc@17
|
134 tree:ForceLoad()
|
mckenziemc@17
|
135 elseif tree:CanLoad() then
|
mckenziemc@17
|
136 tree:PrepareForLoad()
|
mckenziemc@17
|
137 requestReload = true
|
mckenziemc@17
|
138 else
|
mckenziemc@17
|
139 -- TODO: tell user
|
mckenziemc@17
|
140 end
|
mckenziemc@17
|
141 ]]
|
mckenziemc@17
|
142 else
|
mckenziemc@17
|
143 -- if it can be loaded on demand (deps are loaded or LoD) then
|
mckenziemc@17
|
144 -- prepare it (enable all deps)
|
mckenziemc@17
|
145 -- else
|
mckenziemc@17
|
146 -- if it can be loaded (and isn't already) then
|
mckenziemc@17
|
147 -- if force loading is available, we have to wait, then enable everything
|
mckenziemc@17
|
148 -- else
|
mckenziemc@17
|
149 -- prepare for reload (TODO: move this check and similar to PLAYER_LOGOUT)
|
mckenziemc@17
|
150 -- else
|
mckenziemc@17
|
151 -- can't be loaded, maybe tell the user
|
mckenziemc@17
|
152
|
mckenziemc@17
|
153 if tree:CanLoD() then
|
mckenziemc@17
|
154 tree:PrepareForLoad()
|
mckenziemc@17
|
155 -- don't actually intend to reload, just enable everything
|
mckenziemc@18
|
156 elseif self:CanLoadLate() and tree:CanLoadLate() then
|
mckenziemc@18
|
157 tree:LoadLate()
|
mckenziemc@17
|
158 elseif tree:CanLoad() then
|
mckenziemc@17
|
159 tree:PrepareForLoad()
|
mckenziemc@17
|
160 requestReload = true
|
mckenziemc@17
|
161 else
|
mckenziemc@17
|
162 -- TODO: tell user
|
mckenziemc@17
|
163 end
|
mckenziemc@17
|
164 end
|
mckenziemc@17
|
165
|
mckenziemc@17
|
166 if requestReload then
|
mckenziemc@17
|
167 self:RequestReload()
|
mckenziemc@17
|
168 end
|
mckenziemc@17
|
169 end
|
mckenziemc@17
|
170
|
mckenziemc@17
|
171 -- propogate the call even if it doesn't exist or deps are unavailable
|
mckenziemc@17
|
172 return self:RawEnableAddOn(...)
|
mckenziemc@17
|
173 end
|
mckenziemc@17
|
174
|
mckenziemc@17
|
175
|
mckenziemc@17
|
176
|
mckenziemc@17
|
177 --- Prepares the addon tree rooted at the specified addon
|
mckenziemc@17
|
178 function Core:LoadAddOn(...)
|
mckenziemc@17
|
179 local id = ...
|
mckenziemc@17
|
180
|
mckenziemc@17
|
181 debug("LoadAddOn", ...)
|
mckenziemc@17
|
182
|
mckenziemc@17
|
183 if classes.Addon:Exists(id) then
|
mckenziemc@17
|
184 local addon = classes.Addon:Get(id)
|
mckenziemc@17
|
185 local tree = classes.Tree:Get(addon)
|
mckenziemc@17
|
186
|
mckenziemc@17
|
187 if tree:CanLoD() then
|
mckenziemc@17
|
188 tree:PrepareForLoD()
|
mckenziemc@17
|
189 elseif tree:CanLoad() then
|
mckenziemc@17
|
190 tree:PrepareForLoad()
|
mckenziemc@17
|
191 -- TODO: request reload
|
mckenziemc@17
|
192 end
|
mckenziemc@17
|
193 end
|
mckenziemc@17
|
194
|
mckenziemc@17
|
195 -- call even if it can't be loaded so regular returns appear
|
mckenziemc@17
|
196 return self:RawLoadAddOn(...)
|
mckenziemc@17
|
197 end
|
mckenziemc@17
|
198
|
mckenziemc@17
|
199
|
mckenziemc@17
|
200 function Core:RequestReload()
|
mckenziemc@17
|
201 -- TODO: this should be throtled so that it can
|
mckenziemc@17
|
202 -- occur more than once but not within a short time
|
mckenziemc@17
|
203
|
mckenziemc@17
|
204 debug("reload requested (NYI)")
|
mckenziemc@17
|
205 end
|
mckenziemc@17
|
206
|
mckenziemc@17
|
207
|
mckenziemc@17
|
208 -- name or index
|
mckenziemc@17
|
209 function Core:QueueEnable(addon)
|
mckenziemc@17
|
210 self.queuedEnables[addon] = true
|
mckenziemc@17
|
211 end
|
mckenziemc@17
|
212
|
mckenziemc@17
|
213
|
mckenziemc@17
|
214 function Core:RawEnableAddOn(...)
|
mckenziemc@18
|
215 debug("RawEnableAddOn: enabling", ...)
|
mckenziemc@17
|
216 return self.hooks.EnableAddOn(...)
|
mckenziemc@17
|
217 end
|
mckenziemc@17
|
218
|
mckenziemc@17
|
219
|
mckenziemc@17
|
220 function Core:RawLoadAddOn(...)
|
mckenziemc@17
|
221 return self.hooks.LoadAddOn(...)
|
mckenziemc@17
|
222 end
|
mckenziemc@17
|
223
|
mckenziemc@17
|
224
|
mckenziemc@17
|
225 function Core:ProcessEnableQueue()
|
mckenziemc@17
|
226 for addon in pairs(self.queuedEnables) do
|
mckenziemc@17
|
227 self:RawEnableAddOn(addon)
|
mckenziemc@17
|
228 self.queuedEnables[addon] = nil
|
mckenziemc@17
|
229 end
|
mckenziemc@17
|
230 end
|