AceHook-2.1
From WowAce Wiki
AceHook-2.1 is a Mixin to allow for safe hooking of functions, methods, and scripts.
Example
MyAddon = AceLibrary("AceAddon-2.0"):new("AceHook-2.1") -- hooking mixin
function MyAddon:OnInitialize()
self:Hook(DEFAULT_CHAT_FRAME, "AddMessage")
self:Hook(ChatFrame2, "AddMessage")
self:Hook(ChatFrame3, "AddMessage")
self:Hook(ChatFrame4, "AddMessage")
self:Hook(ChatFrame5, "AddMessage")
self:Hook(ChatFrame6, "AddMessage")
self:Hook(ChatFrame7, "AddMessage")
-- those all hook the AddMessage method of the chat frames.
-- They will be redirected to MyAddon:AddMessage(...)
end
function MyAddon:AddMessage(frame, text, r, g, b, id)
-- frame is the object that was hooked (one of the ChatFrames)
-- text, r, g, b, id are the other arguments provided to it.
local h,m = GetGameTime()
self.hooks[frame].AddMessage(frame, string.format("[%02d:%02d] %s", h, m, text), r, g, b, id)
-- self.hooks[object][method] holds the original method.
-- This should be called every time you deal with hooking, unless you use a secure hook.
-- be sure to provide all the arguments provided to you as well.
-- In this case, we pass back the method with modified arguments (adding a timestamp).
-- Note that if the original AddMessage would be required to return a value you need to do:
-- return self.hooks[frame].AddMessage(frame, string.format("[%02d:%02d] %s", h, m, text), r, g, b, id)
end
Differences from AceHook-2.0
- Hooking scripts now work properly for WoW 2.0
-
SecureHook()added -
:Hook()errors when trying to hook a secure function/method -
self.hooks.Func.orig()is changed toself.hooks.Func() - Much more memory and CPU efficient.
-
:HookReport()now actually works
API Documentation
:Hook("functionName" [, "handlerName" or handler] [, override]) or (object, "methodName" [, "handlerName" or handler] [, override])
Hook a function or method.
Args
- "functionName"
- string - global name of the function
- object
- table - object which contains the method to hook
- "methodName"
- string - name of the method to hook
- ["handlerName"]
- string - name of the method to handle the hook. If not given, "functionName" or "methodName" is assumed.
- [handler]
- function - function to handle the hook.
- [override]
- boolean - allow the insecure hook on a secure function.
Remarks
When hooking, you should almost always call the original hook. This is done with
self.hooks["functionName"](...)
or
self.hooks[object]["methodName"](object, ...)
Unless you set override to true, if you try to hook a secure function or method, an error will be raised. Use :SecureHook() instead.
</p>If you know that the function or method you are hooking will not cause tainting issues, then use
:Hook() instead of :SecureHook(), since that can be quite expensive.
Example
function self:UnitName(unit)
return self.hooks.UnitName(unit)
end
self:Hook("UnitName", true) -- hooking a secure function, thus the true
function self:SomeMethod(object)
return self.hooks[object].SomeMethod(object)
end
self:Hook(someObject, "SomeMethod")
:SecureHook("functionName" [, "handlerName" or handler]) or (object, "methodName" [, "handlerName" or handler])
Securely hook a function or method, preventing any possible code taint.
Args
- "functionName"
- string - global name of the function
- object
- table - object which contains the method to hook
- "methodName"
- string - name of the method to hook
- ["handlerName"]
- string - name of the method to handle the hook. If not given, "functionName" or "methodName" is assumed.
- [handler]
- function - function to handle the hook.
Remarks
In secure hooking, you do not call the original function, your hook will be called after the original function has executed and your return values will not affect it.
</p>If you know that the function or method you are hooking will not cause tainting issues, then use :Hook() instead of :SecureHook(), since that can be quite expensive.
Example
function self:CastSpellByName(spell, onSelf)
print("Cast:", spell)
end
self:SecureHook("CastSpellByName")
:Unhook("functionName") or (object, "methodName") or (object, "scriptName")
Safely unhooks from a method, function, or script.
Args
- "functionName"
- string - global name of the function
- object
- table - object which contains the hooked method/script
- "methodName"
- string - name of the hooked method
- "scriptName"
- string - name of the script method
Remarks
Unhooking from a function/method which you are not hooked into will cause an error.
Example
self:Unhook("UnitName")
self:Unhook(someObject, "SomeMethod")
:HookScript(object, "scriptName" [, "handlerName" or handler])
Hook a script
Args
- object
- table - object which contains the method to hook
- "scriptName"
- string - name of the method to hook
- ["handlerName"]
- string - name of the method to handle the hook. If not given, "scriptName" is assumed.
- [handler]
- function - function to handle the hook.
Remarks
When hooking, you should almost always call the original hook. This is done with
self.hooks[object]["scriptName"]()
To unhook, call :Unhook(object, "scriptName"). It intelligently knows the difference between a method and a script.
Example
function self:OnMouseDown(object, mouseButton)
return self.hooks[object].OnMouseDown(object, mouseButton)
end
self:HookScript(someFrame, "OnMouseDown")
:UnhookAll()
Safely unhooks from all methods, functions, and scripts.
Remarks
This is also called when your addon is put on standby by AceDB-2.0
Example
self:UnhookAll()
:HookReport()
Prints out a report of your current hooks.
Example
self:HookReport()
:IsHooked("functionName") or (object, "methodName")
Returns whether a function, method, or script is hooked
Args
- "functionName"
- string - global name of the function
- object
- table - object which contains the hooked method/script
- "methodName"
- string - name of the hooked method/script
Returns
isHooked, func
- isHooked
- boolean - whether a function, method, or script is hooked
- func
- string - name of the method
- function - function to be called
Example
if self:IsHooked("UnitName") then
-- do something
end

