mckenziemc@0
|
1 -- Addon
|
mckenziemc@10
|
2 -- Represents individual addon modules.
|
mckenziemc@0
|
3
|
mckenziemc@0
|
4
|
mckenziemc@0
|
5 local addonName, addonTable = ...
|
mckenziemc@0
|
6
|
mckenziemc@0
|
7
|
mckenziemc@18
|
8 local debug = addonTable.debug
|
mckenziemc@18
|
9
|
mckenziemc@10
|
10 -- TODO: test if the API functions are quicker with indexes than names.
|
mckenziemc@10
|
11 -- TODO: modify the dependency stuff to check the Errata module.
|
mckenziemc@0
|
12
|
mckenziemc@0
|
13 local Addon, addon = addonTable:NewClass("Addon")
|
mckenziemc@0
|
14
|
mckenziemc@8
|
15 Addon.addons = {}
|
mckenziemc@8
|
16 Addon.nameToIndex = {}
|
mckenziemc@8
|
17
|
mckenziemc@8
|
18
|
mckenziemc@15
|
19 --- (private) Creates a new Addon object
|
mckenziemc@8
|
20 -- @param id Name or index of the addon.
|
mckenziemc@0
|
21 function Addon:New(id)
|
mckenziemc@0
|
22 local instance = {}
|
mckenziemc@0
|
23 setmetatable(instance, self.instanceMetatable)
|
mckenziemc@0
|
24
|
mckenziemc@0
|
25 if type(id) == "number" then
|
mckenziemc@0
|
26 -- TODO: make sure it's in range
|
mckenziemc@0
|
27 instance.index = id
|
mckenziemc@0
|
28 instance.name = GetAddOnInfo(id)
|
mckenziemc@0
|
29 else
|
mckenziemc@0
|
30 -- FIXME: allow blizzard addons?
|
mckenziemc@0
|
31 local index
|
mckenziemc@0
|
32
|
mckenziemc@0
|
33 for i=1,GetNumAddOns() do
|
mckenziemc@0
|
34 if GetAddOnInfo(i) == id then
|
mckenziemc@0
|
35 index = i
|
mckenziemc@0
|
36 break
|
mckenziemc@0
|
37 end
|
mckenziemc@0
|
38 end
|
mckenziemc@0
|
39
|
mckenziemc@0
|
40 if index then
|
mckenziemc@0
|
41 instance.name = GetAddOnInfo(id)
|
mckenziemc@0
|
42 instance.index = index
|
mckenziemc@0
|
43 else
|
mckenziemc@12
|
44 local message = "Addon not found: "..(id or "nil")
|
mckenziemc@12
|
45 error(message)
|
mckenziemc@0
|
46 end
|
mckenziemc@0
|
47 end
|
mckenziemc@0
|
48
|
mckenziemc@0
|
49 return instance
|
mckenziemc@0
|
50 end
|
mckenziemc@0
|
51
|
mckenziemc@0
|
52
|
mckenziemc@8
|
53 --- Retrieves an Addon object.
|
mckenziemc@8
|
54 -- @param id Name or index of the addon to retrieve.
|
mckenziemc@8
|
55 -- @return The Addon object, or nil if not found.
|
mckenziemc@8
|
56 function Addon:Get(id)
|
mckenziemc@15
|
57 assert(id)
|
mckenziemc@15
|
58
|
mckenziemc@8
|
59 if not self:Exists(id) then
|
mckenziemc@8
|
60 return nil
|
mckenziemc@8
|
61 end
|
mckenziemc@8
|
62
|
mckenziemc@8
|
63 if type(id) == "number" then
|
mckenziemc@8
|
64 if self.addons[id] ~= nil then
|
mckenziemc@8
|
65 return self.addons[id]
|
mckenziemc@8
|
66 end
|
mckenziemc@8
|
67
|
mckenziemc@8
|
68 local new = self:New(id)
|
mckenziemc@8
|
69 self.addons[new:GetIndex()] = new
|
mckenziemc@8
|
70 self.nameToIndex[new:GetName()] = id
|
mckenziemc@8
|
71
|
mckenziemc@8
|
72 return new
|
mckenziemc@8
|
73 elseif type(id) == "string" then
|
mckenziemc@8
|
74 if self.nameToIndex[id] then
|
mckenziemc@8
|
75 return self.addons[self.nameToIndex[id] ]
|
mckenziemc@8
|
76 end
|
mckenziemc@8
|
77
|
mckenziemc@8
|
78 local new = self:New(id)
|
mckenziemc@8
|
79 self.addons[new:GetIndex()] = new
|
mckenziemc@8
|
80 self.nameToIndex[id] = new:GetIndex()
|
mckenziemc@8
|
81
|
mckenziemc@8
|
82 return new
|
mckenziemc@8
|
83 end
|
mckenziemc@8
|
84 end
|
mckenziemc@8
|
85
|
mckenziemc@10
|
86
|
mckenziemc@0
|
87 -- Checks if an addon exists with the specified name.
|
mckenziemc@0
|
88 -- @param addon Name of the addon.
|
mckenziemc@0
|
89 -- @return True if the addon is present, false otherwise.
|
mckenziemc@0
|
90 function Addon:Exists(addon)
|
mckenziemc@0
|
91 if type(addon) == "number" then
|
mckenziemc@0
|
92 if addon >= 1 and addon <= GetNumAddOns() then
|
mckenziemc@0
|
93 return true
|
mckenziemc@0
|
94 else
|
mckenziemc@0
|
95 return false
|
mckenziemc@0
|
96 end
|
mckenziemc@0
|
97 elseif type(addon) == "string" then
|
mckenziemc@15
|
98 if addon:match("Blizzard_") then
|
mckenziemc@15
|
99 return false
|
mckenziemc@15
|
100 end
|
mckenziemc@15
|
101
|
mckenziemc@0
|
102 local status = select(6, GetAddOnInfo(addon))
|
mckenziemc@0
|
103
|
mckenziemc@0
|
104 if status == "MISSING" then
|
mckenziemc@0
|
105 return false
|
mckenziemc@0
|
106 else
|
mckenziemc@0
|
107 return true
|
mckenziemc@0
|
108 end
|
mckenziemc@0
|
109 else
|
mckenziemc@15
|
110 local message = string.format("Unexpected argument type: \"%s\", value: %s", type(addon), addon or "nil")
|
mckenziemc@15
|
111 error(message)
|
mckenziemc@0
|
112 end
|
mckenziemc@0
|
113 end
|
mckenziemc@0
|
114
|
mckenziemc@0
|
115
|
mckenziemc@0
|
116 function addon:GetName()
|
mckenziemc@0
|
117 return self.name
|
mckenziemc@0
|
118 end
|
mckenziemc@0
|
119
|
mckenziemc@0
|
120
|
mckenziemc@0
|
121 function addon:GetIndex()
|
mckenziemc@0
|
122 return self.index
|
mckenziemc@0
|
123 end
|
mckenziemc@0
|
124
|
mckenziemc@0
|
125
|
mckenziemc@0
|
126 function addon:IsEnabled()
|
mckenziemc@0
|
127 -- FIXME: written while tired; review later
|
mckenziemc@0
|
128 local status = select(6, GetAddOnInfo(self.index))
|
mckenziemc@0
|
129
|
mckenziemc@0
|
130 if status == "DISABLED" then
|
mckenziemc@0
|
131 return false
|
mckenziemc@0
|
132 else
|
mckenziemc@0
|
133 return true
|
mckenziemc@0
|
134 end
|
mckenziemc@0
|
135 end
|
mckenziemc@0
|
136
|
mckenziemc@0
|
137
|
mckenziemc@15
|
138 function addon:IsLoaded()
|
mckenziemc@15
|
139 if IsAddOnLoaded(self.index) then
|
mckenziemc@15
|
140 return true
|
mckenziemc@15
|
141 else
|
mckenziemc@15
|
142 return false
|
mckenziemc@15
|
143 end
|
mckenziemc@15
|
144 end
|
mckenziemc@15
|
145
|
mckenziemc@15
|
146
|
mckenziemc@8
|
147 --- Checks if the addon is loadable.
|
mckenziemc@8
|
148 -- Considers interface issues, missing, etc. (NYI)
|
mckenziemc@8
|
149 -- Does not check dependencies.
|
mckenziemc@8
|
150 function addon:CanLoad()
|
mckenziemc@8
|
151 -- FIXME: an addon may be present but unloadable if loading out of date addons is disabled.
|
mckenziemc@8
|
152 return true
|
mckenziemc@8
|
153 end
|
mckenziemc@8
|
154
|
mckenziemc@8
|
155
|
mckenziemc@0
|
156 function addon:CanLoD()
|
mckenziemc@0
|
157 -- FIXME: what will the client say about addons using LoadManagers if the LM was force-loaded?
|
mckenziemc@0
|
158 if IsAddOnLoadOnDemand(self.name) then
|
mckenziemc@0
|
159 return true
|
mckenziemc@0
|
160 else
|
mckenziemc@0
|
161 return false
|
mckenziemc@0
|
162 end
|
mckenziemc@0
|
163 end
|
mckenziemc@0
|
164
|
mckenziemc@8
|
165
|
mckenziemc@18
|
166 function addon:CanLoadLate()
|
mckenziemc@18
|
167 -- TODO: check Errata module
|
mckenziemc@18
|
168 return false
|
mckenziemc@18
|
169 end
|
mckenziemc@18
|
170
|
mckenziemc@18
|
171
|
mckenziemc@15
|
172 -- can this addon be force-loaded after the point where the client would enable it?
|
mckenziemc@8
|
173 function addon:CanForceLoadAfter()
|
mckenziemc@8
|
174 -- TODO: check Errata module
|
mckenziemc@8
|
175 return false
|
mckenziemc@8
|
176 end
|
mckenziemc@8
|
177
|
mckenziemc@8
|
178
|
mckenziemc@15
|
179 -- can this addon be force-loaded before the point where the client would enable it?
|
mckenziemc@8
|
180 function addon:CanForceLoadBefore()
|
mckenziemc@8
|
181 -- TODO: check Errata module
|
mckenziemc@8
|
182 return false -- TODO: check if there's any reason addons can't be forceloaded
|
mckenziemc@8
|
183 end
|
mckenziemc@8
|
184
|
mckenziemc@8
|
185
|
mckenziemc@10
|
186 function addon:CanForceLoad()
|
mckenziemc@10
|
187 -- FIXME: check if this would've already been loaded
|
mckenziemc@15
|
188 return self:CanForceLoadAfter() or self:CanLoD()
|
mckenziemc@15
|
189 -- FIXME: should CanLoD() be in here?
|
mckenziemc@10
|
190 end
|
mckenziemc@10
|
191
|
mckenziemc@10
|
192
|
mckenziemc@8
|
193 function addon:Enable()
|
mckenziemc@15
|
194 if IsLoggedIn() then
|
mckenziemc@18
|
195 addonTable.classes.Core:RawEnableAddOn(self.name)
|
mckenziemc@18
|
196 else
|
mckenziemc@17
|
197 addonTable.classes.Core:QueueEnable(self.name)
|
mckenziemc@15
|
198 end
|
mckenziemc@8
|
199 end
|
mckenziemc@8
|
200
|
mckenziemc@8
|
201
|
mckenziemc@0
|
202 -- NOTE: only call for LoD, not force-loading
|
mckenziemc@0
|
203 function addon:Load()
|
mckenziemc@0
|
204 assert(self:CanLoD())
|
mckenziemc@0
|
205
|
mckenziemc@17
|
206 addonTable.classes.Core:RawEnableAddOn(self.name)
|
mckenziemc@17
|
207 addonTable.classes.Core:RawLoadAddOn(self.name)
|
mckenziemc@0
|
208 end
|
mckenziemc@0
|
209
|
mckenziemc@8
|
210
|
mckenziemc@18
|
211 function addon:LoadLate()
|
mckenziemc@18
|
212 classes.Core:RawEnableAddOn(self.name)
|
mckenziemc@18
|
213 classes.Core:RawLoadAddOn(self.name)
|
mckenziemc@18
|
214 end
|
mckenziemc@18
|
215
|
mckenziemc@18
|
216
|
mckenziemc@0
|
217 function addon:ForceLoad()
|
mckenziemc@18
|
218 debug("addon:ForceLoad called on", self.name)
|
mckenziemc@18
|
219
|
mckenziemc@0
|
220 assert(self:CanForceLoad())
|
mckenziemc@0
|
221 -- TODO: make sure force-loading is available at this time
|
mckenziemc@0
|
222
|
mckenziemc@17
|
223 addonTable.Core:RawEnableAddOn(self.name) -- This should cause the game to also load this addon
|
mckenziemc@0
|
224 end
|
mckenziemc@0
|
225
|
mckenziemc@0
|
226
|
mckenziemc@0
|
227 function addon:GetDependencies()
|
mckenziemc@8
|
228 -- TODO: consider no-lib embeds as deps?
|
mckenziemc@0
|
229 return GetAddOnDependencies(self.index)
|
mckenziemc@0
|
230 end
|
mckenziemc@0
|
231
|
mckenziemc@0
|
232
|
mckenziemc@0
|
233 function addon:GetEmbeds()
|
mckenziemc@0
|
234 local embeds = {}
|
mckenziemc@0
|
235
|
mckenziemc@0
|
236 local embedString = GetAddOnMetadata(self.name, "X-Embeds")
|
mckenziemc@0
|
237
|
mckenziemc@0
|
238 if embedString then
|
mckenziemc@0
|
239 for match in string.gmatch(embedString, "[^,%s]+") do
|
mckenziemc@0
|
240 table.insert(embeds, match)
|
mckenziemc@0
|
241 end
|
mckenziemc@0
|
242 end
|
mckenziemc@0
|
243
|
mckenziemc@0
|
244 return unpack(embeds)
|
mckenziemc@0
|
245 end
|