flickerstreak@1
|
1 --[[
|
flickerstreak@1
|
2 Name: AceHook-2.0
|
flickerstreak@1
|
3 Revision: $Rev: 18708 $
|
flickerstreak@1
|
4 Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team)
|
flickerstreak@1
|
5 Inspired By: Ace 1.x by Turan (turan@gryphon.com)
|
flickerstreak@1
|
6 Website: http://www.wowace.com/
|
flickerstreak@1
|
7 Documentation: http://www.wowace.com/index.php/AceHook-2.0
|
flickerstreak@1
|
8 SVN: http://svn.wowace.com/root/trunk/Ace2/AceHook-2.0
|
flickerstreak@1
|
9 Description: Mixin to allow for safe hooking of functions, methods, and scripts.
|
flickerstreak@1
|
10 Dependencies: AceLibrary, AceOO-2.0
|
flickerstreak@1
|
11 ]]
|
flickerstreak@1
|
12
|
flickerstreak@1
|
13 local MAJOR_VERSION = "AceHook-2.0"
|
flickerstreak@1
|
14 local MINOR_VERSION = "$Revision: 18708 $"
|
flickerstreak@1
|
15
|
flickerstreak@1
|
16 -- This ensures the code is only executed if the libary doesn't already exist, or is a newer version
|
flickerstreak@1
|
17 if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary.") end
|
flickerstreak@1
|
18 if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
|
flickerstreak@1
|
19
|
flickerstreak@1
|
20 local lua51 = loadstring("return function(...) return ... end") and true or false
|
flickerstreak@1
|
21
|
flickerstreak@1
|
22 if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0") end
|
flickerstreak@1
|
23
|
flickerstreak@1
|
24 --[[---------------------------------------------------------------------------------
|
flickerstreak@1
|
25 Create the library object
|
flickerstreak@1
|
26 ----------------------------------------------------------------------------------]]
|
flickerstreak@1
|
27
|
flickerstreak@1
|
28 local AceOO = AceLibrary:GetInstance("AceOO-2.0")
|
flickerstreak@1
|
29 local AceHook = AceOO.Mixin {
|
flickerstreak@1
|
30 "Hook",
|
flickerstreak@1
|
31 "Unhook",
|
flickerstreak@1
|
32 "UnhookAll",
|
flickerstreak@1
|
33 "HookReport",
|
flickerstreak@1
|
34 "IsHooked",
|
flickerstreak@1
|
35 "HookScript",
|
flickerstreak@1
|
36 }
|
flickerstreak@1
|
37
|
flickerstreak@1
|
38 local table_setn = lua51 and function() end or table.setn
|
flickerstreak@1
|
39
|
flickerstreak@1
|
40 if lua51 then
|
flickerstreak@1
|
41 AceHook.__deprecated = MAJOR_VERSION .. " is deprecated in WoW 2.0"
|
flickerstreak@1
|
42 end
|
flickerstreak@1
|
43
|
flickerstreak@1
|
44 --[[---------------------------------------------------------------------------------
|
flickerstreak@1
|
45 Library Definitions
|
flickerstreak@1
|
46 ----------------------------------------------------------------------------------]]
|
flickerstreak@1
|
47
|
flickerstreak@1
|
48 local protFuncs = {
|
flickerstreak@1
|
49 CameraOrSelectOrMoveStart = true, CameraOrSelectOrMoveStop = true,
|
flickerstreak@1
|
50 TurnOrActionStart = true, TurnOrActionStop = true,
|
flickerstreak@1
|
51 PitchUpStart = true, PitchUpStop = true,
|
flickerstreak@1
|
52 PitchDownStart = true, PitchDownStop = true,
|
flickerstreak@1
|
53 MoveBackwardStart = true, MoveBackwardStop = true,
|
flickerstreak@1
|
54 MoveForwardStart = true, MoveForwardStop = true,
|
flickerstreak@1
|
55 Jump = true, StrafeLeftStart = true,
|
flickerstreak@1
|
56 StrafeLeftStop = true, StrafeRightStart = true,
|
flickerstreak@1
|
57 StrafeRightStop = true, ToggleMouseMove = true,
|
flickerstreak@1
|
58 ToggleRun = true, TurnLeftStart = true,
|
flickerstreak@1
|
59 TurnLeftStop = true, TurnRightStart = true,
|
flickerstreak@1
|
60 TurnRightStop = true,
|
flickerstreak@1
|
61 }
|
flickerstreak@1
|
62
|
flickerstreak@1
|
63 local _G = getfenv(0)
|
flickerstreak@1
|
64
|
flickerstreak@1
|
65 local handlers, funcs, scripts, actives
|
flickerstreak@1
|
66
|
flickerstreak@1
|
67 --[[---------------------------------------------------------------------------------
|
flickerstreak@1
|
68 Private definitions (Not exposed)
|
flickerstreak@1
|
69 ----------------------------------------------------------------------------------]]
|
flickerstreak@1
|
70
|
flickerstreak@1
|
71 --[[----------------------------------------------------------------------
|
flickerstreak@1
|
72 _debug - Internal Method
|
flickerstreak@1
|
73 -------------------------------------------------------------------------]]
|
flickerstreak@1
|
74 local function print(text)
|
flickerstreak@1
|
75 DEFAULT_CHAT_FRAME:AddMessage(text)
|
flickerstreak@1
|
76 end
|
flickerstreak@1
|
77
|
flickerstreak@1
|
78 local function _debug(self, msg)
|
flickerstreak@1
|
79 local name = self.hooks.name
|
flickerstreak@1
|
80 if name then
|
flickerstreak@1
|
81 print(string.format("[%s]: %s", name, msg))
|
flickerstreak@1
|
82 else
|
flickerstreak@1
|
83 print(msg)
|
flickerstreak@1
|
84 end
|
flickerstreak@1
|
85 end
|
flickerstreak@1
|
86
|
flickerstreak@1
|
87 local new, del
|
flickerstreak@1
|
88 do
|
flickerstreak@1
|
89 local list = setmetatable({}, {__mode = "k"})
|
flickerstreak@1
|
90 function new()
|
flickerstreak@1
|
91 local t = next(list)
|
flickerstreak@1
|
92 if not t then
|
flickerstreak@1
|
93 return {}
|
flickerstreak@1
|
94 end
|
flickerstreak@1
|
95 list[t] = nil
|
flickerstreak@1
|
96 return t
|
flickerstreak@1
|
97 end
|
flickerstreak@1
|
98
|
flickerstreak@1
|
99 function del(t)
|
flickerstreak@1
|
100 setmetatable(t, nil)
|
flickerstreak@1
|
101 table_setn(t, 0)
|
flickerstreak@1
|
102 for k in pairs(t) do
|
flickerstreak@1
|
103 t[k] = nil
|
flickerstreak@1
|
104 end
|
flickerstreak@1
|
105 list[t] = true
|
flickerstreak@1
|
106 end
|
flickerstreak@1
|
107 end
|
flickerstreak@1
|
108
|
flickerstreak@1
|
109 local origMetatable = {
|
flickerstreak@1
|
110 __call = function(self, ...)
|
flickerstreak@1
|
111 return self.orig(...)
|
flickerstreak@1
|
112 end
|
flickerstreak@1
|
113 }
|
flickerstreak@1
|
114
|
flickerstreak@1
|
115 --[[----------------------------------------------------------------------
|
flickerstreak@1
|
116 AceHook:_getFunctionHook- internal method
|
flickerstreak@1
|
117 -------------------------------------------------------------------------]]
|
flickerstreak@1
|
118
|
flickerstreak@1
|
119 local function _getFunctionHook(self, func, handler, orig)
|
flickerstreak@1
|
120 if type(handler) == "string" then
|
flickerstreak@1
|
121 -- The handler is a method, need to self it
|
flickerstreak@1
|
122 return function(...)
|
flickerstreak@1
|
123 if actives[orig] then
|
flickerstreak@1
|
124 return self[handler](self, ...)
|
flickerstreak@1
|
125 else
|
flickerstreak@1
|
126 return orig(...)
|
flickerstreak@1
|
127 end
|
flickerstreak@1
|
128 end
|
flickerstreak@1
|
129 else
|
flickerstreak@1
|
130 -- The handler is a function, just call it
|
flickerstreak@1
|
131 return function(...)
|
flickerstreak@1
|
132 if actives[orig] then
|
flickerstreak@1
|
133 return handler(...)
|
flickerstreak@1
|
134 else
|
flickerstreak@1
|
135 return orig(...)
|
flickerstreak@1
|
136 end
|
flickerstreak@1
|
137 end
|
flickerstreak@1
|
138 end
|
flickerstreak@1
|
139 end
|
flickerstreak@1
|
140
|
flickerstreak@1
|
141 --[[----------------------------------------------------------------------
|
flickerstreak@1
|
142 AceHook:_getMethodHook - Internal Method
|
flickerstreak@1
|
143 -------------------------------------------------------------------------]]
|
flickerstreak@1
|
144 local function _getMethodHook(self, object, method, handler, orig, script)
|
flickerstreak@1
|
145 if type(handler) == "string" then
|
flickerstreak@1
|
146 -- The handler is a method, need to self it
|
flickerstreak@1
|
147 if script then
|
flickerstreak@1
|
148 return function()
|
flickerstreak@1
|
149 if actives[orig] then
|
flickerstreak@1
|
150 return self[handler](self, object)
|
flickerstreak@1
|
151 else
|
flickerstreak@1
|
152 return orig()
|
flickerstreak@1
|
153 end
|
flickerstreak@1
|
154 end
|
flickerstreak@1
|
155 else
|
flickerstreak@1
|
156 return function(obj,...)
|
flickerstreak@1
|
157 if actives[orig] then
|
flickerstreak@1
|
158 return self[handler](self, obj, ...)
|
flickerstreak@1
|
159 else
|
flickerstreak@1
|
160 return orig(obj, ...)
|
flickerstreak@1
|
161 end
|
flickerstreak@1
|
162 end
|
flickerstreak@1
|
163 end
|
flickerstreak@1
|
164 else
|
flickerstreak@1
|
165 -- The handler is a function, just call it
|
flickerstreak@1
|
166 if script then
|
flickerstreak@1
|
167 return function()
|
flickerstreak@1
|
168 if actives[orig] then
|
flickerstreak@1
|
169 return handler(object)
|
flickerstreak@1
|
170 else
|
flickerstreak@1
|
171 return orig()
|
flickerstreak@1
|
172 end
|
flickerstreak@1
|
173 end
|
flickerstreak@1
|
174 else
|
flickerstreak@1
|
175 return function(obj, ...)
|
flickerstreak@1
|
176 if actives[orig] then
|
flickerstreak@1
|
177 return handler(obj, ...)
|
flickerstreak@1
|
178 else
|
flickerstreak@1
|
179 return orig(obj, ...)
|
flickerstreak@1
|
180 end
|
flickerstreak@1
|
181 end
|
flickerstreak@1
|
182 end
|
flickerstreak@1
|
183 end
|
flickerstreak@1
|
184 end
|
flickerstreak@1
|
185
|
flickerstreak@1
|
186 --[[----------------------------------------------------------------------
|
flickerstreak@1
|
187 AceHook:HookFunc - internal method.
|
flickerstreak@1
|
188 o You can only hook each function once from each source.
|
flickerstreak@1
|
189 o If there is an inactive hook for this func/handler pair, we reactivate it
|
flickerstreak@1
|
190 o If there is an inactive hook for another handler, we error out.
|
flickerstreak@1
|
191 o Looks for handler as a method of the calling class, error if not available
|
flickerstreak@1
|
192 o If handler is a function, it just uses it directly through the wrapper
|
flickerstreak@1
|
193 -------------------------------------------------------------------------]]
|
flickerstreak@1
|
194 local function _hookFunc(self, func, handler)
|
flickerstreak@1
|
195 local orig = _G[func]
|
flickerstreak@1
|
196
|
flickerstreak@1
|
197 if not orig or type(orig) ~= "function" then
|
flickerstreak@1
|
198 _debug(self, string.format("Attempt to hook a non-existant function %q", func),3)
|
flickerstreak@1
|
199 return
|
flickerstreak@1
|
200 end
|
flickerstreak@1
|
201
|
flickerstreak@1
|
202 if not handler then handler = func end
|
flickerstreak@1
|
203
|
flickerstreak@1
|
204 if self.hooks[func] then
|
flickerstreak@1
|
205 local orig = self.hooks[func].orig
|
flickerstreak@1
|
206 -- We have an active hook from this source. Don't multi-hook
|
flickerstreak@1
|
207 if actives[orig] then
|
flickerstreak@1
|
208 _debug(self, string.format("%q already has an active hook from this source.", func))
|
flickerstreak@1
|
209 return
|
flickerstreak@1
|
210 end
|
flickerstreak@1
|
211 -- The hook is inactive, so reactivate it
|
flickerstreak@1
|
212 if handlers[orig] == handler then
|
flickerstreak@1
|
213 actives[orig] = true
|
flickerstreak@1
|
214 return
|
flickerstreak@1
|
215 else
|
flickerstreak@1
|
216 AceHook:error("There is a stale hook for %q can't hook or reactivate.", func)
|
flickerstreak@1
|
217 end
|
flickerstreak@1
|
218 end
|
flickerstreak@1
|
219
|
flickerstreak@1
|
220 if type(handler) == "string" then
|
flickerstreak@1
|
221 if type(self[handler]) ~= "function" then
|
flickerstreak@1
|
222 AceHook:error("Could not find the the handler %q when hooking function %q", handler, func)
|
flickerstreak@1
|
223 end
|
flickerstreak@1
|
224 elseif type(handler) ~= "function" then
|
flickerstreak@1
|
225 AceHook:error("Could not find the handler you supplied when hooking %q", func)
|
flickerstreak@1
|
226 end
|
flickerstreak@1
|
227
|
flickerstreak@1
|
228 local t = setmetatable(new(), origMetatable)
|
flickerstreak@1
|
229 self.hooks[func] = t
|
flickerstreak@1
|
230 t.orig = orig
|
flickerstreak@1
|
231
|
flickerstreak@1
|
232 actives[orig] = true
|
flickerstreak@1
|
233 handlers[orig] = handler
|
flickerstreak@1
|
234 local newFunc = _getFunctionHook(self, func, handler, orig)
|
flickerstreak@1
|
235 funcs[orig] = newFunc
|
flickerstreak@1
|
236
|
flickerstreak@1
|
237 _G[func] = newFunc
|
flickerstreak@1
|
238 end
|
flickerstreak@1
|
239
|
flickerstreak@1
|
240 --[[----------------------------------------------------------------------
|
flickerstreak@1
|
241 AceHook:UnhookFunc - internal method
|
flickerstreak@1
|
242 o If you attempt to unhook a function that has never been hooked, or to unhook in a
|
flickerstreak@1
|
243 system that has never had a hook before, the system will error with a stack trace
|
flickerstreak@1
|
244 o If we own the global function, then put the original back in its place and remove
|
flickerstreak@1
|
245 all references to the Hooks[func] structure.
|
flickerstreak@1
|
246 o If we don't own the global function (we've been hooked) we deactivate the hook,
|
flickerstreak@1
|
247 forcing the handler to passthrough.
|
flickerstreak@1
|
248 -------------------------------------------------------------------------]]
|
flickerstreak@1
|
249 local function _unhookFunc(self, func)
|
flickerstreak@1
|
250 if not self.hooks[func] or not funcs[self.hooks[func].orig] then
|
flickerstreak@1
|
251 _debug(self, string.format("Tried to unhook %q which is not currently hooked.", func))
|
flickerstreak@1
|
252 return
|
flickerstreak@1
|
253 end
|
flickerstreak@1
|
254
|
flickerstreak@1
|
255 local orig = self.hooks[func].orig
|
flickerstreak@1
|
256
|
flickerstreak@1
|
257 if actives[orig] then
|
flickerstreak@1
|
258 -- See if we own the global function
|
flickerstreak@1
|
259 if _G[func] == funcs[orig] then
|
flickerstreak@1
|
260 _G[func] = orig
|
flickerstreak@1
|
261 self.hooks[func] = del(self.hooks[func])
|
flickerstreak@1
|
262 handlers[orig] = nil
|
flickerstreak@1
|
263 funcs[orig] = nil
|
flickerstreak@1
|
264 scripts[orig] = nil
|
flickerstreak@1
|
265 actives[orig] = nil
|
flickerstreak@1
|
266 -- Magically all-done
|
flickerstreak@1
|
267 else
|
flickerstreak@1
|
268 actives[orig] = nil
|
flickerstreak@1
|
269 end
|
flickerstreak@1
|
270 end
|
flickerstreak@1
|
271 end
|
flickerstreak@1
|
272
|
flickerstreak@1
|
273 --[[----------------------------------------------------------------------
|
flickerstreak@1
|
274 AceHook:HookMeth - Takes an optional fourth argument
|
flickerstreak@1
|
275 o script - Signifies whether this is a script hook or not
|
flickerstreak@1
|
276 -------------------------------------------------------------------------]]
|
flickerstreak@1
|
277
|
flickerstreak@1
|
278 local function _hookMeth(self, obj, method, handler, script)
|
flickerstreak@1
|
279 if not handler then handler = method end
|
flickerstreak@1
|
280 if (not obj or type(obj) ~= "table") then
|
flickerstreak@1
|
281 AceHook:error("The object you supplied could not be found, or isn't a table.")
|
flickerstreak@1
|
282 end
|
flickerstreak@1
|
283
|
flickerstreak@1
|
284 if self.hooks[obj] and self.hooks[obj][method] then
|
flickerstreak@1
|
285 local orig = self.hooks[obj][method].orig
|
flickerstreak@1
|
286 -- We have an active hook from this source. Don't multi-hook
|
flickerstreak@1
|
287 if actives[orig] then
|
flickerstreak@1
|
288 _debug(self, string.format("%q already has an active hook from this source.", method))
|
flickerstreak@1
|
289 return
|
flickerstreak@1
|
290 end
|
flickerstreak@1
|
291 -- The hook is inactive, so reactivate it.
|
flickerstreak@1
|
292 if handlers[orig] == handler then
|
flickerstreak@1
|
293 actives[orig] = true
|
flickerstreak@1
|
294 return
|
flickerstreak@1
|
295 else
|
flickerstreak@1
|
296 AceHook:error("There is a stale hook for %q can't hook or reactivate.", method)
|
flickerstreak@1
|
297 end
|
flickerstreak@1
|
298 end
|
flickerstreak@1
|
299 -- We're clear to try the hook, let's make some checks first
|
flickerstreak@1
|
300 if type(handler) == "string" then
|
flickerstreak@1
|
301 if type(self[handler]) ~= "function" then
|
flickerstreak@1
|
302 AceHook:error("Could not find the handler %q you supplied when hooking method %q", handler, method)
|
flickerstreak@1
|
303 end
|
flickerstreak@1
|
304 elseif type(handler) ~= "function" then
|
flickerstreak@1
|
305 AceHook:error("Could not find the handler you supplied when hooking method %q", method)
|
flickerstreak@1
|
306 end
|
flickerstreak@1
|
307 -- Handler has been found, so now try to find the method we're trying to hook
|
flickerstreak@1
|
308 local orig
|
flickerstreak@1
|
309 -- Script
|
flickerstreak@1
|
310 if script then
|
flickerstreak@1
|
311 if not obj.GetScript then
|
flickerstreak@1
|
312 AceHook:error("The object you supplied does not have a GetScript method.")
|
flickerstreak@1
|
313 end
|
flickerstreak@1
|
314 if not obj:HasScript(method) then
|
flickerstreak@1
|
315 AceHook:error("The object you supplied doesn't allow the %q method.", method)
|
flickerstreak@1
|
316 end
|
flickerstreak@1
|
317 -- Sometimes there is not a original function for a script.
|
flickerstreak@1
|
318 orig = obj:GetScript(method)
|
flickerstreak@1
|
319 if not orig then
|
flickerstreak@1
|
320 orig = function() end
|
flickerstreak@1
|
321 end
|
flickerstreak@1
|
322 -- Method
|
flickerstreak@1
|
323 else
|
flickerstreak@1
|
324 orig = obj[method]
|
flickerstreak@1
|
325 end
|
flickerstreak@1
|
326 if not orig then
|
flickerstreak@1
|
327 AceHook:error("Could not find the method or script %q you are trying to hook.", method)
|
flickerstreak@1
|
328 end
|
flickerstreak@1
|
329 if not self.hooks[obj] then
|
flickerstreak@1
|
330 self.hooks[obj] = new()
|
flickerstreak@1
|
331 end
|
flickerstreak@1
|
332 local t = setmetatable(new(), origMetatable)
|
flickerstreak@1
|
333 self.hooks[obj][method] = t
|
flickerstreak@1
|
334 t.orig = orig
|
flickerstreak@1
|
335
|
flickerstreak@1
|
336 actives[orig] = true
|
flickerstreak@1
|
337 handlers[orig] = handler
|
flickerstreak@1
|
338 scripts[orig] = script and true or nil
|
flickerstreak@1
|
339 local newFunc = _getMethodHook(self, obj, method, handler, orig, script)
|
flickerstreak@1
|
340 funcs[orig] = newFunc
|
flickerstreak@1
|
341
|
flickerstreak@1
|
342 if script then
|
flickerstreak@1
|
343 obj:SetScript(method, newFunc)
|
flickerstreak@1
|
344 else
|
flickerstreak@1
|
345 obj[method] = newFunc
|
flickerstreak@1
|
346 end
|
flickerstreak@1
|
347 end
|
flickerstreak@1
|
348
|
flickerstreak@1
|
349 --[[----------------------------------------------------------------------
|
flickerstreak@1
|
350 AceHook:UnhookMeth - Internal method
|
flickerstreak@1
|
351 o If you attempt to unhook a method that has never been hooked, or to unhook in a
|
flickerstreak@1
|
352 system that has never had a hook before, the system will error with a stack trace
|
flickerstreak@1
|
353 o If we own the global method, then put the original back in its place and remove
|
flickerstreak@1
|
354 all references to the Hooks[obj][method] structure.
|
flickerstreak@1
|
355 o If we don't own the global method (we've been hooked) we deactivate the hook,
|
flickerstreak@1
|
356 forcing the handler to passthrough.
|
flickerstreak@1
|
357 -------------------------------------------------------------------------]]
|
flickerstreak@1
|
358 local function _unhookMeth(self, obj, method)
|
flickerstreak@1
|
359 if not self.hooks[obj] or not self.hooks[obj][method] or not funcs[self.hooks[obj][method].orig] then
|
flickerstreak@1
|
360 _debug(self, string.format("Attempt to unhook a method %q that is not currently hooked.", method))
|
flickerstreak@1
|
361 return
|
flickerstreak@1
|
362 end
|
flickerstreak@1
|
363
|
flickerstreak@1
|
364 local orig = self.hooks[obj][method].orig
|
flickerstreak@1
|
365
|
flickerstreak@1
|
366 if actives[orig] then
|
flickerstreak@1
|
367 -- If this is a script
|
flickerstreak@1
|
368 if scripts[orig] then
|
flickerstreak@1
|
369 if obj:GetScript(method) == funcs[orig] then
|
flickerstreak@1
|
370 -- We own the script. Kill it.
|
flickerstreak@1
|
371 obj:SetScript(method, orig)
|
flickerstreak@1
|
372 self.hooks[obj][method] = del(self.hooks[obj][method])
|
flickerstreak@1
|
373 handlers[orig] = nil
|
flickerstreak@1
|
374 funcs[orig] = nil
|
flickerstreak@1
|
375 scripts[orig] = nil
|
flickerstreak@1
|
376 actives[orig] = nil
|
flickerstreak@1
|
377 else
|
flickerstreak@1
|
378 actives[orig] = nil
|
flickerstreak@1
|
379 end
|
flickerstreak@1
|
380 else
|
flickerstreak@1
|
381 if obj[method] == funcs[orig] then
|
flickerstreak@1
|
382 -- We own the method. Kill it.
|
flickerstreak@1
|
383 obj[method] = orig
|
flickerstreak@1
|
384 self.hooks[obj][method] = del(self.hooks[obj][method])
|
flickerstreak@1
|
385 handlers[orig] = nil
|
flickerstreak@1
|
386 funcs[orig] = nil
|
flickerstreak@1
|
387 scripts[orig] = nil
|
flickerstreak@1
|
388 actives[orig] = nil
|
flickerstreak@1
|
389 else
|
flickerstreak@1
|
390 actives[orig] = nil
|
flickerstreak@1
|
391 end
|
flickerstreak@1
|
392 end
|
flickerstreak@1
|
393 end
|
flickerstreak@1
|
394 if not next(self.hooks[obj]) then
|
flickerstreak@1
|
395 -- Spank the table
|
flickerstreak@1
|
396 self.hooks[obj] = del(self.hooks[obj])
|
flickerstreak@1
|
397 end
|
flickerstreak@1
|
398 end
|
flickerstreak@1
|
399
|
flickerstreak@1
|
400 function AceHook:OnInstanceInit(object)
|
flickerstreak@1
|
401 if not object.hooks then
|
flickerstreak@1
|
402 object.hooks = new()
|
flickerstreak@1
|
403 end
|
flickerstreak@1
|
404
|
flickerstreak@1
|
405 local name
|
flickerstreak@1
|
406
|
flickerstreak@1
|
407 if type(rawget(object, 'GetLibraryVersion')) == "function" then
|
flickerstreak@1
|
408 name = object:GetLibraryVersion()
|
flickerstreak@1
|
409 end
|
flickerstreak@1
|
410 if not name and type(object.GetName) == "function" then
|
flickerstreak@1
|
411 name = object:GetName()
|
flickerstreak@1
|
412 end
|
flickerstreak@1
|
413 if not name and type(object.name) == "string" then
|
flickerstreak@1
|
414 name = object.name
|
flickerstreak@1
|
415 end
|
flickerstreak@1
|
416 if not name then
|
flickerstreak@1
|
417 for k,v in pairs(_G) do
|
flickerstreak@1
|
418 if v == object then
|
flickerstreak@1
|
419 name = tostring(k)
|
flickerstreak@1
|
420 break
|
flickerstreak@1
|
421 end
|
flickerstreak@1
|
422 end
|
flickerstreak@1
|
423 end
|
flickerstreak@1
|
424
|
flickerstreak@1
|
425 object.hooks.name = name
|
flickerstreak@1
|
426 end
|
flickerstreak@1
|
427
|
flickerstreak@1
|
428 AceHook.OnManualEmbed = AceHook.OnInstanceInit
|
flickerstreak@1
|
429
|
flickerstreak@1
|
430 --[[----------------------------------------------------------------------
|
flickerstreak@1
|
431 AceHook:Hook
|
flickerstreak@1
|
432 self:Hook("functionName", ["handlerName" | handler])
|
flickerstreak@1
|
433 self:Hook(ObjectName, "Method", ["Handler" | handler])
|
flickerstreak@1
|
434 -------------------------------------------------------------------------]]
|
flickerstreak@1
|
435 function AceHook:Hook(arg1, arg2, arg3)
|
flickerstreak@1
|
436 if type(arg1)== "string" then
|
flickerstreak@1
|
437 if protFuncs[arg1] then
|
flickerstreak@1
|
438 if self.hooks.name then
|
flickerstreak@1
|
439 AceHook:error("%s tried to hook %q, which is a Blizzard protected function.", self.hooks.name, arg1)
|
flickerstreak@1
|
440 else
|
flickerstreak@1
|
441 _debug(self, string.format("An Addon tried to hook %q, which is a Blizzard protected function.", arg1))
|
flickerstreak@1
|
442 end
|
flickerstreak@1
|
443 else
|
flickerstreak@1
|
444 _hookFunc(self, arg1, arg2)
|
flickerstreak@1
|
445 end
|
flickerstreak@1
|
446 else
|
flickerstreak@1
|
447 _hookMeth(self, arg1, arg2, arg3)
|
flickerstreak@1
|
448 end
|
flickerstreak@1
|
449 end
|
flickerstreak@1
|
450
|
flickerstreak@1
|
451 function AceHook:HookScript(arg1, arg2, arg3)
|
flickerstreak@1
|
452 _hookMeth(self, arg1, arg2, arg3, true)
|
flickerstreak@1
|
453 end
|
flickerstreak@1
|
454
|
flickerstreak@1
|
455 --[[----------------------------------------------------------------------
|
flickerstreak@1
|
456 AceHook:IsHooked()
|
flickerstreak@1
|
457 self:Hook("functionName")
|
flickerstreak@1
|
458 self:Hook(ObjectName, "Method")
|
flickerstreak@1
|
459
|
flickerstreak@1
|
460 Returns whether or not the given function is hooked in the current
|
flickerstreak@1
|
461 namespace. A hooked, but inactive function is considered NOT
|
flickerstreak@1
|
462 hooked in this context.
|
flickerstreak@1
|
463 -------------------------------------------------------------------------]]
|
flickerstreak@1
|
464 function AceHook:IsHooked(obj, method)
|
flickerstreak@1
|
465 if method and obj then
|
flickerstreak@1
|
466 if self.hooks and self.hooks[obj] and self.hooks[obj][method] and actives[self.hooks[obj][method].orig] then
|
flickerstreak@1
|
467 return true, handlers[self.hooks[obj][method].orig]
|
flickerstreak@1
|
468 end
|
flickerstreak@1
|
469 else
|
flickerstreak@1
|
470 if self.hooks and self.hooks[obj] and actives[self.hooks[obj].orig] then
|
flickerstreak@1
|
471 return true, handlers[self.hooks[obj].orig]
|
flickerstreak@1
|
472 end
|
flickerstreak@1
|
473 end
|
flickerstreak@1
|
474
|
flickerstreak@1
|
475 return false, nil
|
flickerstreak@1
|
476 end
|
flickerstreak@1
|
477
|
flickerstreak@1
|
478 --[[----------------------------------------------------------------------
|
flickerstreak@1
|
479 AceHook:Unhook
|
flickerstreak@1
|
480 self:Unhook("functionName")
|
flickerstreak@1
|
481 self:Unhook(ObjectName, "Method")
|
flickerstreak@1
|
482 -------------------------------------------------------------------------]]
|
flickerstreak@1
|
483 function AceHook:Unhook(arg1, arg2)
|
flickerstreak@1
|
484 if type(arg1) == "string" then
|
flickerstreak@1
|
485 _unhookFunc(self, arg1)
|
flickerstreak@1
|
486 else
|
flickerstreak@1
|
487 _unhookMeth(self, arg1, arg2)
|
flickerstreak@1
|
488 end
|
flickerstreak@1
|
489 end
|
flickerstreak@1
|
490
|
flickerstreak@1
|
491 --[[----------------------------------------------------------------------
|
flickerstreak@1
|
492 AceHook:UnhookAll - Unhooks all active hooks from the calling source
|
flickerstreak@1
|
493 -------------------------------------------------------------------------]]
|
flickerstreak@1
|
494 function AceHook:UnhookAll()
|
flickerstreak@1
|
495 for key, value in pairs(self.hooks) do
|
flickerstreak@1
|
496 if type(key) == "table" then
|
flickerstreak@1
|
497 for method in pairs(value) do
|
flickerstreak@1
|
498 self:Unhook(key, method)
|
flickerstreak@1
|
499 end
|
flickerstreak@1
|
500 else
|
flickerstreak@1
|
501 self:Unhook(key)
|
flickerstreak@1
|
502 end
|
flickerstreak@1
|
503 end
|
flickerstreak@1
|
504 end
|
flickerstreak@1
|
505
|
flickerstreak@1
|
506
|
flickerstreak@1
|
507 function AceHook:OnEmbedDisable(target)
|
flickerstreak@1
|
508 self.UnhookAll(target)
|
flickerstreak@1
|
509 end
|
flickerstreak@1
|
510
|
flickerstreak@1
|
511 --[[----------------------------------------------------------------------
|
flickerstreak@1
|
512 AceHook:HookReport - Lists registered hooks from this source
|
flickerstreak@1
|
513 -------------------------------------------------------------------------]]
|
flickerstreak@1
|
514
|
flickerstreak@1
|
515 function AceHook:HookReport()
|
flickerstreak@1
|
516 _debug(self, "This is a list of all active hooks for this object:")
|
flickerstreak@1
|
517 if not self.hooks then _debug(self, "No registered hooks.") return end
|
flickerstreak@1
|
518
|
flickerstreak@1
|
519 for key, value in pairs(self.hooks) do
|
flickerstreak@1
|
520 if type(value) == "table" then
|
flickerstreak@1
|
521 for method in pairs(value) do
|
flickerstreak@1
|
522 _debug(self, string.format("key: %s method: %q |cff%s|r", tostring(key), method, self.hooks[key][method].active and "00ff00Active" or "ffff00Inactive"))
|
flickerstreak@1
|
523 end
|
flickerstreak@1
|
524 else
|
flickerstreak@1
|
525 _debug(self, string.format("key: %s value: %q |cff%s|r", tostring(key), tostring(value), self.hooks[key].active and "00ff00Active" or "ffff00Inactive"))
|
flickerstreak@1
|
526 end
|
flickerstreak@1
|
527 end
|
flickerstreak@1
|
528 end
|
flickerstreak@1
|
529
|
flickerstreak@1
|
530 --[[---------------------------------------------------------------------------------
|
flickerstreak@1
|
531 Stub and Library registration
|
flickerstreak@1
|
532 ----------------------------------------------------------------------------------]]
|
flickerstreak@1
|
533
|
flickerstreak@1
|
534 local function activate(self, oldLib, oldDeactivate)
|
flickerstreak@1
|
535 AceHook = self
|
flickerstreak@1
|
536
|
flickerstreak@1
|
537 self.handlers = oldLib and oldLib.handlers or {}
|
flickerstreak@1
|
538 self.funcs = oldLib and oldLib.funcs or {}
|
flickerstreak@1
|
539 self.scripts = oldLib and oldLib.scripts or {}
|
flickerstreak@1
|
540 self.actives = oldLib and oldLib.actives or {}
|
flickerstreak@1
|
541
|
flickerstreak@1
|
542 handlers = self.handlers
|
flickerstreak@1
|
543 funcs = self.funcs
|
flickerstreak@1
|
544 scripts = self.scripts
|
flickerstreak@1
|
545 actives = self.actives
|
flickerstreak@1
|
546
|
flickerstreak@1
|
547 self:activate(oldLib, oldDeactivate)
|
flickerstreak@1
|
548
|
flickerstreak@1
|
549 if oldDeactivate then
|
flickerstreak@1
|
550 oldDeactivate(oldLib)
|
flickerstreak@1
|
551 end
|
flickerstreak@1
|
552 end
|
flickerstreak@1
|
553
|
flickerstreak@1
|
554 AceLibrary:Register(AceHook, MAJOR_VERSION, MINOR_VERSION, activate)
|