diff --git a/Libs/AceHook-2.0/AceHook-2.0.lua b/Libs/AceHook-2.0/AceHook-2.0.lua deleted file mode 100644 index 0897142..0000000 --- a/Libs/AceHook-2.0/AceHook-2.0.lua +++ /dev/null @@ -1,561 +0,0 @@ ---[[ -Name: AceHook-2.0 -Revision: $Rev: 10447 $ -Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team) -Inspired By: Ace 1.x by Turan (turan@gryphon.com) -Website: http://www.wowace.com/ -Documentation: http://www.wowace.com/index.php/AceHook-2.0 -SVN: http://svn.wowace.com/root/trunk/Ace2/AceHook-2.0 -Description: Mixin to allow for safe hooking of functions, methods, and scripts. -Dependencies: AceLibrary, AceOO-2.0 -]] - -local MAJOR_VERSION = "AceHook-2.0" -local MINOR_VERSION = "$Revision: 10447 $" - --- This ensures the code is only executed if the libary doesn't already exist, or is a newer version -if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary.") end -if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end - -if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0") end - ---[[--------------------------------------------------------------------------------- - Create the library object -----------------------------------------------------------------------------------]] - -local AceOO = AceLibrary:GetInstance("AceOO-2.0") -local AceHook = AceOO.Mixin { - "Hook", - "Unhook", - "UnhookAll", - "HookReport", - "IsHooked", - "HookScript", - } - ---[[--------------------------------------------------------------------------------- - Library Definitions -----------------------------------------------------------------------------------]] - -local protFuncs = { - CameraOrSelectOrMoveStart = true, CameraOrSelectOrMoveStop = true, - TurnOrActionStart = true, TurnOrActionStop = true, - PitchUpStart = true, PitchUpStop = true, - PitchDownStart = true, PitchDownStop = true, - MoveBackwardStart = true, MoveBackwardStop = true, - MoveForwardStart = true, MoveForwardStop = true, - Jump = true, StrafeLeftStart = true, - StrafeLeftStop = true, StrafeRightStart = true, - StrafeRightStop = true, ToggleMouseMove = true, - ToggleRun = true, TurnLeftStart = true, - TurnLeftStop = true, TurnRightStart = true, - TurnRightStop = true, -} - -local _G = getfenv(0) - -local handlers, funcs, scripts, actives - ---[[--------------------------------------------------------------------------------- - Private definitions (Not exposed) -----------------------------------------------------------------------------------]] - ---[[---------------------------------------------------------------------- - _debug - Internal Method --------------------------------------------------------------------------]] -local function print(text) - DEFAULT_CHAT_FRAME:AddMessage(text) -end - -local function _debug(self, msg) - local name = self.hooks.name - if name then - print(string.format("[%s]: %s", name, msg)) - else - print(msg) - end -end - -local new, del -do - local list = setmetatable({}, {__mode = "k"}) - function new() - local t = next(list) - if not t then - return {} - end - list[t] = nil - return t - end - - function del(t) - setmetatable(t, nil) - table.setn(t, 0) - for k in pairs(t) do - t[k] = nil - end - list[t] = true - end -end - -local origMetatable = { - __call = function(self, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) - return self.orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) - end -} - ---[[---------------------------------------------------------------------- - AceHook:_getFunctionHook- internal method --------------------------------------------------------------------------]] - -local function _getFunctionHook(self, func, handler, orig) - if type(handler) == "string" then - -- The handler is a method, need to self it - return function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) - if actives[orig] then - return self[handler](self, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) - else - return orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) - end - end - else - -- The handler is a function, just call it - return function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) - if actives[orig] then - return handler(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) - else - return orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) - end - end - end -end - ---[[---------------------------------------------------------------------- - AceHook:_getMethodHook - Internal Method --------------------------------------------------------------------------]] -local function _getMethodHook(self, object, method, handler, orig, script) - if type(handler) == "string" then - -- The handler is a method, need to self it - if script then - return function() - if actives[orig] then - return self[handler](self, object) - else - return orig() - end - end - else - return function(obj,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) - if actives[orig] then - return self[handler](self, obj, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) - else - return orig(obj, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) - end - end - end - else - -- The handler is a function, just call it - if script then - return function() - if actives[orig] then - return handler(object) - else - return orig() - end - end - else - return function(obj,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) - if actives[orig] then - return handler(obj,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) - else - return orig(obj, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) - end - end - end - end -end - ---[[---------------------------------------------------------------------- - AceHook:HookFunc - internal method. - o You can only hook each function once from each source. - o If there is an inactive hook for this func/handler pair, we reactivate it - o If there is an inactive hook for another handler, we error out. - o Looks for handler as a method of the calling class, error if not available - o If handler is a function, it just uses it directly through the wrapper --------------------------------------------------------------------------]] -local function _hookFunc(self, func, handler) - local orig = _G[func] - - if not orig or type(orig) ~= "function" then - _debug(self, string.format("Attempt to hook a non-existant function %q", func),3) - return - end - - if not handler then handler = func end - - if self.hooks[func] then - local orig = self.hooks[func].orig - -- We have an active hook from this source. Don't multi-hook - if actives[orig] then - _debug(self, string.format("%q already has an active hook from this source.", func)) - return - end - -- The hook is inactive, so reactivate it - if handlers[orig] == handler then - actives[orig] = true - return - else - AceHook:error("There is a stale hook for %q can't hook or reactivate.", func) - end - end - - if type(handler) == "string" then - if type(self[handler]) ~= "function" then - AceHook:error("Could not find the the handler %q when hooking function %q", handler, func) - end - elseif type(handler) ~= "function" then - AceHook:error("Could not find the handler you supplied when hooking %q", func) - end - - local t = setmetatable(new(), origMetatable) - self.hooks[func] = t - t.orig = orig - - actives[orig] = true - handlers[orig] = handler - local newFunc = _getFunctionHook(self, func, handler, orig) - funcs[orig] = newFunc - - _G[func] = newFunc -end - ---[[---------------------------------------------------------------------- - AceHook:UnhookFunc - internal method - o If you attempt to unhook a function that has never been hooked, or to unhook in a - system that has never had a hook before, the system will error with a stack trace - o If we own the global function, then put the original back in its place and remove - all references to the Hooks[func] structure. - o If we don't own the global function (we've been hooked) we deactivate the hook, - forcing the handler to passthrough. --------------------------------------------------------------------------]] -local function _unhookFunc(self, func) - if not self.hooks[func] or not funcs[self.hooks[func].orig] then - _debug(self, string.format("Tried to unhook %q which is not currently hooked.", func)) - return - end - - local orig = self.hooks[func].orig - - if actives[orig] then - -- See if we own the global function - if _G[func] == funcs[orig] then - _G[func] = orig - self.hooks[func] = del(self.hooks[func]) - handlers[orig] = nil - funcs[orig] = nil - scripts[orig] = nil - actives[orig] = nil - -- Magically all-done - else - actives[orig] = nil - end - end -end - ---[[---------------------------------------------------------------------- - AceHook:HookMeth - Takes an optional fourth argument - o script - Signifies whether this is a script hook or not --------------------------------------------------------------------------]] - -local function _hookMeth(self, obj, method, handler, script) - if not handler then handler = method end - if (not obj or type(obj) ~= "table") then - AceHook:error("The object you supplied could not be found, or isn't a table.") - end - - if self.hooks[obj] and self.hooks[obj][method] then - local orig = self.hooks[obj][method].orig - -- We have an active hook from this source. Don't multi-hook - if actives[orig] then - _debug(self, string.format("%q already has an active hook from this source.", method)) - return - end - -- The hook is inactive, so reactivate it. - if handlers[orig] == handler then - actives[orig] = true - return - else - AceHook:error("There is a stale hook for %q can't hook or reactivate.", method) - end - end - -- We're clear to try the hook, let's make some checks first - if type(handler) == "string" then - if type(self[handler]) ~= "function" then - AceHook:error("Could not find the handler %q you supplied when hooking method %q", handler, method) - end - elseif type(handler) ~= "function" then - AceHook:error("Could not find the handler you supplied when hooking method %q", method) - end - -- Handler has been found, so now try to find the method we're trying to hook - local orig - -- Script - if script then - if not obj.GetScript then - AceHook:error("The object you supplied does not have a GetScript method.") - end - if not obj:HasScript(method) then - AceHook:error("The object you supplied doesn't allow the %q method.", method) - end - -- Sometimes there is not a original function for a script. - orig = obj:GetScript(method) - if not orig then - orig = function() end - end - -- Method - else - orig = obj[method] - end - if not orig then - AceHook:error("Could not find the method or script %q you are trying to hook.", method) - end - if not self.hooks[obj] then - self.hooks[obj] = new() - end - local t = setmetatable(new(), origMetatable) - self.hooks[obj][method] = t - t.orig = orig - - actives[orig] = true - handlers[orig] = handler - scripts[orig] = script and true or nil - local newFunc = _getMethodHook(self, obj, method, handler, orig, script) - funcs[orig] = newFunc - - if script then - obj:SetScript(method, newFunc) - else - obj[method] = newFunc - end -end - ---[[---------------------------------------------------------------------- - AceHook:UnhookMeth - Internal method - o If you attempt to unhook a method that has never been hooked, or to unhook in a - system that has never had a hook before, the system will error with a stack trace - o If we own the global method, then put the original back in its place and remove - all references to the Hooks[obj][method] structure. - o If we don't own the global method (we've been hooked) we deactivate the hook, - forcing the handler to passthrough. --------------------------------------------------------------------------]] -local function _unhookMeth(self, obj, method) - if not self.hooks[obj] or not self.hooks[obj][method] or not funcs[self.hooks[obj][method].orig] then - _debug(self, string.format("Attempt to unhook a method %q that is not currently hooked.", method)) - return - end - - local orig = self.hooks[obj][method].orig - - if actives[orig] then - -- If this is a script - if scripts[orig] then - if obj:GetScript(method) == funcs[orig] then - -- We own the script. Kill it. - obj:SetScript(method, orig) - self.hooks[obj][method] = del(self.hooks[obj][method]) - handlers[orig] = nil - funcs[orig] = nil - scripts[orig] = nil - actives[orig] = nil - else - actives[orig] = nil - end - else - if obj[method] == funcs[orig] then - -- We own the method. Kill it. - obj[method] = orig - self.hooks[obj][method] = del(self.hooks[obj][method]) - handlers[orig] = nil - funcs[orig] = nil - scripts[orig] = nil - actives[orig] = nil - else - actives[orig] = nil - end - end - end - if not next(self.hooks[obj]) then - -- Spank the table - self.hooks[obj] = del(self.hooks[obj]) - end -end - -function AceHook:OnInstanceInit(object) - if not object.hooks then - object.hooks = new() - end - - local name - - if type(rawget(object, 'GetLibraryVersion')) == "function" then - name = object:GetLibraryVersion() - end - if not name and type(object.GetName) == "function" then - name = object:GetName() - end - if not name and type(object.name) == "string" then - name = object.name - end - if not name then - for k,v in pairs(_G) do - if v == object then - name = tostring(k) - break - end - end - end - - object.hooks.name = name -end - -AceHook.OnManualEmbed = AceHook.OnInstanceInit - ---[[---------------------------------------------------------------------- - AceHook:Hook - self:Hook("functionName", ["handlerName" | handler]) - self:Hook(ObjectName, "Method", ["Handler" | handler]) --------------------------------------------------------------------------]] -function AceHook:Hook(arg1, arg2, arg3) - if type(arg1)== "string" then - if protFuncs[arg1] then - if self.hooks.name then - AceHook:error("%s tried to hook %q, which is a Blizzard protected function.", self.hooks.name, arg1) - else - _debug(self, string.format("An Addon tried to hook %q, which is a Blizzard protected function.", arg1)) - end - else - _hookFunc(self, arg1, arg2) - end - else - _hookMeth(self, arg1, arg2, arg3) - end -end - -function AceHook:HookScript(arg1, arg2, arg3) - _hookMeth(self, arg1, arg2, arg3, true) -end - ---[[---------------------------------------------------------------------- - AceHook:IsHooked() - self:Hook("functionName") - self:Hook(ObjectName, "Method") - - Returns whether or not the given function is hooked in the current - namespace. A hooked, but inactive function is considered NOT - hooked in this context. --------------------------------------------------------------------------]] -function AceHook:IsHooked(obj, method) - if method and obj then - if self.hooks and self.hooks[obj] and self.hooks[obj][method] and actives[self.hooks[obj][method].orig] then - return true, handlers[self.hooks[obj][method].orig] - end - else - if self.hooks and self.hooks[obj] and actives[self.hooks[obj].orig] then - return true, handlers[self.hooks[obj].orig] - end - end - - return false, nil -end - ---[[---------------------------------------------------------------------- - AceHook:Unhook - self:Unhook("functionName") - self:Unhook(ObjectName, "Method") --------------------------------------------------------------------------]] -function AceHook:Unhook(arg1, arg2) - if type(arg1) == "string" then - _unhookFunc(self, arg1) - else - _unhookMeth(self, arg1, arg2) - end -end - ---[[---------------------------------------------------------------------- - AceHook:UnhookAll - Unhooks all active hooks from the calling source --------------------------------------------------------------------------]] -function AceHook:UnhookAll() - for key, value in pairs(self.hooks) do - if type(key) == "table" then - for method in pairs(value) do - self:Unhook(key, method) - end - else - self:Unhook(key) - end - end -end - - -function AceHook:OnEmbedDisable(target) - self.UnhookAll(target) -end - ---[[---------------------------------------------------------------------- - AceHook:HookReport - Lists registered hooks from this source --------------------------------------------------------------------------]] - -function AceHook:HookReport() - _debug(self, "This is a list of all active hooks for this object:") - if not self.hooks then _debug(self, "No registered hooks.") return end - - for key, value in pairs(self.hooks) do - if type(value) == "table" then - for method in pairs(value) do - _debug(self, string.format("key: %s method: %q |cff%s|r", tostring(key), method, self.hooks[key][method].active and "00ff00Active" or "ffff00Inactive")) - end - else - _debug(self, string.format("key: %s value: %q |cff%s|r", tostring(key), tostring(value), self.hooks[key].active and "00ff00Active" or "ffff00Inactive")) - end - end -end - ---[[--------------------------------------------------------------------------------- - Stub and Library registration -----------------------------------------------------------------------------------]] - -local function activate(self, oldLib, oldDeactivate) - AceHook = self - - AceHook.super.activate(self, oldLib, oldDeactivate) - - if oldLib then - self.handlers = oldLib.handlers - self.funcs = oldLib.funcs - self.scripts = oldLib.scripts - self.actives = oldLib.actives - end - - if not self.handlers then - self.handlers = {} - end - if not self.funcs then - self.funcs = {} - end - if not self.scripts then - self.scripts = {} - end - if not self.actives then - self.actives = {} - end - - handlers = self.handlers - funcs = self.funcs - scripts = self.scripts - actives = self.actives - - if oldDeactivate then - oldDeactivate(oldLib) - end -end - -AceLibrary:Register(AceHook, MAJOR_VERSION, MINOR_VERSION, activate) diff --git a/Libs/AceHook-2.1/AceHook-2.1.lua b/Libs/AceHook-2.1/AceHook-2.1.lua new file mode 100644 index 0000000..8beaf66 --- /dev/null +++ b/Libs/AceHook-2.1/AceHook-2.1.lua @@ -0,0 +1,569 @@ +--[[ +Name: AceHook-2.1 +Revision: $Rev: 17638 $ +Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team) +Inspired By: Ace 1.x by Turan (turan@gryphon.com) +Website: http://www.wowace.com/ +Documentation: http://www.wowace.com/index.php/AceHook-2.1 +SVN: http://svn.wowace.com/root/trunk/Ace2/AceHook-2.1 +Description: Mixin to allow for safe hooking of functions, methods, and scripts. +Dependencies: AceLibrary, AceOO-2.0 +]] + +local MAJOR_VERSION = "AceHook-2.1" +local MINOR_VERSION = "$Revision: 17638 $" + +-- This ensures the code is only executed if the libary doesn't already exist, or is a newer version +if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary.") end +if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end + +if loadstring("return function(...) return ... end") and AceLibrary:HasInstance(MAJOR_VERSION) then return end -- lua51 check +if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0") end + +--[[--------------------------------------------------------------------------------- + Create the library object +----------------------------------------------------------------------------------]] + +local AceOO = AceLibrary:GetInstance("AceOO-2.0") +local AceHook = AceOO.Mixin { + "Hook", + "HookScript", + "SecureHook", + "Unhook", + "UnhookAll", + "HookReport", + "IsHooked", + } + +--[[--------------------------------------------------------------------------------- + Library Definitions +----------------------------------------------------------------------------------]] + +local protFuncs = { + CameraOrSelectOrMoveStart = true, CameraOrSelectOrMoveStop = true, + TurnOrActionStart = true, TurnOrActionStop = true, + PitchUpStart = true, PitchUpStop = true, + PitchDownStart = true, PitchDownStop = true, + MoveBackwardStart = true, MoveBackwardStop = true, + MoveForwardStart = true, MoveForwardStop = true, + Jump = true, StrafeLeftStart = true, + StrafeLeftStop = true, StrafeRightStart = true, + StrafeRightStop = true, ToggleMouseMove = true, + ToggleRun = true, TurnLeftStart = true, + TurnLeftStop = true, TurnRightStart = true, + TurnRightStop = true, +} + +local function issecurevariable(x) + if protFuncs[x] then + return 1 + else + return nil + end +end + +local _G = getfenv(0) + +local function hooksecurefunc(arg1, arg2, arg3) + if type(arg1) == "string" then + arg1, arg2, arg3 = _G, arg1, arg2 + end + local orig = arg1[arg2] + arg1[arg2] = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + local x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15,x16,x17,x18,x19,x20 = orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + + arg3(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + + return x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15,x16,x17,x18,x19,x20 + end +end + +local protectedScripts = { + OnClick = true, +} + + +local handlers, scripts, actives, registry + +--[[--------------------------------------------------------------------------------- + Private definitions (Not exposed) +----------------------------------------------------------------------------------]] + +local new, del +do + local list = setmetatable({}, {__mode = "k"}) + function new() + local t = next(list) + if not t then + return {} + end + list[t] = nil + return t + end + + function del(t) + setmetatable(t, nil) + for k in pairs(t) do + t[k] = nil + end + list[t] = true + end +end + +local function createFunctionHook(self, func, handler, orig, secure) + if not secure then + if type(handler) == "string" then + -- The handler is a method, need to self it + local uid + uid = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + if actives[uid] then + return self[handler](self, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + else + return orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + end + end + return uid + else + -- The handler is a function, just call it + local uid + uid = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + if actives[uid] then + return handler(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + else + return orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + end + end + return uid + end + else + -- secure hooks don't call the original method + if type(handler) == "string" then + -- The handler is a method, need to self it + local uid + uid = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + if actives[uid] then + return self[handler](self, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + end + end + return uid + else + -- The handler is a function, just call it + local uid + uid = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + if actives[uid] then + return handler(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + end + end + return uid + end + end +end + +local function createMethodHook(self, object, method, handler, orig, secure, script) + if script then + if type(handler) == "string" then + local uid + uid = function() + if actives[uid] then + return self[handler](self, object) + else + return orig() + end + end + return uid + else + -- The handler is a function, just call it + local uid + uid = function() + if actives[uid] then + return handler(object) + else + return orig() + end + end + return uid + end + elseif not secure then + if type(handler) == "string" then + local uid + uid = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + if actives[uid] then + return self[handler](self, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + else + return orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + end + end + return uid + else + -- The handler is a function, just call it + local uid + uid = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + if actives[uid] then + return handler(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + else + return orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + end + end + return uid + end + else + -- secure hooks don't call the original method + if type(handler) == "string" then + local uid + uid = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + if actives[uid] then + return self[handler](self, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + end + end + return uid + else + -- The handler is a function, just call it + local uid + uid = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + if actives[uid] then + return handler(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20) + end + end + return uid + end + end +end + +local function hookFunction(self, func, handler, secure) + local orig = _G[func] + + if not orig or type(orig) ~= "function" then + AceHook:error("Attempt to hook a non-existant function %q", func) + end + + if not handler then + handler = func + end + + if registry[self][func] then + local uid = registry[self][func] + + if actives[uid] then + -- We have an active hook from this source. Don't multi-hook + AceHook:error("%q already has an active hook from this source.", func) + end + + if handlers[uid] == handler then + -- The hook is inactive, so reactivate it + actives[uid] = true + return + else + AceHook:error("There is a stale hook for %q can't hook or reactivate.", func) + end + end + + if type(handler) == "string" then + if type(self[handler]) ~= "function" then + AceHook:error("Could not find the the handler %q when hooking function %q", handler, func) + end + elseif type(handler) ~= "function" then + AceHook:error("Could not find the handler you supplied when hooking %q", func) + end + + local uid = createFunctionHook(self, func, handler, orig, secure) + registry[self][func] = uid + actives[uid] = true + handlers[uid] = handler + + if not secure then + _G[func] = uid + self.hooks[func] = orig + else + hooksecurefunc(func, uid) + end +end + +local function unhookFunction(self, func) + if not registry[self][func] then + AceHook:error("Tried to unhook %q which is not currently hooked.", func) + end + + local uid = registry[self][func] + + if actives[uid] then + -- See if we own the global function + if self.hooks[func] and _G[func] == uid then + _G[func] = self.hooks[func] + self.hooks[func] = nil + registry[self][func] = nil + handlers[uid] = nil + scripts[uid] = nil + actives[uid] = nil + -- Magically all-done + else + actives[uid] = nil + end + end +end + +local function hookMethod(self, obj, method, handler, script, secure) + if not handler then + handler = method + end + + if not obj or type(obj) ~= "table" then + AceHook:error("The object you supplied could not be found, or isn't a table.") + end + + local uid = registry[self][obj] and registry[self][obj][method] + if uid then + if actives[uid] then + -- We have an active hook from this source. Don't multi-hook + AceHook:error("%q already has an active hook from this source.", method) + end + + if handlers[uid] == handler then + -- The hook is inactive, reactivate it. + actives[uid] = true + return + else + AceHook:error("There is a stale hook for %q can't hook or reactivate.", method) + end + end + + if type(handler) == "string" then + if type(self[handler]) ~= "function" then + AceHook:error("Could not find the handler %q you supplied when hooking method %q", handler, method) + end + elseif type(handler) ~= "function" then + AceHook:error("Could not find the handler you supplied when hooking method %q", method) + end + + local orig + if script then + if not obj.GetScript then + AceHook:error("The object you supplied does not have a GetScript method.") + end + if not obj:HasScript(method) then + AceHook:error("The object you supplied doesn't allow the %q method.", method) + end + + orig = obj:GetScript(method) + if type(orig) ~= "function" then + -- Sometimes there is not a original function for a script. + orig = function() end + end + else + orig = obj[method] + end + if not orig then + AceHook:error("Could not find the method or script %q you are trying to hook.", method) + end + + if not registry[self][obj] then + registry[self][obj] = new() + end + + if not self.hooks[obj] then + self.hooks[obj] = new() + end + + local uid = createMethodHook(self, obj, method, handler, orig, secure, script) + registry[self][obj][method] = uid + actives[uid] = true + handlers[uid] = handler + scripts[uid] = script and true or nil + + if script then + obj:SetScript(method, uid) + self.hooks[obj][method] = orig + elseif not secure then + obj[method] = uid + self.hooks[obj][method] = orig + else + hooksecurefunc(obj, method, uid) + end +end + +local function unhookMethod(self, obj, method) + if not registry[self][obj] or not registry[self][obj][method] then + AceHook:error("Attempt to unhook a method %q that is not currently hooked.", method) + return + end + + local uid = registry[self][obj][method] + + if actives[uid] then + if scripts[uid] then -- If this is a script + if obj:GetScript(method) == uid then + -- We own the script. Revert to normal. + obj:SetScript(method, self.hooks[obj][method]) + self.hooks[obj][method] = nil + registry[self][obj][method] = nil + handlers[uid] = nil + scripts[uid] = nil + actives[uid] = nil + else + actives[uid] = nil + end + else + if self.hooks[obj] and self.hooks[obj][method] and obj[method] == uid then + -- We own the method. Revert to normal. + obj[method] = self.hooks[obj][method] + self.hooks[obj][method] = nil + registry[self][obj][method] = nil + handlers[uid] = nil + actives[uid] = nil + else + actives[uid] = nil + end + end + end + if self.hooks[obj] and not next(self.hooks[obj]) then + self.hooks[obj] = del(self.hooks[obj]) + end + if not next(registry[self][obj]) then + registry[self][obj] = del(registry[self][obj]) + end +end + +-- ("function" [, handler] [, hookSecure]) or (object, "method" [, handler] [, hookSecure]) +function AceHook:Hook(object, method, handler, hookSecure) + if type(object) == "string" then + method, handler, hookSecure = object, method, handler + if handler == true then + handler, hookSecure = nil, true + end + if not hookSecure and issecurevariable(method) then + AceHook:error("Attempt to hook secure function %q. Use `SecureHook' or add `true' to the argument list to override.", method) + end + AceHook:argCheck(handler, 3, "function", "string", "nil") + AceHook:argCheck(hookSecure, 4, "boolean", "nil") + hookFunction(self, method, handler, false) + else + if handler == true then + handler, hookSecure = nil, true + end + if not hookSecure and issecurevariable(object, method) then + AceHook:error("Attempt to hook secure method %q. Use `SecureHook' or add `true' to the argument list to override.", method) + end + AceHook:argCheck(object, 2, "table") + AceHook:argCheck(method, 3, "string") + AceHook:argCheck(handler, 4, "function", "string", "nil") + AceHook:argCheck(hookSecure, 5, "boolean", "nil") + hookMethod(self, object, method, handler, false, false) + end +end + +-- ("function", handler) or (object, "method", handler) +function AceHook:SecureHook(object, method, handler) + if type(object) == "string" then + method, handler = object, method + AceHook:argCheck(handler, 3, "function", "string", "nil") + hookFunction(self, method, handler, true) + else + AceHook:argCheck(object, 2, "table") + AceHook:argCheck(method, 3, "string") + AceHook:argCheck(handler, 4, "function", "string", "nil") + hookMethod(self, object, method, handler, false, true) + end +end + +function AceHook:HookScript(frame, script, handler) + AceHook:argCheck(frame, 2, "table") + if not frame[0] or type(frame.IsFrameType) ~= "function" then + AceHook:error("Bad argument #2 to `HookScript'. Expected frame.") + end + AceHook:argCheck(script, 3, "string") + AceHook:argCheck(handler, 4, "function", "string", "nil") + hookMethod(self, frame, script, handler, true, false) +end + +-- ("function") or (object, "method") +function AceHook:IsHooked(obj, method) + if type(obj) == "string" then + if registry[self][obj] and actives[registry[self][obj]] then + return true, handlers[registry[self][obj]] + end + else + AceHook:argCheck(obj, 2, "string", "table") + AceHook:argCheck(method, 3, "string") + if registry[self][obj] and registry[self][obj][method] and actives[registry[self][obj][method]] then + return true, handlers[registry[self][obj][method]] + end + end + + return false, nil +end + +-- ("function") or (object, "method") +function AceHook:Unhook(obj, method) + if type(obj) == "string" then + unhookFunction(self, obj) + else + AceHook:argCheck(obj, 2, "string", "table") + AceHook:argCheck(method, 3, "string") + unhookMethod(self, obj, method) + end +end + +function AceHook:UnhookAll() + for key, value in pairs(registry[self]) do + if type(key) == "table" then + for method in pairs(value) do + self:Unhook(key, method) + end + else + self:Unhook(key) + end + end +end + +function AceHook:HookReport() + DEFAULT_CHAT_FRAME:AddMessage("This is a list of all active hooks for this object:") + if not next(registry[self]) then + DEFAULT_CHAT_FRAME:AddMessage("No hooks") + end + + for key, value in pairs(registry[self]) do + if type(value) == "table" then + for method, uid in pairs(value) do + DEFAULT_CHAT_FRAME:AddMessage(string.format("object: %s method: %q |cff%s|r%s", tostring(key), method, actives[uid] and "00ff00Active" or "ffff00Inactive", not self.hooks[key][method] and " |cff7f7fff-Secure-|r" or "")) + end + else + DEFAULT_CHAT_FRAME:AddMessage(string.format("function: %q |cff%s|r%s", tostring(key), actives[value] and "00ff00Active" or "ffff00Inactive", not self.hooks[key] and " |cff7f7fff-Secure-|r" or "")) + end + end +end + +function AceHook:OnInstanceInit(object) + if not object.hooks then + object.hooks = new() + end + if not registry[object] then + registry[object] = new() + end +end + +AceHook.OnManualEmbed = AceHook.OnInstanceInit + +function AceHook:OnEmbedDisable(target) + self.UnhookAll(target) +end + +local function activate(self, oldLib, oldDeactivate) + AceHook = self + + self.handlers = oldLib and oldLib.handlers or {} + self.registry = oldLib and oldLib.registry or {} + self.scripts = oldLib and oldLib.scripts or {} + self.actives = oldLib and oldLib.actives or {} + + handlers = self.handlers + registry = self.registry + scripts = self.scripts + actives = self.actives + + AceHook.super.activate(self, oldLib, oldDeactivate) + + if oldDeactivate then + oldDeactivate(oldLib) + end +end + +AceLibrary:Register(AceHook, MAJOR_VERSION, MINOR_VERSION, activate) diff --git a/shootyepgp.lua b/shootyepgp.lua index 0b78cb4..9fb92ad 100644 --- a/shootyepgp.lua +++ b/shootyepgp.lua @@ -22,6 +22,10 @@ local shooty_debugchat local running_check,running_bid local partyUnit,raidUnit = {},{} local reserves_blacklist,bids_blacklist = {},{} +local bidlink = { + ["ms"]="|cffFF3333|Hshootybid:1:$ML|h[Mainspec/Need]|h|r", + ["os"]="|cff009900|Hshootybid:2:$ML|h[Offspec/Greed]|h|r" +} do for i=1,40 do raidUnit[i] = "raid"..i @@ -73,9 +77,10 @@ function sepgp:AceEvent_FullyInitialized() -- SYNTHETIC EVENT, later than PLAYER if (pfUI) and pfUI.api and pfUI.api.CreateBackdrop and pfUI_config and pfUI_config.tooltip and pfUI_config.tooltip.alpha then pfUI.api.CreateBackdrop(sepgp.extratip,nil,nil,pfUI_config.tooltip.alpha) end + -- hook SetItemRef to parse our client bid links + self:Hook("SetItemRef") -- hook tooltip to add our GP values sepgp:TipHook() - -- make tablets closable with ESC for i=1,4 do table.insert(UISpecialFrames,string.format("Tablet20DetachedFrame%d",i)) @@ -130,7 +135,7 @@ function sepgp:TipHook() sepgp:AddDataToTooltip(GameTooltip, GetLootRollItemLink(id)) end ) - self:SecureHook("SetItemRef", function(link, name, button) + --[[self:SecureHook("SetItemRef", function(link, name, button) if (link and name and ItemRefTooltip) then if (strsub(link, 1, 6) ~= "Player") then if (ItemRefTooltip:IsVisible()) then @@ -142,7 +147,7 @@ function sepgp:TipHook() end end end - ) + )]] self:HookScript(GameTooltip, "OnHide", function() if sepgp.extratip:IsVisible() then sepgp.extratip:Hide() end self.hooks[GameTooltip]["OnHide"]() @@ -240,6 +245,37 @@ function sepgp:GuildRosterSetOfficerNote(index,note,fromAddon) end end +function sepgp:SetItemRef(link, name, button) + if string.sub(link,1,9) == "shootybid" then + local _,_,bid,masterlooter = string.find(link,"shootybid:(%d+):(%w+)") + if bid == "1" then + bid = "+" + elseif bid == "2" then + bid = "-" + else + bid = nil + end + if not sepgp:inRaid(masterlooter) then + masterlooter = nil + end + if (bid and masterlooter) then + SendChatMessage(bid,"WHISPER",nil,masterlooter) + end + return + end + self.hooks["SetItemRef"](link, name, button) + if (link and name and ItemRefTooltip) then + if (strsub(link, 1, 4) == "item") then + if (ItemRefTooltip:IsVisible()) then + if (not DressUpFrame:IsVisible()) then + sepgp:AddDataToTooltip(ItemRefTooltip, link) + end + ItemRefTooltip.isDisplayDone = nil + end + end + end +end + ------------------- -- Communication ------------------- @@ -268,6 +304,39 @@ function sepgp:defaultPrint(msg) DEFAULT_CHAT_FRAME:AddMessage(string.format(out,msg)) end +function sepgp:bidPrint(link,masterlooter,need,greed,bid) + local mslink = string.gsub(bidlink["ms"],"$ML",masterlooter) + local oslink = string.gsub(bidlink["os"],"$ML",masterlooter) + local msg = string.format("Click to bid $MS or $OS for %s",link) + if (need and greed) then + msg = string.gsub(msg,"$MS",mslink) + msg = string.gsub(msg,"$OS",oslink) + elseif (need) then + msg = string.gsub(msg,"$MS",mslink) + msg = string.gsub(msg,"or $OS ","") + elseif (greed) then + msg = string.gsub(msg,"$OS",oslink) + msg = string.gsub(msg,"$MS or ","") + elseif (bid) then + msg = string.gsub(msg,"$MS",mslink) + msg = string.gsub(msg,"$OS",oslink) + end + local _, count = string.gsub(msg,"%$","%$") + if (count > 0) then return end + local chatframe + if (SELECTED_CHAT_FRAME) then + chatframe = SELECTED_CHAT_FRAME + else + if not DEFAULT_CHAT_FRAME:IsVisible() then + FCF_SelectDockFrame(DEFAULT_CHAT_FRAME) + end + chatframe = DEFAULT_CHAT_FRAME + end + if (chatframe) then + chatframe:AddMessage(string.format(out,msg)) + end +end + function sepgp:simpleSay(msg) SendChatMessage(string.format("shootyepgp: %s",msg), sepgp_saychannel) end @@ -526,12 +595,13 @@ function sepgp:gp_reset_v3() local name,_,_,_,class,_,note,officernote,_,_ = GetGuildRosterInfo(i) local ep,gp = self:get_ep_v3(name,officernote), self:get_gp_v3(name,officernote) if (ep and gp) then - sepgp:update_epgp_v3(ep,sepgp.VARS.basegp,i,name,officernote) + sepgp:update_epgp_v3(0,sepgp.VARS.basegp,i,name,officernote) end - end - sepgp:debugPrint(string.format("All GP has been reset to %d.",sepgp.VARS.basegp)) - self:adminSay(string.format("All GP has been reset to %d.",sepgp.VARS.basegp)) - self:addToLog(string.format("All GP has been reset to %d.",sepgp.VARS.basegp)) + end + local msg = "All EP and GP has been reset to 0/%d." + sepgp:debugPrint(string.format(msg,sepgp.VARS.basegp)) + self:adminSay(string.format(msg,sepgp.VARS.basegp)) + self:addToLog(string.format(msg,sepgp.VARS.basegp)) end end @@ -943,8 +1013,6 @@ lootCall.bs = { -- blacklist "^(roll)[%s%p%c]+.+",".+[%s%p%c]+(roll)$",".*[%s%p%c]+(roll)[%s%p%c]+.*" } function sepgp:captureLootCall(text, sender) - if not (IsRaidLeader() or self:lootMaster()) then return end - if not sender == playerName then return end if not (string.find(text, "|Hitem:", 1, true)) then return end local linkstriptext, count = string.gsub(text,"|c%x+|H[eimt:%d]+|h%[[%w%s',%-]+%]|h|r"," ; ") if count > 1 then return end @@ -973,14 +1041,17 @@ function sepgp:captureLootCall(text, sender) link_found, _, itemColor, itemString, itemName = string.find(itemLink, "^(|c%x+)|H(.+)|h(%[.+%])") end if (link_found) then - self:clearBids() - sepgp.bid_item.link = itemString - sepgp.bid_item.linkFull = itemLink - sepgp.bid_item.name = string.format("%s%s|r",itemColor,itemName) - self:ScheduleEvent("shootyepgpBidTimeout",self.clearBids,360,self) - running_bid = true - self:debugPrint("Capturing Bids for 6min.") - sepgp_bids:Toggle(true) + if (IsRaidLeader() or self:lootMaster()) and (sender == playerName) then + self:clearBids() + sepgp.bid_item.link = itemString + sepgp.bid_item.linkFull = itemLink + sepgp.bid_item.name = string.format("%s%s|r",itemColor,itemName) + self:ScheduleEvent("shootyepgpBidTimeout",self.clearBids,360,self) + running_bid = true + self:debugPrint("Capturing Bids for 6min.") + sepgp_bids:Toggle(true) + end + sepgp:bidPrint(itemLink,sender,mskw_found,oskw_found,whisperkw_found) end end end @@ -1028,7 +1099,7 @@ function sepgp:captureBid(text, sender) end function sepgp:clearBids() - sepgp:defaultPrint("clearBids") + sepgp:debugPrint("clearing old Bids") sepgp.bid_item = {} sepgp.bids_main = {} sepgp.bids_off = {} diff --git a/shootyepgp.toc b/shootyepgp.toc index 8783cdd..e3dd7a7 100644 --- a/shootyepgp.toc +++ b/shootyepgp.toc @@ -3,7 +3,7 @@ ## Notes: Effort Points/Gear Points Loot System ## Author: Roadblock ## X-Credits: shooty for original version -## Version: 3.11 +## Version: 3.12 ## OptionalDeps: Ace2 ## SavedVariables: sepgp_saychannel,sepgp_groupbyclass,sepgp_raidonly,sepgp_decay,sepgp_reservechannel,sepgp_main,sepgp_progress,sepgp_discount ## SavedVariablesPerCharacter: sepgp_log, sepgp_dbver @@ -12,7 +12,7 @@ Libs\AceLibrary\AceLibrary.lua Libs\AceOO-2.0\AceOO-2.0.lua Libs\AceEvent-2.0\AceEvent-2.0.lua Libs\AceAddon-2.0\AceAddon-2.0.lua -Libs\AceHook-2.0\AceHook-2.0.lua +Libs\AceHook-2.1\AceHook-2.1.lua Libs\AceConsole-2.0\AceConsole-2.0.lua Libs\AceModuleCore-2.0\AceModuleCore-2.0.lua Libs\AceDB-2.0\AceDB-2.0.lua