removed ace
This commit is contained in:
+69
-42
@@ -1,4 +1,11 @@
|
|||||||
Postal = AceLibrary('AceAddon-2.0'):new('AceEvent-2.0', 'AceHook-2.0')
|
local Postal = CreateFrame('Frame', nil, MailFrame)
|
||||||
|
Postal:SetScript('OnUpdate', function()
|
||||||
|
this:UPDATE()
|
||||||
|
end)
|
||||||
|
Postal:SetScript('OnEvent', function()
|
||||||
|
this[event](this)
|
||||||
|
end)
|
||||||
|
Postal:RegisterEvent('ADDON_LOADED')
|
||||||
|
|
||||||
local ATTACHMENTS_MAX = 21
|
local ATTACHMENTS_MAX = 21
|
||||||
local ATTACHMENTS_PER_ROW_SEND = 7
|
local ATTACHMENTS_PER_ROW_SEND = 7
|
||||||
@@ -56,7 +63,7 @@ do
|
|||||||
self:Wait(function()
|
self:Wait(function()
|
||||||
lastPickedUp = item
|
lastPickedUp = item
|
||||||
end)
|
end)
|
||||||
return self.hooks['PickupContainerItem'].orig(unpack(item))
|
return self.PickupContainerItem_Orig(unpack(item))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -95,22 +102,57 @@ function Postal:Print(msg, r, g, b)
|
|||||||
DEFAULT_CHAT_FRAME:AddMessage(msg, r, g, b)
|
DEFAULT_CHAT_FRAME:AddMessage(msg, r, g, b)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Postal:OnEnable()
|
function Postal:ADDON_LOADED()
|
||||||
|
if arg1 ~= 'Postal' then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
UIPanelWindows['MailFrame'].pushable = 1
|
||||||
|
UIPanelWindows['FriendsFrame'].pushable = 2
|
||||||
|
|
||||||
|
MailItem1:SetPoint('TOPLEFT', 'InboxFrame', 'TOPLEFT', 48, -80)
|
||||||
|
for i=1,7 do
|
||||||
|
getglobal('MailItem' .. i .. 'ExpireTime'):SetPoint('TOPRIGHT', 'MailItem' .. i, 'TOPRIGHT', 10, -4)
|
||||||
|
getglobal('MailItem' .. i):SetWidth(280)
|
||||||
|
end
|
||||||
|
|
||||||
|
CreateFrame('GameTooltip', 'PostalTooltip', nil, 'GameTooltipTemplate')
|
||||||
|
PostalTooltip:SetOwner(WorldFrame, 'ANCHOR_NONE')
|
||||||
|
|
||||||
self:RegisterEvent('UI_ERROR_MESSAGE')
|
self:RegisterEvent('UI_ERROR_MESSAGE')
|
||||||
self:RegisterEvent('MAIL_SEND_SUCCESS')
|
self:RegisterEvent('MAIL_SEND_SUCCESS')
|
||||||
self:RegisterEvent('MAIL_CLOSED')
|
self:RegisterEvent('MAIL_CLOSED')
|
||||||
self:RegisterEvent('CURSOR_UPDATE')
|
self:RegisterEvent('CURSOR_UPDATE')
|
||||||
|
|
||||||
self:Hook('ContainerFrameItemButton_OnClick')
|
self.ContainerFrameItemButton_OnClick_Orig = ContainerFrameItemButton_OnClick
|
||||||
self:Hook('PickupContainerItem')
|
ContainerFrameItemButton_OnClick = self.ContainerFrameItemButton_OnClick
|
||||||
self:Hook('UseContainerItem')
|
|
||||||
self:Hook('ClickSendMailItemButton')
|
self.PickupContainerItem_Orig = PickupContainerItem
|
||||||
self:Hook('SendMailFrame_Update')
|
PickupContainerItem = self.PickupContainerItem
|
||||||
self:Hook('SendMailFrame_CanSend')
|
|
||||||
self:Hook('SetItemButtonDesaturated')
|
self.UseContainerItem_Orig = UseContainerItem
|
||||||
self:Hook('InboxFrame_OnClick')
|
UseContainerItem = self.UseContainerItem
|
||||||
self:Hook('InboxFrameItem_OnEnter')
|
|
||||||
self:Hook('InboxFrame_Update')
|
self.ClickSendMailItemButton_Orig = ClickSendMailItemButton
|
||||||
|
ClickSendMailItemButton = self.ClickSendMailItemButton
|
||||||
|
|
||||||
|
self.SendMailFrame_Update_Orig = SendMailFrame_Update
|
||||||
|
SendMailFrame_Update = self.SendMailFrame_Update
|
||||||
|
|
||||||
|
self.SendMailFrame_CanSend_Orig = SendMailFrame_CanSend
|
||||||
|
SendMailFrame_CanSend = self.SendMailFrame_CanSend
|
||||||
|
|
||||||
|
self.SetItemButtonDesaturated_Orig = SetItemButtonDesaturated
|
||||||
|
SetItemButtonDesaturated = self.SetItemButtonDesaturated
|
||||||
|
|
||||||
|
self.InboxFrame_OnClick_Orig = InboxFrame_OnClick
|
||||||
|
InboxFrame_OnClick = self.InboxFrame_OnClick
|
||||||
|
|
||||||
|
self.InboxFrameItem_OnEnter_Orig = InboxFrameItem_OnEnter
|
||||||
|
InboxFrameItem_OnEnter = self.InboxFrameItem_OnEnter
|
||||||
|
|
||||||
|
self.InboxFrame_Update_Orig = InboxFrame_Update
|
||||||
|
InboxFrame_Update = self.InboxFrame_Update
|
||||||
|
|
||||||
SendMailFrame:CreateTexture('PostalHorizontalBarLeft', 'BACKGROUND')
|
SendMailFrame:CreateTexture('PostalHorizontalBarLeft', 'BACKGROUND')
|
||||||
PostalHorizontalBarLeft:SetTexture([[Interface\ClassTrainerFrame\UI-ClassTrainer-HorizontalBar]])
|
PostalHorizontalBarLeft:SetTexture([[Interface\ClassTrainerFrame\UI-ClassTrainer-HorizontalBar]])
|
||||||
@@ -178,25 +220,10 @@ function Postal:OnEnable()
|
|||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
SendMailFrame_Update()
|
|
||||||
end
|
|
||||||
|
|
||||||
function Postal:OnInitialize()
|
|
||||||
|
|
||||||
UIPanelWindows['MailFrame'].pushable = 1
|
|
||||||
UIPanelWindows['FriendsFrame'].pushable = 2
|
|
||||||
|
|
||||||
MailItem1:SetPoint('TOPLEFT', 'InboxFrame', 'TOPLEFT', 48, -80)
|
|
||||||
for i=1,7 do
|
|
||||||
getglobal('MailItem' .. i .. 'ExpireTime'):SetPoint('TOPRIGHT', 'MailItem' .. i, 'TOPRIGHT', 10, -4)
|
|
||||||
getglobal('MailItem' .. i):SetWidth(280)
|
|
||||||
end
|
|
||||||
|
|
||||||
CreateFrame('GameTooltip', 'PostalTooltip', nil, 'GameTooltipTemplate')
|
|
||||||
PostalTooltip:SetOwner(WorldFrame, 'ANCHOR_NONE')
|
|
||||||
|
|
||||||
self.Inbox_selectedItems = {}
|
self.Inbox_selectedItems = {}
|
||||||
self.SendMail_Ready = true
|
self.SendMail_Ready = true
|
||||||
|
|
||||||
|
SendMailFrame_Update()
|
||||||
end
|
end
|
||||||
|
|
||||||
function Postal:SendMailFrame_Update()
|
function Postal:SendMailFrame_Update()
|
||||||
@@ -317,7 +344,7 @@ function Postal:ContainerFrameItemButton_OnClick(btn, ignore)
|
|||||||
if self:SendMail_Attached(item) then
|
if self:SendMail_Attached(item) then
|
||||||
return
|
return
|
||||||
else
|
else
|
||||||
return self.hooks['ContainerFrameItemButton_OnClick'].orig(btn, ignore)
|
return self.ContainerFrameItemButton_OnClick_Orig(btn, ignore)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -381,9 +408,9 @@ end
|
|||||||
function Postal:SetItemButtonDesaturated(itemButton, locked)
|
function Postal:SetItemButtonDesaturated(itemButton, locked)
|
||||||
local item = { itemButton:GetParent():GetID(), itemButton:GetID() }
|
local item = { itemButton:GetParent():GetID(), itemButton:GetID() }
|
||||||
if self:SendMail_Attached(item) then
|
if self:SendMail_Attached(item) then
|
||||||
return self.hooks['SetItemButtonDesaturated'].orig(itemButton, true)
|
return self.SetItemButtonDesaturated_Orig(itemButton, true)
|
||||||
end
|
end
|
||||||
return self.hooks['SetItemButtonDesaturated'].orig(itemButton, locked)
|
return self.SetItemButtonDesaturated_Orig(itemButton, locked)
|
||||||
end
|
end
|
||||||
|
|
||||||
function Postal:UseContainerItem(bag, slot)
|
function Postal:UseContainerItem(bag, slot)
|
||||||
@@ -393,21 +420,21 @@ function Postal:UseContainerItem(bag, slot)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if IsShiftKeyDown() or IsControlKeyDown() or IsAltKeyDown() then
|
if IsShiftKeyDown() or IsControlKeyDown() or IsAltKeyDown() then
|
||||||
self.hooks['UseContainerItem'].orig(unpack(item))
|
self.UseContainerItem_Orig(unpack(item))
|
||||||
elseif SendMailFrame:IsVisible() then
|
elseif SendMailFrame:IsVisible() then
|
||||||
self:SendMail_AttachItem(item)
|
self:SendMail_AttachItem(item)
|
||||||
self.hooks['PickupContainerItem'].orig(unpack(item))
|
self.PickupContainerItem_Orig(unpack(item))
|
||||||
ClearCursor()
|
ClearCursor()
|
||||||
elseif TradeFrame:IsVisible() then
|
elseif TradeFrame:IsVisible() then
|
||||||
for i = 1,6 do
|
for i = 1,6 do
|
||||||
if not GetTradePlayerItemLink(i) then
|
if not GetTradePlayerItemLink(i) then
|
||||||
self.hooks['PickupContainerItem'].orig(unpack(item))
|
self.PickupContainerItem_Orig(unpack(item))
|
||||||
ClickTradeButton(i)
|
ClickTradeButton(i)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
self.hooks['UseContainerItem'].orig(unpack(item))
|
self.UseContainerItem_Orig(unpack(item))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -477,10 +504,10 @@ function Postal:SendMail_Send()
|
|||||||
|
|
||||||
if item then
|
if item then
|
||||||
ClearCursor()
|
ClearCursor()
|
||||||
self.hooks['ClickSendMailItemButton'].orig()
|
self.ClickSendMailItemButton_Orig()
|
||||||
ClearCursor()
|
ClearCursor()
|
||||||
self.hooks['PickupContainerItem'].orig(unpack(item))
|
self.PickupContainerItem_Orig(unpack(item))
|
||||||
self.hooks['ClickSendMailItemButton'].orig()
|
self.ClickSendMailItemButton_Orig()
|
||||||
|
|
||||||
if not GetSendMailItem() then
|
if not GetSendMailItem() then
|
||||||
return self:Print('Postal: An error occured in POSTAL. This might be related to lag, trying to send items with an item placed in the normal send mail window, or trying to send items that cannot be sent.', 1, 0, 0)
|
return self:Print('Postal: An error occured in POSTAL. This might be related to lag, trying to send items with an item placed in the normal send mail window, or trying to send items that cannot be sent.', 1, 0, 0)
|
||||||
@@ -604,7 +631,7 @@ function Postal:Inbox_OpenItem(i, inboxCount, selected)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Postal:InboxFrame_Update()
|
function Postal:InboxFrame_Update()
|
||||||
self.hooks['InboxFrame_Update'].orig()
|
self.InboxFrame_Update_Orig()
|
||||||
for i = 1,7 do
|
for i = 1,7 do
|
||||||
local index = (i + (InboxFrame.pageNum - 1) * 7)
|
local index = (i + (InboxFrame.pageNum - 1) * 7)
|
||||||
if index > GetInboxNumItems() then
|
if index > GetInboxNumItems() then
|
||||||
@@ -631,7 +658,7 @@ function Postal:InboxFrame_OnClick(index)
|
|||||||
this:SetChecked(nil)
|
this:SetChecked(nil)
|
||||||
return
|
return
|
||||||
else
|
else
|
||||||
return self.hooks['InboxFrame_OnClick'].orig(index)
|
return self.InboxFrame_OnClick_Orig(index)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -2,10 +2,4 @@
|
|||||||
## Title: Postal
|
## Title: Postal
|
||||||
## Notes: Postal
|
## Notes: Postal
|
||||||
## Author: shirsig
|
## Author: shirsig
|
||||||
## OptionalDeps: Ace2
|
|
||||||
libs\AceLibrary\AceLibrary.lua
|
|
||||||
libs\AceOO\AceOO-2.0.lua
|
|
||||||
libs\AceEvent\AceEvent-2.0.lua
|
|
||||||
libs\AceAddon\AceAddon-2.0.lua
|
|
||||||
libs\AceHook\AceHook-2.0.lua
|
|
||||||
Postal.xml
|
Postal.xml
|
||||||
|
|||||||
@@ -1,13 +1,6 @@
|
|||||||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/
|
||||||
C:\Projects\WoW\Bin\Interface\FrameXML\UI.xsd">
|
C:\Projects\WoW\Bin\Interface\FrameXML\UI.xsd">
|
||||||
<Script file="Postal.lua"/>
|
<Script file="Postal.lua"/>
|
||||||
<frame parent="MailFrame">
|
|
||||||
<Scripts>
|
|
||||||
<OnUpdate>
|
|
||||||
Postal:UPDATE()
|
|
||||||
</OnUpdate>
|
|
||||||
</Scripts>
|
|
||||||
</frame>
|
|
||||||
|
|
||||||
<EditBox name="PostalSubjectEditBox" parent="SendMailFrame" letters="64" historyLines="0" autoFocus="false">
|
<EditBox name="PostalSubjectEditBox" parent="SendMailFrame" letters="64" historyLines="0" autoFocus="false">
|
||||||
<Size>
|
<Size>
|
||||||
|
|||||||
@@ -1,728 +0,0 @@
|
|||||||
--[[
|
|
||||||
Name: AceAddon-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/AceAddon-2.0
|
|
||||||
SVN: http://svn.wowace.com/root/trunk/Ace2/AceAddon-2.0
|
|
||||||
Description: Base for all Ace addons to inherit from.
|
|
||||||
Dependencies: AceLibrary, AceOO-2.0, AceEvent-2.0, (optional) AceConsole-2.0
|
|
||||||
]]
|
|
||||||
|
|
||||||
local MAJOR_VERSION = "AceAddon-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
|
|
||||||
|
|
||||||
-- Localization
|
|
||||||
local STANDBY, TITLE, NOTES, VERSION, AUTHOR, DATE, CATEGORY, EMAIL, WEBSITE, CATEGORIES, ABOUT, PRINT_ADDON_INFO
|
|
||||||
if false then -- GetLocale() == "deDE"
|
|
||||||
else -- enUS
|
|
||||||
STANDBY = "|cffff5050(standby)|r"
|
|
||||||
|
|
||||||
TITLE = "Title"
|
|
||||||
NOTES = "Notes"
|
|
||||||
VERSION = "Version"
|
|
||||||
AUTHOR = "Author"
|
|
||||||
DATE = "Date"
|
|
||||||
CATEGORY = "Category"
|
|
||||||
EMAIL = "E-mail"
|
|
||||||
WEBSITE = "Website"
|
|
||||||
|
|
||||||
ABOUT = "About"
|
|
||||||
PRINT_ADDON_INFO = "Print out addon info"
|
|
||||||
|
|
||||||
CATEGORIES = {
|
|
||||||
["Action Bars"] = "Action Bars",
|
|
||||||
["Auction"] = "Auction",
|
|
||||||
["Audio"] = "Audio",
|
|
||||||
["Battlegrounds/PvP"] = "Battlegrounds/PvP",
|
|
||||||
["Buffs"] = "Buffs",
|
|
||||||
["Chat/Communication"] = "Chat/Communication",
|
|
||||||
["Druid"] = "Druid",
|
|
||||||
["Hunter"] = "Hunter",
|
|
||||||
["Mage"] = "Mage",
|
|
||||||
["Paladin"] = "Paladin",
|
|
||||||
["Priest"] = "Priest",
|
|
||||||
["Rogue"] = "Rogue",
|
|
||||||
["Shaman"] = "Shaman",
|
|
||||||
["Warlock"] = "Warlock",
|
|
||||||
["Warrior"] = "Warrior",
|
|
||||||
["Healer"] = "Healer",
|
|
||||||
["Tank"] = "Tank",
|
|
||||||
["Caster"] = "Caster",
|
|
||||||
["Combat"] = "Combat",
|
|
||||||
["Compilations"] = "Compilations",
|
|
||||||
["Data Export"] = "Data Export",
|
|
||||||
["Development Tools "] = "Development Tools ",
|
|
||||||
["Guild"] = "Guild",
|
|
||||||
["Frame Modification"] = "Frame Modification",
|
|
||||||
["Interface Enhancements"] = "Interface Enhancements",
|
|
||||||
["Inventory"] = "Inventory",
|
|
||||||
["Library"] = "Library",
|
|
||||||
["Map"] = "Map",
|
|
||||||
["Mail"] = "Mail",
|
|
||||||
["Miscellaneous"] = "Miscellaneous",
|
|
||||||
["Quest"] = "Quest",
|
|
||||||
["Raid"] = "Raid",
|
|
||||||
["Tradeskill"] = "Tradeskill",
|
|
||||||
["UnitFrame"] = "UnitFrame",
|
|
||||||
}
|
|
||||||
end
|
|
||||||
|
|
||||||
setmetatable(CATEGORIES, { __index = function(self, key) -- case-insensitive
|
|
||||||
local lowerKey = string.lower(key)
|
|
||||||
for k,v in CATEGORIES do
|
|
||||||
if string.lower(k) == lowerKey then
|
|
||||||
return v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end })
|
|
||||||
|
|
||||||
-- Create the library object
|
|
||||||
|
|
||||||
local AceOO = AceLibrary("AceOO-2.0")
|
|
||||||
local AceAddon = AceOO.Class()
|
|
||||||
local AceEvent
|
|
||||||
local AceConsole
|
|
||||||
local AceModuleCore
|
|
||||||
|
|
||||||
function AceAddon:ToString()
|
|
||||||
return "AceAddon"
|
|
||||||
end
|
|
||||||
|
|
||||||
local function print(text)
|
|
||||||
DEFAULT_CHAT_FRAME:AddMessage(text)
|
|
||||||
end
|
|
||||||
|
|
||||||
function AceAddon:ADDON_LOADED(name)
|
|
||||||
while table.getn(self.nextAddon) > 0 do
|
|
||||||
local addon = table.remove(self.nextAddon, 1)
|
|
||||||
table.insert(self.addons, addon)
|
|
||||||
if not self.addons[name] then
|
|
||||||
self.addons[name] = addon
|
|
||||||
end
|
|
||||||
self:InitializeAddon(addon, name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function RegisterOnEnable(self)
|
|
||||||
if DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.defaultLanguage then -- HACK
|
|
||||||
AceAddon.playerLoginFired = true
|
|
||||||
end
|
|
||||||
if AceAddon.playerLoginFired then
|
|
||||||
AceAddon.addonsStarted[self] = true
|
|
||||||
if (type(self.IsActive) ~= "function" or self:IsActive()) and (not AceModuleCore or not AceModuleCore:IsModule(self) or AceModuleCore:IsModuleActive(self)) then
|
|
||||||
local current = self.class
|
|
||||||
while true do
|
|
||||||
if current == AceOO.Class then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
if current.mixins then
|
|
||||||
for mixin in pairs(current.mixins) do
|
|
||||||
if type(mixin.OnEmbedEnable) == "function" then
|
|
||||||
mixin:OnEmbedEnable(self)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
current = current.super
|
|
||||||
end
|
|
||||||
if type(self.OnEnable) == "function" then
|
|
||||||
self:OnEnable()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if not AceAddon.addonsToOnEnable then
|
|
||||||
AceAddon.addonsToOnEnable = {}
|
|
||||||
end
|
|
||||||
table.insert(AceAddon.addonsToOnEnable, self)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function stripSpaces(text)
|
|
||||||
if type(text) == "string" then
|
|
||||||
return (string.gsub(string.gsub(text, "^%s*(.-)%s*$", "%1"), "%s%s+", " "))
|
|
||||||
end
|
|
||||||
return text
|
|
||||||
end
|
|
||||||
|
|
||||||
function AceAddon:InitializeAddon(addon, name)
|
|
||||||
if addon.name == nil then
|
|
||||||
addon.name = name
|
|
||||||
end
|
|
||||||
if GetAddOnMetadata then
|
|
||||||
-- TOC checks
|
|
||||||
if addon.title == nil then
|
|
||||||
addon.title = GetAddOnMetadata(name, "Title")
|
|
||||||
if addon.title then
|
|
||||||
local num = string.find(addon.title, " |cff7fff7f %-Ace2%-|r$")
|
|
||||||
if num then
|
|
||||||
addon.title = string.sub(addon.title, 1, num - 1)
|
|
||||||
end
|
|
||||||
addon.title = stripSpaces(addon.title)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if addon.notes == nil then
|
|
||||||
addon.notes = GetAddOnMetadata(name, "Notes")
|
|
||||||
addon.notes = stripSpaces(addon.notes)
|
|
||||||
end
|
|
||||||
if addon.version == nil then
|
|
||||||
addon.version = GetAddOnMetadata(name, "Version")
|
|
||||||
if addon.version then
|
|
||||||
if string.find(addon.version, "%$Revision: (%d+) %$") then
|
|
||||||
addon.version = string.gsub(addon.version, "%$Revision: (%d+) %$", "%1")
|
|
||||||
elseif string.find(addon.version, "%$Rev: (%d+) %$") then
|
|
||||||
addon.version = string.gsub(addon.version, "%$Rev: (%d+) %$", "%1")
|
|
||||||
elseif string.find(addon.version, "%$LastChangedRevision: (%d+) %$") then
|
|
||||||
addon.version = string.gsub(addon.version, "%$LastChangedRevision: (%d+) %$", "%1")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
addon.version = stripSpaces(addon.version)
|
|
||||||
end
|
|
||||||
if addon.author == nil then
|
|
||||||
addon.author = GetAddOnMetadata(name, "Author")
|
|
||||||
addon.author = stripSpaces(addon.author)
|
|
||||||
end
|
|
||||||
if addon.date == nil then
|
|
||||||
addon.date = GetAddOnMetadata(name, "X-Date") or GetAddOnMetadata(name, "X-ReleaseDate")
|
|
||||||
if addon.date then
|
|
||||||
if string.find(addon.date, "%$Date: (.-) %$") then
|
|
||||||
addon.date = string.gsub(addon.date, "%$Date: (.-) %$", "%1")
|
|
||||||
elseif string.find(addon.date, "%$LastChangedDate: (.-) %$") then
|
|
||||||
addon.date = string.gsub(addon.date, "%$LastChangedDate: (.-) %$", "%1")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
addon.date = stripSpaces(addon.date)
|
|
||||||
end
|
|
||||||
if addon.category == nil then
|
|
||||||
addon.category = GetAddOnMetadata(name, "X-Category")
|
|
||||||
addon.category = stripSpaces(addon.category)
|
|
||||||
end
|
|
||||||
if addon.email == nil then
|
|
||||||
addon.email = GetAddOnMetadata(name, "X-eMail") or GetAddOnMetadata(name, "X-Email")
|
|
||||||
addon.email = stripSpaces(addon.email)
|
|
||||||
end
|
|
||||||
if addon.website == nil then
|
|
||||||
addon.website = GetAddOnMetadata(name, "X-Website")
|
|
||||||
addon.website = stripSpaces(addon.website)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local current = addon.class
|
|
||||||
while true do
|
|
||||||
if current == AceOO.Class then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
if current.mixins then
|
|
||||||
for mixin in pairs(current.mixins) do
|
|
||||||
if type(mixin.OnEmbedInitialize) == "function" then
|
|
||||||
mixin:OnEmbedInitialize(addon, name)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
current = current.super
|
|
||||||
end
|
|
||||||
if type(addon.OnInitialize) == "function" then
|
|
||||||
addon:OnInitialize(name)
|
|
||||||
end
|
|
||||||
RegisterOnEnable(addon)
|
|
||||||
end
|
|
||||||
|
|
||||||
function AceAddon.prototype:PrintAddonInfo()
|
|
||||||
local x
|
|
||||||
if self.title then
|
|
||||||
x = "|cffffff7f" .. tostring(self.title) .. "|r"
|
|
||||||
elseif self.name then
|
|
||||||
x = "|cffffff7f" .. tostring(self.name) .. "|r"
|
|
||||||
else
|
|
||||||
x = "|cffffff7f<" .. tostring(self.class) .. " instance>|r"
|
|
||||||
end
|
|
||||||
if type(self.IsActive) == "function" then
|
|
||||||
if not self:IsActive() then
|
|
||||||
x = x .. " " .. STANDBY
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if self.version then
|
|
||||||
x = x .. " - |cffffff7f" .. tostring(self.version) .. "|r"
|
|
||||||
end
|
|
||||||
if self.notes then
|
|
||||||
x = x .. " - " .. tostring(self.notes)
|
|
||||||
end
|
|
||||||
print(x)
|
|
||||||
if self.author then
|
|
||||||
print(" - |cffffff7f" .. AUTHOR .. ":|r " .. tostring(self.author))
|
|
||||||
end
|
|
||||||
if self.date then
|
|
||||||
print(" - |cffffff7f" .. DATE .. ":|r " .. tostring(self.date))
|
|
||||||
end
|
|
||||||
if self.category then
|
|
||||||
local category = CATEGORIES[self.category]
|
|
||||||
if category then
|
|
||||||
print(" - |cffffff7f" .. CATEGORY .. ":|r " .. category)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if self.email then
|
|
||||||
print(" - |cffffff7f" .. EMAIL .. ":|r " .. tostring(self.email))
|
|
||||||
end
|
|
||||||
if self.website then
|
|
||||||
print(" - |cffffff7f" .. WEBSITE .. ":|r " .. tostring(self.website))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local options
|
|
||||||
function AceAddon:GetAceOptionsDataTable(target)
|
|
||||||
if not options then
|
|
||||||
options = {
|
|
||||||
about = {
|
|
||||||
name = ABOUT,
|
|
||||||
desc = PRINT_ADDON_INFO,
|
|
||||||
type = "execute",
|
|
||||||
func = "PrintAddonInfo",
|
|
||||||
order = -1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
end
|
|
||||||
return options
|
|
||||||
end
|
|
||||||
|
|
||||||
function AceAddon:PLAYER_LOGIN()
|
|
||||||
self.playerLoginFired = true
|
|
||||||
if self.addonsToOnEnable then
|
|
||||||
while table.getn(self.addonsToOnEnable) > 0 do
|
|
||||||
local addon = table.remove(self.addonsToOnEnable, 1)
|
|
||||||
self.addonsStarted[addon] = true
|
|
||||||
if (type(addon.IsActive) ~= "function" or addon:IsActive()) and (not AceModuleCore or not AceModuleCore:IsModule(addon) or AceModuleCore:IsModuleActive(addon)) then
|
|
||||||
local current = addon.class
|
|
||||||
while true do
|
|
||||||
if current == AceOO.Class then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
if current.mixins then
|
|
||||||
for mixin in pairs(current.mixins) do
|
|
||||||
if type(mixin.OnEmbedEnable) == "function" then
|
|
||||||
mixin:OnEmbedEnable(addon)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
current = current.super
|
|
||||||
end
|
|
||||||
if type(addon.OnEnable) == "function" then
|
|
||||||
addon:OnEnable()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
self.addonsToOnEnable = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function AceAddon.prototype:Inject(t)
|
|
||||||
AceAddon:argCheck(t, 2, "table")
|
|
||||||
for k,v in pairs(t) do
|
|
||||||
self[k] = v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function AceAddon.prototype:init()
|
|
||||||
if not AceEvent then
|
|
||||||
error(MAJOR_VERSION .. " requires AceEvent-2.0", 4)
|
|
||||||
end
|
|
||||||
AceAddon.super.prototype.init(self)
|
|
||||||
|
|
||||||
self.super = self.class.prototype
|
|
||||||
|
|
||||||
AceAddon:RegisterEvent("ADDON_LOADED", "ADDON_LOADED", true)
|
|
||||||
table.insert(AceAddon.nextAddon, self)
|
|
||||||
end
|
|
||||||
|
|
||||||
function AceAddon.prototype:ToString()
|
|
||||||
local x
|
|
||||||
if type(self.title) == "string" then
|
|
||||||
x = self.title
|
|
||||||
elseif type(self.name) == "string" then
|
|
||||||
x = self.name
|
|
||||||
else
|
|
||||||
x = "<" .. tostring(self.class) .. " instance>"
|
|
||||||
end
|
|
||||||
if (type(self.IsActive) == "function" and not self:IsActive()) or (AceModuleCore and AceModuleCore:IsModule(addon) and AceModuleCore:IsModuleActive(addon)) then
|
|
||||||
x = x .. " " .. STANDBY
|
|
||||||
end
|
|
||||||
return x
|
|
||||||
end
|
|
||||||
|
|
||||||
AceAddon.new = function(self, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20)
|
|
||||||
local class = AceAddon:pcall(AceOO.Classpool, self, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18, m19, m20)
|
|
||||||
return class:new()
|
|
||||||
end
|
|
||||||
|
|
||||||
local function external(self, major, instance)
|
|
||||||
if major == "AceEvent-2.0" then
|
|
||||||
AceEvent = instance
|
|
||||||
|
|
||||||
AceEvent:embed(self)
|
|
||||||
|
|
||||||
self:RegisterEvent("PLAYER_LOGIN", "PLAYER_LOGIN", true)
|
|
||||||
elseif major == "AceConsole-2.0" then
|
|
||||||
AceConsole = instance
|
|
||||||
|
|
||||||
local slashCommands = { "/ace2" }
|
|
||||||
local _,_,_,enabled,loadable = GetAddOnInfo("Ace")
|
|
||||||
if not enabled or not loadable then
|
|
||||||
table.insert(slashCommands, "/ace")
|
|
||||||
end
|
|
||||||
local function listAddon(addon, depth)
|
|
||||||
if not depth then
|
|
||||||
depth = 0
|
|
||||||
end
|
|
||||||
|
|
||||||
local s = string.rep(" ", depth) .. " - " .. tostring(addon)
|
|
||||||
if addon.version then
|
|
||||||
s = s .. " - |cffffff7f" .. tostring(addon.version) .. "|r"
|
|
||||||
end
|
|
||||||
if addon.slashCommand then
|
|
||||||
s = s .. " |cffffff7f(" .. tostring(addon.slashCommand) .. ")|r"
|
|
||||||
end
|
|
||||||
print(s)
|
|
||||||
if type(addon.modules) == "table" then
|
|
||||||
local i = 0
|
|
||||||
for k,v in pairs(addon.modules) do
|
|
||||||
i = i + 1
|
|
||||||
if i == 6 then
|
|
||||||
print(string.rep(" ", depth + 1) .. " - more...")
|
|
||||||
break
|
|
||||||
else
|
|
||||||
listAddon(v, depth + 1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local function listNormalAddon(i)
|
|
||||||
local name,_,_,enabled,loadable = GetAddOnInfo(i)
|
|
||||||
if not loadable then
|
|
||||||
enabled = false
|
|
||||||
end
|
|
||||||
if self.addons[name] then
|
|
||||||
local addon = self.addons[name]
|
|
||||||
if not AceCoreAddon or not AceCoreAddon:IsModule(addon) then
|
|
||||||
listAddon(addon)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
local s = " - " .. tostring(GetAddOnMetadata(i, "Title") or name)
|
|
||||||
local version = GetAddOnMetadata(i, "Version")
|
|
||||||
if version then
|
|
||||||
if string.find(version, "%$Revision: (%d+) %$") then
|
|
||||||
version = string.gsub(version, "%$Revision: (%d+) %$", "%1")
|
|
||||||
elseif string.find(version, "%$Rev: (%d+) %$") then
|
|
||||||
version = string.gsub(version, "%$Rev: (%d+) %$", "%1")
|
|
||||||
elseif string.find(version, "%$LastChangedRevision: (%d+) %$") then
|
|
||||||
version = string.gsub(version, "%$LastChangedRevision: (%d+) %$", "%1")
|
|
||||||
end
|
|
||||||
s = s .. " - |cffffff7f" .. version .. "|r"
|
|
||||||
end
|
|
||||||
if not enabled then
|
|
||||||
s = s .. " |cffff0000(disabled)|r"
|
|
||||||
end
|
|
||||||
if IsAddOnLoadOnDemand(i) then
|
|
||||||
s = s .. " |cff00ff00[LoD]|r"
|
|
||||||
end
|
|
||||||
print(s)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local function mySort(alpha, bravo)
|
|
||||||
return tostring(alpha) < tostring(bravo)
|
|
||||||
end
|
|
||||||
AceConsole.RegisterChatCommand(self, slashCommands, {
|
|
||||||
desc = "AddOn development framework",
|
|
||||||
name = "Ace2",
|
|
||||||
type = "group",
|
|
||||||
args = {
|
|
||||||
about = {
|
|
||||||
desc = "Get information about Ace2",
|
|
||||||
name = "About",
|
|
||||||
type = "execute",
|
|
||||||
func = function()
|
|
||||||
print("|cffffff7fAce2|r - |cffffff7f2.0." .. string.gsub(MINOR_VERSION, "%$Revision: (%d+) %$", "%1") .. "|r - AddOn development framework")
|
|
||||||
print(" - |cffffff7f" .. AUTHOR .. ":|r Ace Development Team")
|
|
||||||
print(" - |cffffff7f" .. WEBSITE .. ":|r http://www.wowace.com/")
|
|
||||||
end
|
|
||||||
},
|
|
||||||
list = {
|
|
||||||
desc = "List addons",
|
|
||||||
name = "List",
|
|
||||||
type = "group",
|
|
||||||
args = {
|
|
||||||
ace2 = {
|
|
||||||
desc = "List addons using Ace2",
|
|
||||||
name = "Ace2",
|
|
||||||
type = "execute",
|
|
||||||
func = function()
|
|
||||||
print("|cffffff7fAddon list:|r")
|
|
||||||
local AceCoreAddon = AceLibrary:HasInstance("AceCoreAddon-2.0") and AceLibrary("AceCoreAddon-2.0")
|
|
||||||
table.sort(self.addons, mySort)
|
|
||||||
for _,v in ipairs(self.addons) do
|
|
||||||
if not AceCoreAddon or not AceCoreAddon:IsModule(v) then
|
|
||||||
listAddon(v)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
},
|
|
||||||
all = {
|
|
||||||
desc = "List all addons",
|
|
||||||
name = "All",
|
|
||||||
type = "execute",
|
|
||||||
func = function()
|
|
||||||
print("|cffffff7fAddon list:|r")
|
|
||||||
local AceCoreAddon = AceLibrary:HasInstance("AceCoreAddon-2.0") and AceLibrary("AceCoreAddon-2.0")
|
|
||||||
local count = GetNumAddOns()
|
|
||||||
for i = 1, count do
|
|
||||||
listNormalAddon(i)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
},
|
|
||||||
enabled = {
|
|
||||||
desc = "List all enabled addons",
|
|
||||||
name = "Enabled",
|
|
||||||
type = "execute",
|
|
||||||
func = function()
|
|
||||||
print("|cffffff7fAddon list:|r")
|
|
||||||
local AceCoreAddon = AceLibrary:HasInstance("AceCoreAddon-2.0") and AceLibrary("AceCoreAddon-2.0")
|
|
||||||
local count = GetNumAddOns()
|
|
||||||
for i = 1, count do
|
|
||||||
local _,_,_,enabled,loadable = GetAddOnInfo(i)
|
|
||||||
if enabled and loadable then
|
|
||||||
listNormalAddon(i)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
},
|
|
||||||
disabled = {
|
|
||||||
desc = "List all disabled addons",
|
|
||||||
name = "Disabled",
|
|
||||||
type = "execute",
|
|
||||||
func = function()
|
|
||||||
print("|cffffff7fAddon list:|r")
|
|
||||||
local AceCoreAddon = AceLibrary:HasInstance("AceCoreAddon-2.0") and AceLibrary("AceCoreAddon-2.0")
|
|
||||||
local count = GetNumAddOns()
|
|
||||||
for i = 1, count do
|
|
||||||
local _,_,_,enabled,loadable = GetAddOnInfo(i)
|
|
||||||
if not enabled or not loadable then
|
|
||||||
listNormalAddon(i)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
},
|
|
||||||
lod = {
|
|
||||||
desc = "List all LoadOnDemand addons",
|
|
||||||
name = "LoadOnDemand",
|
|
||||||
type = "execute",
|
|
||||||
func = function()
|
|
||||||
print("|cffffff7fAddon list:|r")
|
|
||||||
local AceCoreAddon = AceLibrary:HasInstance("AceCoreAddon-2.0") and AceLibrary("AceCoreAddon-2.0")
|
|
||||||
local count = GetNumAddOns()
|
|
||||||
for i = 1, count do
|
|
||||||
if IsAddOnLoadOnDemand(i) then
|
|
||||||
listNormalAddon(i)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
},
|
|
||||||
ace1 = {
|
|
||||||
desc = "List all addons using Ace1",
|
|
||||||
name = "Ace 1.x",
|
|
||||||
type = "execute",
|
|
||||||
func = function()
|
|
||||||
print("|cffffff7fAddon list:|r")
|
|
||||||
local count = GetNumAddOns()
|
|
||||||
for i = 1, count do
|
|
||||||
local dep1, dep2, dep3, dep4 = GetAddOnDependencies(i)
|
|
||||||
if dep1 == "Ace" or dep2 == "Ace" or dep3 == "Ace" or dep4 == "Ace" then
|
|
||||||
listNormalAddon(i)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
},
|
|
||||||
libs = {
|
|
||||||
desc = "List all libraries using AceLibrary",
|
|
||||||
name = "Libraries",
|
|
||||||
type = "execute",
|
|
||||||
func = function()
|
|
||||||
if type(AceLibrary) == "table" and type(AceLibrary.libs) == "table" then
|
|
||||||
print("|cffffff7fLibrary list:|r")
|
|
||||||
for name, data in pairs(AceLibrary.libs) do
|
|
||||||
local s
|
|
||||||
if data.minor then
|
|
||||||
s = " - " .. tostring(name) .. "." .. tostring(data.minor)
|
|
||||||
else
|
|
||||||
s = " - " .. tostring(name)
|
|
||||||
end
|
|
||||||
if AceLibrary(name).slashCommand then
|
|
||||||
s = s .. " |cffffff7f(" .. tostring(AceLibrary(name).slashCommand) .. "|cffffff7f)"
|
|
||||||
end
|
|
||||||
print(s)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
},
|
|
||||||
search = {
|
|
||||||
desc = "Search by name",
|
|
||||||
name = "Search",
|
|
||||||
type = "text",
|
|
||||||
usage = "<keyword>",
|
|
||||||
input = true,
|
|
||||||
get = false,
|
|
||||||
set = function(...)
|
|
||||||
for i,v in ipairs(arg) do
|
|
||||||
arg[i] = string.lower(string.gsub(string.gsub(v, '%*', '.*'), '%%', '%%%%'))
|
|
||||||
end
|
|
||||||
local count = GetNumAddOns()
|
|
||||||
for i = 1, count do
|
|
||||||
local name = GetAddOnInfo(i)
|
|
||||||
local good = true
|
|
||||||
for _,v in ipairs(arg) do
|
|
||||||
if not string.find(string.lower(name), v) then
|
|
||||||
good = false
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if good then
|
|
||||||
listNormalAddon(i)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
enable = {
|
|
||||||
desc = "Enable addon",
|
|
||||||
name = "Enable",
|
|
||||||
type = "text",
|
|
||||||
usage = "<addon>",
|
|
||||||
get = false,
|
|
||||||
set = function(text)
|
|
||||||
local name,title,_,_,_,reason = GetAddOnInfo(text)
|
|
||||||
if reason == "MISSING" then
|
|
||||||
print(string.format("|cffffff7fAce2:|r AddOn %q does not exist", text))
|
|
||||||
else
|
|
||||||
EnableAddOn(text)
|
|
||||||
print(string.format("|cffffff7fAce2:|r %s is now enabled", title or name))
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
disable = {
|
|
||||||
desc = "Disable addon",
|
|
||||||
name = "Disable",
|
|
||||||
type = "text",
|
|
||||||
usage = "<addon>",
|
|
||||||
get = false,
|
|
||||||
set = function(text)
|
|
||||||
local name,title,_,_,_,reason = GetAddOnInfo(text)
|
|
||||||
if reason == "MISSING" then
|
|
||||||
print(string.format("|cffffff7fAce2:|r AddOn %q does not exist", text))
|
|
||||||
else
|
|
||||||
DisableAddOn(text)
|
|
||||||
print(string.format("|cffffff7fAce2:|r %s is now disabled", title or name))
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
},
|
|
||||||
load = {
|
|
||||||
desc = "Load addon",
|
|
||||||
name = "Load",
|
|
||||||
type = "text",
|
|
||||||
usage = "<addon>",
|
|
||||||
get = false,
|
|
||||||
set = function(text)
|
|
||||||
local name,title,_,_,loadable,reason = GetAddOnInfo(text)
|
|
||||||
if reason == "MISSING" then
|
|
||||||
print(string.format("|cffffff7fAce2:|r AddOn %q does not exist.", text))
|
|
||||||
elseif not loadable then
|
|
||||||
print(string.format("|cffffff7fAce2:|r AddOn %q is not loadable. Reason: %s", text, reason))
|
|
||||||
else
|
|
||||||
LoadAddOn(text)
|
|
||||||
print(string.format("|cffffff7fAce2:|r %s is now loaded", title or name))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
},
|
|
||||||
info = {
|
|
||||||
desc = "Display information",
|
|
||||||
name = "Information",
|
|
||||||
type = "execute",
|
|
||||||
func = function()
|
|
||||||
local mem, threshold = gcinfo()
|
|
||||||
print(string.format(" - |cffffff7fMemory usage [|r%.3f MiB|cffffff7f]|r", mem / 1024))
|
|
||||||
print(string.format(" - |cffffff7fThreshold [|r%.3f MiB|cffffff7f]|r", threshold / 1024))
|
|
||||||
print(string.format(" - |cffffff7fFramerate [|r%.0f fps|cffffff7f]|r", GetFramerate()))
|
|
||||||
local bandwidthIn, bandwidthOut, latency = GetNetStats()
|
|
||||||
bandwidthIn, bandwidthOut = floor(bandwidthIn * 1024), floor(bandwidthOut * 1024)
|
|
||||||
print(string.format(" - |cffffff7fLatency [|r%.0f ms|cffffff7f]|r", latency))
|
|
||||||
print(string.format(" - |cffffff7fBandwidth in [|r%.0f B/s|cffffff7f]|r", bandwidthIn))
|
|
||||||
print(string.format(" - |cffffff7fBandwidth out [|r%.0f B/s|cffffff7f]|r", bandwidthOut))
|
|
||||||
print(string.format(" - |cffffff7fTotal addons [|r%d|cffffff7f]|r", GetNumAddOns()))
|
|
||||||
print(string.format(" - |cffffff7fAce2 addons [|r%d|cffffff7f]|r", table.getn(self.addons)))
|
|
||||||
local ace = 0
|
|
||||||
local enabled = 0
|
|
||||||
local disabled = 0
|
|
||||||
local lod = 0
|
|
||||||
for i = 1, GetNumAddOns() do
|
|
||||||
local dep1, dep2, dep3, dep4 = GetAddOnDependencies(i)
|
|
||||||
if dep1 == "Ace" or dep2 == "Ace" or dep3 == "Ace" or dep4 == "Ace" then
|
|
||||||
ace = ace + 1
|
|
||||||
end
|
|
||||||
if IsAddOnLoadOnDemand(i) then
|
|
||||||
lod = lod + 1
|
|
||||||
end
|
|
||||||
local _,_,_,IsActive,loadable = GetAddOnInfo(i)
|
|
||||||
if not IsActive or not loadable then
|
|
||||||
disabled = disabled + 1
|
|
||||||
else
|
|
||||||
enabled = enabled + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
print(string.format(" - |cffffff7fAce 1.x addons [|r%d|cffffff7f]|r", ace))
|
|
||||||
print(string.format(" - |cffffff7fLoadOnDemand addons [|r%d|cffffff7f]|r", lod))
|
|
||||||
print(string.format(" - |cffffff7fenabled addons [|r%d|cffffff7f]|r", enabled))
|
|
||||||
print(string.format(" - |cffffff7fdisabled addons [|r%d|cffffff7f]|r", disabled))
|
|
||||||
local libs = 0
|
|
||||||
if type(AceLibrary) == "table" and type(AceLibrary.libs) == "table" then
|
|
||||||
for _ in pairs(AceLibrary.libs) do
|
|
||||||
libs = libs + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
print(string.format(" - |cffffff7fAceLibrary instances [|r%d|cffffff7f]|r", libs))
|
|
||||||
end
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
elseif major == "AceModuleCore-2.0" then
|
|
||||||
AceModuleCore = instance
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function activate(self, oldLib, oldDeactivate)
|
|
||||||
AceAddon = self
|
|
||||||
|
|
||||||
if oldLib then
|
|
||||||
self.playerLoginFired = oldLib.playerLoginFired or DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.defaultLanguage
|
|
||||||
self.addonsToOnEnable = oldLib.addonsToOnEnable
|
|
||||||
self.addons = oldLib.addons
|
|
||||||
self.nextAddon = oldLib.nextAddon
|
|
||||||
self.addonsStarted = oldLib.addonsStarted
|
|
||||||
end
|
|
||||||
if not self.addons then
|
|
||||||
self.addons = {}
|
|
||||||
end
|
|
||||||
if not self.nextAddon then
|
|
||||||
self.nextAddon = {}
|
|
||||||
end
|
|
||||||
if not self.addonsStarted then
|
|
||||||
self.addonsStarted = {}
|
|
||||||
end
|
|
||||||
if oldDeactivate then
|
|
||||||
oldDeactivate(oldLib)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
AceLibrary:Register(AceAddon, MAJOR_VERSION, MINOR_VERSION, activate, nil, external)
|
|
||||||
AceAddon = AceLibrary(MAJOR_VERSION)
|
|
||||||
@@ -1,956 +0,0 @@
|
|||||||
--[[
|
|
||||||
Name: AceEvent-2.0
|
|
||||||
Revision: $Rev: 11577 $
|
|
||||||
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/AceEvent-2.0
|
|
||||||
SVN: http://svn.wowace.com/root/trunk/Ace2/AceEvent-2.0
|
|
||||||
Description: Mixin to allow for event handling, scheduling, and inter-addon
|
|
||||||
communication.
|
|
||||||
Dependencies: AceLibrary, AceOO-2.0
|
|
||||||
]]
|
|
||||||
|
|
||||||
local MAJOR_VERSION = "AceEvent-2.0"
|
|
||||||
local MINOR_VERSION = "$Revision: 11577 $"
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
local AceOO = AceLibrary:GetInstance("AceOO-2.0")
|
|
||||||
local Mixin = AceOO.Mixin
|
|
||||||
local AceEvent = Mixin {
|
|
||||||
"RegisterEvent",
|
|
||||||
"RegisterAllEvents",
|
|
||||||
"UnregisterEvent",
|
|
||||||
"UnregisterAllEvents",
|
|
||||||
"TriggerEvent",
|
|
||||||
"ScheduleEvent",
|
|
||||||
"ScheduleRepeatingEvent",
|
|
||||||
"CancelScheduledEvent",
|
|
||||||
"CancelAllScheduledEvents",
|
|
||||||
"IsEventRegistered",
|
|
||||||
"IsEventScheduled",
|
|
||||||
"RegisterBucketEvent",
|
|
||||||
"UnregisterBucketEvent",
|
|
||||||
"UnregisterAllBucketEvents",
|
|
||||||
"IsBucketEventRegistered",
|
|
||||||
}
|
|
||||||
|
|
||||||
local table_setn
|
|
||||||
do
|
|
||||||
local version = GetBuildInfo()
|
|
||||||
if string.find(version, "^2%.") then
|
|
||||||
-- 2.0.0
|
|
||||||
table_setn = function() end
|
|
||||||
else
|
|
||||||
table_setn = table.setn
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local weakKey = {__mode="k"}
|
|
||||||
local new, del
|
|
||||||
do
|
|
||||||
local list = setmetatable({}, weakKey)
|
|
||||||
function new()
|
|
||||||
local t = next(list)
|
|
||||||
if t then
|
|
||||||
list[t] = nil
|
|
||||||
return t
|
|
||||||
else
|
|
||||||
return {}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function del(t)
|
|
||||||
setmetatable(t, nil)
|
|
||||||
for k in pairs(t) do
|
|
||||||
t[k] = nil
|
|
||||||
end
|
|
||||||
list[t] = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local FAKE_NIL
|
|
||||||
local RATE
|
|
||||||
|
|
||||||
local eventsWhichHappenOnce = {
|
|
||||||
PLAYER_LOGIN = true,
|
|
||||||
AceEvent_FullyInitialized = true,
|
|
||||||
VARIABLES_LOADED = true,
|
|
||||||
PLAYER_LOGOUT = true,
|
|
||||||
}
|
|
||||||
|
|
||||||
local registeringFromAceEvent
|
|
||||||
function AceEvent:RegisterEvent(event, method, once)
|
|
||||||
AceEvent:argCheck(event, 2, "string")
|
|
||||||
if self == AceEvent and not registeringFromAceEvent then
|
|
||||||
AceEvent:argCheck(method, 3, "function")
|
|
||||||
self = method
|
|
||||||
else
|
|
||||||
AceEvent:argCheck(method, 3, "string", "function", "nil", "boolean", "number")
|
|
||||||
if type(method) == "boolean" or type(method) == "number" then
|
|
||||||
AceEvent:argCheck(once, 4, "nil")
|
|
||||||
once, method = method, event
|
|
||||||
end
|
|
||||||
end
|
|
||||||
AceEvent:argCheck(once, 4, "number", "boolean", "nil")
|
|
||||||
if eventsWhichHappenOnce[event] then
|
|
||||||
once = true
|
|
||||||
end
|
|
||||||
local throttleRate
|
|
||||||
if type(once) == "number" then
|
|
||||||
throttleRate, once = once
|
|
||||||
end
|
|
||||||
if not method then
|
|
||||||
method = event
|
|
||||||
end
|
|
||||||
if type(method) == "string" and type(self[method]) ~= "function" then
|
|
||||||
AceEvent:error("Cannot register event %q to method %q, it does not exist", event, method)
|
|
||||||
else
|
|
||||||
assert(type(method) == "function" or type(method) == "string")
|
|
||||||
end
|
|
||||||
|
|
||||||
local AceEvent_registry = AceEvent.registry
|
|
||||||
if not AceEvent_registry[event] then
|
|
||||||
AceEvent_registry[event] = new()
|
|
||||||
AceEvent.frame:RegisterEvent(event)
|
|
||||||
end
|
|
||||||
|
|
||||||
local remember = true
|
|
||||||
if AceEvent_registry[event][self] then
|
|
||||||
remember = false
|
|
||||||
end
|
|
||||||
AceEvent_registry[event][self] = method
|
|
||||||
|
|
||||||
local AceEvent_onceRegistry = AceEvent.onceRegistry
|
|
||||||
if once then
|
|
||||||
if not AceEvent_onceRegistry then
|
|
||||||
AceEvent.onceRegistry = new()
|
|
||||||
AceEvent_onceRegistry = AceEvent.onceRegistry
|
|
||||||
end
|
|
||||||
if not AceEvent_onceRegistry[event] then
|
|
||||||
AceEvent_onceRegistry[event] = new()
|
|
||||||
end
|
|
||||||
AceEvent_onceRegistry[event][self] = true
|
|
||||||
else
|
|
||||||
if AceEvent_onceRegistry and AceEvent_onceRegistry[event] then
|
|
||||||
AceEvent_onceRegistry[event][self] = nil
|
|
||||||
if not next(AceEvent_onceRegistry[event]) then
|
|
||||||
AceEvent_onceRegistry[event] = del(AceEvent_onceRegistry[event])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local AceEvent_throttleRegistry = AceEvent.throttleRegistry
|
|
||||||
if throttleRate then
|
|
||||||
if not AceEvent_throttleRegistry then
|
|
||||||
AceEvent.throttleRegistry = new()
|
|
||||||
AceEvent_throttleRegistry = AceEvent.throttleRegistry
|
|
||||||
end
|
|
||||||
if not AceEvent_throttleRegistry[event] then
|
|
||||||
AceEvent_throttleRegistry[event] = new()
|
|
||||||
end
|
|
||||||
if AceEvent_throttleRegistry[event][self] then
|
|
||||||
AceEvent_throttleRegistry[event][self] = del(AceEvent_throttleRegistry[event][self])
|
|
||||||
end
|
|
||||||
AceEvent_throttleRegistry[event][self] = setmetatable(new(), weakKey)
|
|
||||||
local t = AceEvent_throttleRegistry[event][self]
|
|
||||||
t[RATE] = throttleRate
|
|
||||||
else
|
|
||||||
if AceEvent_throttleRegistry and AceEvent_throttleRegistry[event] then
|
|
||||||
if AceEvent_throttleRegistry[event][self] then
|
|
||||||
AceEvent_throttleRegistry[event][self] = del(AceEvent_throttleRegistry[event][self])
|
|
||||||
end
|
|
||||||
if not next(AceEvent_throttleRegistry[event]) then
|
|
||||||
AceEvent_throttleRegistry[event] = del(AceEvent_throttleRegistry[event])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if remember then
|
|
||||||
AceEvent:TriggerEvent("AceEvent_EventRegistered", self, event)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local ALL_EVENTS
|
|
||||||
|
|
||||||
function AceEvent:RegisterAllEvents(method)
|
|
||||||
if self == AceEvent then
|
|
||||||
AceEvent:argCheck(method, 1, "function")
|
|
||||||
self = method
|
|
||||||
else
|
|
||||||
AceEvent:argCheck(method, 1, "string", "function")
|
|
||||||
if type(method) == "string" and type(self[method]) ~= "function" then
|
|
||||||
AceEvent:error("Cannot register all events to method %q, it does not exist", method)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local AceEvent_registry = AceEvent.registry
|
|
||||||
if not AceEvent_registry[ALL_EVENTS] then
|
|
||||||
AceEvent_registry[ALL_EVENTS] = new()
|
|
||||||
AceEvent.frame:RegisterAllEvents()
|
|
||||||
end
|
|
||||||
|
|
||||||
AceEvent_registry[ALL_EVENTS][self] = method
|
|
||||||
end
|
|
||||||
|
|
||||||
local _G = getfenv(0)
|
|
||||||
local memstack, timestack = {}, {}
|
|
||||||
local memdiff, timediff
|
|
||||||
function AceEvent:TriggerEvent(event, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
|
||||||
AceEvent:argCheck(event, 2, "string")
|
|
||||||
local AceEvent_registry = AceEvent.registry
|
|
||||||
if (not AceEvent_registry[event] or not next(AceEvent_registry[event])) and (not AceEvent_registry[ALL_EVENTS] or not next(AceEvent_registry[ALL_EVENTS])) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local _G_event = _G.event
|
|
||||||
_G.event = event
|
|
||||||
|
|
||||||
local AceEvent_onceRegistry = AceEvent.onceRegistry
|
|
||||||
local AceEvent_debugTable = AceEvent.debugTable
|
|
||||||
if AceEvent_onceRegistry and AceEvent_onceRegistry[event] then
|
|
||||||
local tmp = new()
|
|
||||||
for obj, method in pairs(AceEvent_onceRegistry[event]) do
|
|
||||||
tmp[obj] = AceEvent_registry[event] and AceEvent_registry[event][obj] or nil
|
|
||||||
end
|
|
||||||
local obj = next(tmp)
|
|
||||||
while obj do
|
|
||||||
local mem, time
|
|
||||||
if AceEvent_debugTable then
|
|
||||||
if not AceEvent_debugTable[event] then
|
|
||||||
AceEvent_debugTable[event] = new()
|
|
||||||
end
|
|
||||||
if not AceEvent_debugTable[event][obj] then
|
|
||||||
AceEvent_debugTable[event][obj] = new()
|
|
||||||
AceEvent_debugTable[event][obj].mem = 0
|
|
||||||
AceEvent_debugTable[event][obj].time = 0
|
|
||||||
AceEvent_debugTable[event][obj].count = 0
|
|
||||||
end
|
|
||||||
if memdiff then
|
|
||||||
table.insert(memstack, memdiff)
|
|
||||||
table.insert(timestack, timediff)
|
|
||||||
end
|
|
||||||
memdiff, timediff = 0, 0
|
|
||||||
mem, time = gcinfo(), GetTime()
|
|
||||||
end
|
|
||||||
local method = tmp[obj]
|
|
||||||
AceEvent.UnregisterEvent(obj, event)
|
|
||||||
if type(method) == "string" then
|
|
||||||
local obj_method = obj[method]
|
|
||||||
if obj_method then
|
|
||||||
obj_method(obj, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
|
||||||
end
|
|
||||||
elseif method then -- function
|
|
||||||
method(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
|
||||||
end
|
|
||||||
if AceEvent_debugTable then
|
|
||||||
local dmem, dtime = memdiff, timediff
|
|
||||||
mem, time = gcinfo() - mem - memdiff, GetTime() - time - timediff
|
|
||||||
AceEvent_debugTable[event][obj].mem = AceEvent_debugTable[event][obj].mem + mem
|
|
||||||
AceEvent_debugTable[event][obj].time = AceEvent_debugTable[event][obj].time + time
|
|
||||||
AceEvent_debugTable[event][obj].count = AceEvent_debugTable[event][obj].count + 1
|
|
||||||
|
|
||||||
memdiff, timediff = table.remove(memstack), table.remove(timestack)
|
|
||||||
if memdiff then
|
|
||||||
memdiff = memdiff + mem + dmem
|
|
||||||
timediff = timediff + time + dtime
|
|
||||||
end
|
|
||||||
end
|
|
||||||
tmp[obj] = nil
|
|
||||||
obj = next(tmp)
|
|
||||||
end
|
|
||||||
del(tmp)
|
|
||||||
end
|
|
||||||
|
|
||||||
local AceEvent_throttleRegistry = AceEvent.throttleRegistry
|
|
||||||
local throttleTable = AceEvent_throttleRegistry and AceEvent_throttleRegistry[event]
|
|
||||||
if AceEvent_registry[event] then
|
|
||||||
local tmp = new()
|
|
||||||
for obj, method in pairs(AceEvent_registry[event]) do
|
|
||||||
tmp[obj] = method
|
|
||||||
end
|
|
||||||
local obj = next(tmp)
|
|
||||||
while obj do
|
|
||||||
local method = tmp[obj]
|
|
||||||
local continue = false
|
|
||||||
if throttleTable and throttleTable[obj] then
|
|
||||||
local a1 = a1
|
|
||||||
if a1 == nil then
|
|
||||||
a1 = FAKE_NIL
|
|
||||||
end
|
|
||||||
if not throttleTable[obj][a1] or GetTime() - throttleTable[obj][a1] >= throttleTable[obj][RATE] then
|
|
||||||
throttleTable[obj][a1] = GetTime()
|
|
||||||
else
|
|
||||||
continue = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if not continue then
|
|
||||||
local mem, time
|
|
||||||
if AceEvent_debugTable then
|
|
||||||
if not AceEvent_debugTable[event] then
|
|
||||||
AceEvent_debugTable[event] = new()
|
|
||||||
end
|
|
||||||
if not AceEvent_debugTable[event][obj] then
|
|
||||||
AceEvent_debugTable[event][obj] = new()
|
|
||||||
AceEvent_debugTable[event][obj].mem = 0
|
|
||||||
AceEvent_debugTable[event][obj].time = 0
|
|
||||||
AceEvent_debugTable[event][obj].count = 0
|
|
||||||
end
|
|
||||||
if memdiff then
|
|
||||||
table.insert(memstack, memdiff)
|
|
||||||
table.insert(timestack, timediff)
|
|
||||||
end
|
|
||||||
memdiff, timediff = 0, 0
|
|
||||||
mem, time = gcinfo(), GetTime()
|
|
||||||
end
|
|
||||||
if type(method) == "string" then
|
|
||||||
local obj_method = obj[method]
|
|
||||||
if obj_method then
|
|
||||||
obj_method(obj, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
|
||||||
end
|
|
||||||
elseif method then -- function
|
|
||||||
method(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
|
||||||
end
|
|
||||||
if AceEvent_debugTable then
|
|
||||||
local dmem, dtime = memdiff, timediff
|
|
||||||
mem, time = gcinfo() - mem - memdiff, GetTime() - time - timediff
|
|
||||||
AceEvent_debugTable[event][obj].mem = AceEvent_debugTable[event][obj].mem + mem
|
|
||||||
AceEvent_debugTable[event][obj].time = AceEvent_debugTable[event][obj].time + time
|
|
||||||
AceEvent_debugTable[event][obj].count = AceEvent_debugTable[event][obj].count + 1
|
|
||||||
|
|
||||||
memdiff, timediff = table.remove(memstack), table.remove(timestack)
|
|
||||||
if memdiff then
|
|
||||||
memdiff = memdiff + mem + dmem
|
|
||||||
timediff = timediff + time + dtime
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
tmp[obj] = nil
|
|
||||||
obj = next(tmp)
|
|
||||||
end
|
|
||||||
del(tmp)
|
|
||||||
end
|
|
||||||
if AceEvent_registry[ALL_EVENTS] then
|
|
||||||
local tmp = new()
|
|
||||||
for obj, method in pairs(AceEvent_registry[ALL_EVENTS]) do
|
|
||||||
tmp[obj] = method
|
|
||||||
end
|
|
||||||
local obj = next(tmp)
|
|
||||||
while obj do
|
|
||||||
local method = tmp[obj]
|
|
||||||
local mem, time
|
|
||||||
if AceEvent_debugTable then
|
|
||||||
if not AceEvent_debugTable[event] then
|
|
||||||
AceEvent_debugTable[event] = new()
|
|
||||||
end
|
|
||||||
if not AceEvent_debugTable[event][obj] then
|
|
||||||
AceEvent_debugTable[event][obj] = new()
|
|
||||||
AceEvent_debugTable[event][obj].mem = 0
|
|
||||||
AceEvent_debugTable[event][obj].time = 0
|
|
||||||
AceEvent_debugTable[event][obj].count = 0
|
|
||||||
end
|
|
||||||
if memdiff then
|
|
||||||
table.insert(memstack, memdiff)
|
|
||||||
table.insert(timestack, timediff)
|
|
||||||
end
|
|
||||||
memdiff, timediff = 0, 0
|
|
||||||
mem, time = gcinfo(), GetTime()
|
|
||||||
end
|
|
||||||
if type(method) == "string" then
|
|
||||||
local obj_method = obj[method]
|
|
||||||
if obj_method then
|
|
||||||
obj_method(obj, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
|
||||||
end
|
|
||||||
elseif method then -- function
|
|
||||||
method(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
|
||||||
end
|
|
||||||
if AceEvent_debugTable then
|
|
||||||
local dmem, dtime = memdiff, timediff
|
|
||||||
mem, time = gcinfo() - mem - memdiff, GetTime() - time - timediff
|
|
||||||
AceEvent_debugTable[event][obj].mem = AceEvent_debugTable[event][obj].mem + mem
|
|
||||||
AceEvent_debugTable[event][obj].time = AceEvent_debugTable[event][obj].time + time
|
|
||||||
AceEvent_debugTable[event][obj].count = AceEvent_debugTable[event][obj].count + 1
|
|
||||||
|
|
||||||
memdiff, timediff = table.remove(memstack), table.remove(timestack)
|
|
||||||
if memdiff then
|
|
||||||
memdiff = memdiff + mem + dmem
|
|
||||||
timediff = timediff + time + dtime
|
|
||||||
end
|
|
||||||
end
|
|
||||||
tmp[obj] = nil
|
|
||||||
obj = next(tmp)
|
|
||||||
end
|
|
||||||
del(tmp)
|
|
||||||
end
|
|
||||||
_G.event = _G_event
|
|
||||||
end
|
|
||||||
|
|
||||||
-- local accessors
|
|
||||||
local getn = table.getn
|
|
||||||
local tinsert = table.insert
|
|
||||||
local tremove = table.remove
|
|
||||||
local floor = math.floor
|
|
||||||
local GetTime = GetTime
|
|
||||||
local next = next
|
|
||||||
local pairs = pairs
|
|
||||||
local unpack = unpack
|
|
||||||
|
|
||||||
local delayRegistry
|
|
||||||
local function OnUpdate()
|
|
||||||
local t = GetTime()
|
|
||||||
local k,v = next(delayRegistry)
|
|
||||||
local last = nil
|
|
||||||
while k do
|
|
||||||
local v_time = v.time
|
|
||||||
if not v_time then
|
|
||||||
delayRegistry[k] = del(v)
|
|
||||||
elseif v_time <= t then
|
|
||||||
local v_repeatDelay = v.repeatDelay
|
|
||||||
if v_repeatDelay then
|
|
||||||
-- use the event time, not the current time, else timing inaccuracies add up over time
|
|
||||||
v.time = v_time + v_repeatDelay
|
|
||||||
end
|
|
||||||
local event = v.event
|
|
||||||
local mem, time
|
|
||||||
if AceEvent_debugTable then
|
|
||||||
mem, time = gcinfo(), GetTime()
|
|
||||||
end
|
|
||||||
if type(event) == "function" then
|
|
||||||
event(unpack(v))
|
|
||||||
else
|
|
||||||
AceEvent:TriggerEvent(event, unpack(v))
|
|
||||||
end
|
|
||||||
if AceEvent_debugTable then
|
|
||||||
mem, time = gcinfo() - mem, GetTime() - time
|
|
||||||
v.mem = v.mem + mem
|
|
||||||
v.timeSpent = v.timeSpent + time
|
|
||||||
v.count = v.count + 1
|
|
||||||
end
|
|
||||||
if not v_repeatDelay then
|
|
||||||
local x = delayRegistry[k]
|
|
||||||
if x and x.time == v_time then -- check if it was manually reset
|
|
||||||
delayRegistry[k] = del(v)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if delayRegistry[k] then
|
|
||||||
last = k
|
|
||||||
end
|
|
||||||
k,v = next(delayRegistry, last)
|
|
||||||
end
|
|
||||||
if not next(delayRegistry) then
|
|
||||||
AceEvent.frame:Hide()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function ScheduleEvent(self, repeating, event, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
|
||||||
local id
|
|
||||||
if type(event) == "string" or type(event) == "table" then
|
|
||||||
if type(event) == "table" then
|
|
||||||
if not delayRegistry or not delayRegistry[event] then
|
|
||||||
AceEvent:error("Bad argument #2 to `ScheduleEvent'. Improper id table fed in.")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if type(delay) ~= "number" then
|
|
||||||
id, event, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20 = event, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20
|
|
||||||
AceEvent:argCheck(event, 3, "string", "function", --[[ so message is right ]] "number")
|
|
||||||
AceEvent:argCheck(delay, 4, "number")
|
|
||||||
self:CancelScheduledEvent(id)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
AceEvent:argCheck(event, 2, "string", "function")
|
|
||||||
AceEvent:argCheck(delay, 3, "number")
|
|
||||||
end
|
|
||||||
|
|
||||||
if not delayRegistry then
|
|
||||||
AceEvent.delayRegistry = new()
|
|
||||||
delayRegistry = AceEvent.delayRegistry
|
|
||||||
AceEvent.frame:SetScript("OnUpdate", OnUpdate)
|
|
||||||
end
|
|
||||||
local t
|
|
||||||
if type(id) == "table" then
|
|
||||||
for k in pairs(id) do
|
|
||||||
id[k] = nil
|
|
||||||
end
|
|
||||||
t = id
|
|
||||||
else
|
|
||||||
t = new()
|
|
||||||
end
|
|
||||||
t[1] = a1
|
|
||||||
t[2] = a2
|
|
||||||
t[3] = a3
|
|
||||||
t[4] = a4
|
|
||||||
t[5] = a5
|
|
||||||
t[6] = a6
|
|
||||||
t[7] = a7
|
|
||||||
t[8] = a8
|
|
||||||
t[9] = a9
|
|
||||||
t[10] = a10
|
|
||||||
t[11] = a11
|
|
||||||
t[12] = a12
|
|
||||||
t[13] = a13
|
|
||||||
t[14] = a14
|
|
||||||
t[15] = a15
|
|
||||||
t[16] = a16
|
|
||||||
t[17] = a17
|
|
||||||
t[18] = a18
|
|
||||||
t[19] = a19
|
|
||||||
t[20] = a20
|
|
||||||
table_setn(t, 20)
|
|
||||||
t.event = event
|
|
||||||
t.time = GetTime() + delay
|
|
||||||
t.self = self
|
|
||||||
t.id = id or t
|
|
||||||
t.repeatDelay = repeating and delay
|
|
||||||
if AceEvent_debugTable then
|
|
||||||
t.mem = 0
|
|
||||||
t.count = 0
|
|
||||||
t.timeSpent = 0
|
|
||||||
end
|
|
||||||
delayRegistry[t.id] = t
|
|
||||||
AceEvent.frame:Show()
|
|
||||||
return t.id
|
|
||||||
end
|
|
||||||
|
|
||||||
function AceEvent:ScheduleEvent(event, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
|
||||||
if type(event) == "string" or type(event) == "table" then
|
|
||||||
if type(event) == "table" then
|
|
||||||
if not delayRegistry or not delayRegistry[event] then
|
|
||||||
AceEvent:error("Bad argument #2 to `ScheduleEvent'. Improper id table fed in.")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if type(delay) ~= "number" then
|
|
||||||
AceEvent:argCheck(delay, 3, "string", "function", --[[ so message is right ]] "number")
|
|
||||||
AceEvent:argCheck(a1, 4, "number")
|
|
||||||
end
|
|
||||||
else
|
|
||||||
AceEvent:argCheck(event, 2, "string", "function")
|
|
||||||
AceEvent:argCheck(delay, 3, "number")
|
|
||||||
end
|
|
||||||
|
|
||||||
return ScheduleEvent(self, false, event, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
|
||||||
end
|
|
||||||
|
|
||||||
function AceEvent:ScheduleRepeatingEvent(event, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
|
||||||
if type(event) == "string" or type(event) == "table" then
|
|
||||||
if type(event) == "table" then
|
|
||||||
if not delayRegistry or not delayRegistry[event] then
|
|
||||||
AceEvent:error("Bad argument #2 to `ScheduleEvent'. Improper id table fed in.")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if type(delay) ~= "number" then
|
|
||||||
AceEvent:argCheck(delay, 3, "string", "function", --[[ so message is right ]] "number")
|
|
||||||
AceEvent:argCheck(a1, 4, "number")
|
|
||||||
end
|
|
||||||
else
|
|
||||||
AceEvent:argCheck(event, 2, "string", "function")
|
|
||||||
AceEvent:argCheck(delay, 3, "number")
|
|
||||||
end
|
|
||||||
|
|
||||||
return ScheduleEvent(self, true, event, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
|
||||||
end
|
|
||||||
|
|
||||||
function AceEvent:CancelScheduledEvent(t)
|
|
||||||
AceEvent:argCheck(t, 2, "string", "table")
|
|
||||||
if delayRegistry then
|
|
||||||
local v = delayRegistry[t]
|
|
||||||
if v then
|
|
||||||
delayRegistry[t] = del(v)
|
|
||||||
if not next(delayRegistry) then
|
|
||||||
AceEvent.frame:Hide()
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
|
|
||||||
function AceEvent:IsEventScheduled(t)
|
|
||||||
AceEvent:argCheck(t, 2, "string", "table")
|
|
||||||
if delayRegistry then
|
|
||||||
local v = delayRegistry[t]
|
|
||||||
if v then
|
|
||||||
return true, v.time - GetTime()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return false, nil
|
|
||||||
end
|
|
||||||
|
|
||||||
function AceEvent:UnregisterEvent(event)
|
|
||||||
AceEvent:argCheck(event, 2, "string")
|
|
||||||
local AceEvent_registry = AceEvent.registry
|
|
||||||
if AceEvent_registry[event] and AceEvent_registry[event][self] then
|
|
||||||
AceEvent_registry[event][self] = nil
|
|
||||||
local AceEvent_onceRegistry = AceEvent.onceRegistry
|
|
||||||
if AceEvent_onceRegistry and AceEvent_onceRegistry[event] and AceEvent_onceRegistry[event][self] then
|
|
||||||
AceEvent_onceRegistry[event][self] = nil
|
|
||||||
if not next(AceEvent_onceRegistry[event]) then
|
|
||||||
AceEvent_onceRegistry[event] = del(AceEvent_onceRegistry[event])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local AceEvent_throttleRegistry = AceEvent.throttleRegistry
|
|
||||||
if AceEvent_throttleRegistry and AceEvent_throttleRegistry[event] and AceEvent_throttleRegistry[event][self] then
|
|
||||||
AceEvent_throttleRegistry[event][self] = del(AceEvent_throttleRegistry[event][self])
|
|
||||||
if not next(AceEvent_throttleRegistry[event]) then
|
|
||||||
AceEvent_throttleRegistry[event] = del(AceEvent_throttleRegistry[event])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if not next(AceEvent_registry[event]) then
|
|
||||||
AceEvent_registry[event] = del(AceEvent_registry[event])
|
|
||||||
if not AceEvent_registry[ALL_EVENTS] or not next(AceEvent_registry[ALL_EVENTS]) then
|
|
||||||
AceEvent.frame:UnregisterEvent(event)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if self == AceEvent then
|
|
||||||
error(string.format("Cannot unregister event %q. Improperly unregistering from AceEvent-2.0.", event), 2)
|
|
||||||
else
|
|
||||||
AceEvent:error("Cannot unregister event %q. %q is not registered with it.", event, self)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
AceEvent:TriggerEvent("AceEvent_EventUnregistered", self, event)
|
|
||||||
end
|
|
||||||
|
|
||||||
function AceEvent:UnregisterAllEvents()
|
|
||||||
local AceEvent_registry = AceEvent.registry
|
|
||||||
if AceEvent_registry[ALL_EVENTS] and AceEvent_registry[ALL_EVENTS][self] then
|
|
||||||
AceEvent_registry[ALL_EVENTS][self] = nil
|
|
||||||
if not next(AceEvent_registry[ALL_EVENTS]) then
|
|
||||||
del(AceEvent_registry[ALL_EVENTS])
|
|
||||||
AceEvent.frame:UnregisterAllEvents()
|
|
||||||
for k,v in pairs(AceEvent_registry) do
|
|
||||||
if k ~= ALL_EVENTS then
|
|
||||||
AceEvent.frame:RegisterEvent(k)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
AceEvent_registry[event] = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local first = true
|
|
||||||
for event, data in pairs(AceEvent_registry) do
|
|
||||||
if first then
|
|
||||||
if AceEvent_registry.AceEvent_EventUnregistered then
|
|
||||||
event = "AceEvent_EventUnregistered"
|
|
||||||
else
|
|
||||||
first = false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local x = data[self]
|
|
||||||
data[self] = nil
|
|
||||||
if x and event ~= ALL_EVENTS then
|
|
||||||
if not next(data) then
|
|
||||||
del(data)
|
|
||||||
if not AceEvent_registry[ALL_EVENTS] or not next(AceEvent_registry[ALL_EVENTS]) then
|
|
||||||
AceEvent.frame:UnregisterEvent(event)
|
|
||||||
end
|
|
||||||
AceEvent_registry[event] = nil
|
|
||||||
end
|
|
||||||
AceEvent:TriggerEvent("AceEvent_EventUnregistered", self, event)
|
|
||||||
end
|
|
||||||
if first then
|
|
||||||
event = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if AceEvent.onceRegistry then
|
|
||||||
for event, data in pairs(AceEvent.onceRegistry) do
|
|
||||||
data[self] = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function AceEvent:CancelAllScheduledEvents()
|
|
||||||
if delayRegistry then
|
|
||||||
for k,v in pairs(delayRegistry) do
|
|
||||||
if v.self == self then
|
|
||||||
delayRegistry[k] = del(v)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if not next(delayRegistry) then
|
|
||||||
AceEvent.frame:Hide()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function AceEvent:IsEventRegistered(event)
|
|
||||||
AceEvent:argCheck(event, 2, "string")
|
|
||||||
local AceEvent_registry = AceEvent.registry
|
|
||||||
if self == AceEvent then
|
|
||||||
return AceEvent_registry[event] and next(AceEvent_registry[event]) and true or false
|
|
||||||
end
|
|
||||||
if AceEvent_registry[event] and AceEvent_registry[event][self] then
|
|
||||||
return true, AceEvent_registry[event][self]
|
|
||||||
end
|
|
||||||
return false, nil
|
|
||||||
end
|
|
||||||
|
|
||||||
local bucketfunc
|
|
||||||
function AceEvent:RegisterBucketEvent(event, delay, method)
|
|
||||||
AceEvent:argCheck(event, 2, "string", "table")
|
|
||||||
if type(event) == "table" then
|
|
||||||
for k,v in pairs(event) do
|
|
||||||
if type(k) ~= "number" then
|
|
||||||
AceEvent:error("All keys to argument #2 to `RegisterBucketEvent' must be numbers.")
|
|
||||||
elseif type(v) ~= "string" then
|
|
||||||
AceEvent:error("All values to argument #2 to `RegisterBucketEvent' must be strings.")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
AceEvent:argCheck(delay, 3, "number")
|
|
||||||
if AceEvent == self then
|
|
||||||
AceEvent:argCheck(method, 4, "function")
|
|
||||||
self = method
|
|
||||||
else
|
|
||||||
if type(event) == "string" then
|
|
||||||
AceEvent:argCheck(method, 4, "string", "function", "nil")
|
|
||||||
if not method then
|
|
||||||
method = event
|
|
||||||
end
|
|
||||||
else
|
|
||||||
AceEvent:argCheck(method, 4, "string", "function")
|
|
||||||
end
|
|
||||||
|
|
||||||
if type(method) == "string" and type(self[method]) ~= "function" then
|
|
||||||
AceEvent:error("Cannot register event %q to method %q, it does not exist", event, method)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if not AceEvent.buckets then
|
|
||||||
AceEvent.buckets = new()
|
|
||||||
end
|
|
||||||
if not AceEvent.buckets[event] then
|
|
||||||
AceEvent.buckets[event] = new()
|
|
||||||
end
|
|
||||||
if not AceEvent.buckets[event][self] then
|
|
||||||
AceEvent.buckets[event][self] = new()
|
|
||||||
AceEvent.buckets[event][self].current = new()
|
|
||||||
AceEvent.buckets[event][self].self = self
|
|
||||||
else
|
|
||||||
AceEvent.CancelScheduledEvent(self, AceEvent.buckets[event][self].id)
|
|
||||||
end
|
|
||||||
local bucket = AceEvent.buckets[event][self]
|
|
||||||
bucket.method = method
|
|
||||||
|
|
||||||
local func = function(arg1)
|
|
||||||
bucket.run = true
|
|
||||||
if arg1 then
|
|
||||||
bucket.current[arg1] = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
AceEvent.buckets[event][self].func = func
|
|
||||||
if type(event) == "string" then
|
|
||||||
AceEvent.RegisterEvent(self, event, func)
|
|
||||||
else
|
|
||||||
for _,v in ipairs(event) do
|
|
||||||
AceEvent.RegisterEvent(self, v, func)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if not bucketfunc then
|
|
||||||
bucketfunc = function(bucket)
|
|
||||||
local current = bucket.current
|
|
||||||
local method = bucket.method
|
|
||||||
local self = bucket.self
|
|
||||||
if bucket.run then
|
|
||||||
if type(method) == "string" then
|
|
||||||
self[method](self, current)
|
|
||||||
elseif method then -- function
|
|
||||||
method(current)
|
|
||||||
end
|
|
||||||
for k in pairs(current) do
|
|
||||||
current[k] = nil
|
|
||||||
k = nil
|
|
||||||
end
|
|
||||||
bucket.run = false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
bucket.id = AceEvent.ScheduleRepeatingEvent(self, bucketfunc, delay, bucket)
|
|
||||||
end
|
|
||||||
|
|
||||||
function AceEvent:IsBucketEventRegistered(event)
|
|
||||||
AceEvent:argCheck(event, 2, "string", "table")
|
|
||||||
return AceEvent.buckets and AceEvent.buckets[event] and AceEvent.buckets[event][self]
|
|
||||||
end
|
|
||||||
|
|
||||||
function AceEvent:UnregisterBucketEvent(event)
|
|
||||||
AceEvent:argCheck(event, 2, "string", "table")
|
|
||||||
if not AceEvent.buckets or not AceEvent.buckets[event] or not AceEvent.buckets[event][self] then
|
|
||||||
AceEvent:error("Cannot unregister bucket event %q. %q is not registered with it.", event, self)
|
|
||||||
end
|
|
||||||
|
|
||||||
local bucket = AceEvent.buckets[event][self]
|
|
||||||
|
|
||||||
if type(event) == "string" then
|
|
||||||
AceEvent.UnregisterEvent(bucket.func, event)
|
|
||||||
else
|
|
||||||
for _,v in ipairs(event) do
|
|
||||||
AceEvent.UnregisterEvent(bucket.func, v)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
AceEvent:CancelScheduledEvent(bucket.id)
|
|
||||||
|
|
||||||
del(bucket.current)
|
|
||||||
AceEvent.buckets[event][self] = del(AceEvent.buckets[event][self])
|
|
||||||
if not next(AceEvent.buckets[event]) then
|
|
||||||
AceEvent.buckets[event] = del(AceEvent.buckets[event])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function AceEvent:UnregisterAllBucketEvents()
|
|
||||||
if not AceEvent.buckets or not next(AceEvent.buckets) then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
for k,v in pairs(AceEvent.buckets) do
|
|
||||||
if v == self then
|
|
||||||
AceEvent.UnregisterBucketEvent(self, k)
|
|
||||||
k = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function AceEvent:OnEmbedDisable(target)
|
|
||||||
self.UnregisterAllEvents(target)
|
|
||||||
|
|
||||||
self.CancelAllScheduledEvents(target)
|
|
||||||
|
|
||||||
self.UnregisterAllBucketEvents(target)
|
|
||||||
end
|
|
||||||
|
|
||||||
function AceEvent:EnableDebugging()
|
|
||||||
if not self.debugTable then
|
|
||||||
self.debugTable = new()
|
|
||||||
|
|
||||||
if delayRegistry then
|
|
||||||
for k,v in pairs(self.delayRegistry) do
|
|
||||||
if not v.mem then
|
|
||||||
v.mem = 0
|
|
||||||
v.count = 0
|
|
||||||
v.timeSpent = 0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function AceEvent:IsFullyInitialized()
|
|
||||||
return self.postInit or false
|
|
||||||
end
|
|
||||||
|
|
||||||
function AceEvent:IsPostPlayerLogin()
|
|
||||||
return self.playerLogin or false
|
|
||||||
end
|
|
||||||
|
|
||||||
function AceEvent:activate(oldLib, oldDeactivate)
|
|
||||||
AceEvent = self
|
|
||||||
|
|
||||||
if oldLib then
|
|
||||||
self.onceRegistry = oldLib.onceRegistry
|
|
||||||
self.throttleRegistry = oldLib.throttleRegistry
|
|
||||||
self.delayRegistry = oldLib.delayRegistry
|
|
||||||
self.buckets = oldLib.buckets
|
|
||||||
self.registry = oldLib.registry
|
|
||||||
self.frame = oldLib.frame
|
|
||||||
self.debugTable = oldLib.debugTable
|
|
||||||
self.playerLogin = oldLib.pew or DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.defaultLanguage and true
|
|
||||||
self.postInit = oldLib.postInit or self.playerLogin and ChatTypeInfo and ChatTypeInfo.WHISPER and ChatTypeInfo.WHISPER.r and true
|
|
||||||
self.ALL_EVENTS = oldLib.ALL_EVENTS
|
|
||||||
self.FAKE_NIL = oldLib.FAKE_NIL
|
|
||||||
self.RATE = oldLib.RATE
|
|
||||||
end
|
|
||||||
if not self.registry then
|
|
||||||
self.registry = {}
|
|
||||||
end
|
|
||||||
if not self.frame then
|
|
||||||
self.frame = CreateFrame("Frame", "AceEvent20Frame")
|
|
||||||
end
|
|
||||||
if not self.ALL_EVENTS then
|
|
||||||
self.ALL_EVENTS = {}
|
|
||||||
end
|
|
||||||
if not self.FAKE_NIL then
|
|
||||||
self.FAKE_NIL = {}
|
|
||||||
end
|
|
||||||
if not self.RATE then
|
|
||||||
self.RATE = {}
|
|
||||||
end
|
|
||||||
ALL_EVENTS = self.ALL_EVENTS
|
|
||||||
FAKE_NIL = self.FAKE_NIL
|
|
||||||
RATE = self.RATE
|
|
||||||
local inPlw = false
|
|
||||||
local blacklist = {
|
|
||||||
UNIT_INVENTORY_CHANGED = true,
|
|
||||||
BAG_UPDATE = true,
|
|
||||||
ITEM_LOCK_CHANGED = true,
|
|
||||||
ACTIONBAR_SLOT_CHANGED = true,
|
|
||||||
}
|
|
||||||
self.frame:SetScript("OnEvent", function()
|
|
||||||
local event = event
|
|
||||||
if event == "PLAYER_ENTERING_WORLD" then
|
|
||||||
inPlw = false
|
|
||||||
elseif event == "PLAYER_LEAVING_WORLD" then
|
|
||||||
inPlw = true
|
|
||||||
end
|
|
||||||
if event and (not inPlw or not blacklist[event]) then
|
|
||||||
self:TriggerEvent(event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
if self.delayRegistry then
|
|
||||||
delayRegistry = self.delayRegistry
|
|
||||||
self.frame:SetScript("OnUpdate", OnUpdate)
|
|
||||||
end
|
|
||||||
|
|
||||||
self:UnregisterAllEvents()
|
|
||||||
self:CancelAllScheduledEvents()
|
|
||||||
|
|
||||||
if not self.playerLogin then
|
|
||||||
registeringFromAceEvent = true
|
|
||||||
self:RegisterEvent("PLAYER_LOGIN", function()
|
|
||||||
self.playerLogin = true
|
|
||||||
end, true)
|
|
||||||
registeringFromAceEvent = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
if not self.postInit then
|
|
||||||
local isReload = true
|
|
||||||
local function func()
|
|
||||||
self.postInit = true
|
|
||||||
self:TriggerEvent("AceEvent_FullyInitialized")
|
|
||||||
if self.registry["CHAT_MSG_CHANNEL_NOTICE"] and self.registry["CHAT_MSG_CHANNEL_NOTICE"][self] then
|
|
||||||
self:UnregisterEvent("CHAT_MSG_CHANNEL_NOTICE")
|
|
||||||
end
|
|
||||||
if self.registry["MEETINGSTONE_CHANGED"] and self.registry["MEETINGSTONE_CHANGED"][self] then
|
|
||||||
self:UnregisterEvent("MEETINGSTONE_CHANGED")
|
|
||||||
end
|
|
||||||
if self.registry["MINIMAP_ZONE_CHANGED"] and self.registry["MINIMAP_ZONE_CHANGED"][self] then
|
|
||||||
self:UnregisterEvent("MINIMAP_ZONE_CHANGED")
|
|
||||||
end
|
|
||||||
if self.registry["LANGUAGE_LIST_CHANGED"] and self.registry["LANGUAGE_LIST_CHANGED"][self] then
|
|
||||||
self:UnregisterEvent("LANGUAGE_LIST_CHANGED")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
registeringFromAceEvent = true
|
|
||||||
local f = function()
|
|
||||||
self.playerLogin = true
|
|
||||||
self:ScheduleEvent("AceEvent_FullyInitialized", func, 1)
|
|
||||||
end
|
|
||||||
self:RegisterEvent("MEETINGSTONE_CHANGED", f, true)
|
|
||||||
self:RegisterEvent("CHAT_MSG_CHANNEL_NOTICE", function()
|
|
||||||
self:ScheduleEvent("AceEvent_FullyInitialized", func, 0.05)
|
|
||||||
end)
|
|
||||||
self:RegisterEvent("LANGUAGE_LIST_CHANGED", function()
|
|
||||||
if self.registry["MEETINGSTONE_CHANGED"] and self.registry["MEETINGSTONE_CHANGED"][self] then
|
|
||||||
self:UnregisterEvent("MEETINGSTONE_CHANGED")
|
|
||||||
self:RegisterEvent("MINIMAP_ZONE_CHANGED", f, true)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
registeringFromAceEvent = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
self.super.activate(self, oldLib, oldDeactivate)
|
|
||||||
if oldLib then
|
|
||||||
oldDeactivate(oldLib)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
AceLibrary:Register(AceEvent, MAJOR_VERSION, MINOR_VERSION, AceEvent.activate)
|
|
||||||
AceEvent = AceLibrary(MAJOR_VERSION)
|
|
||||||
@@ -1,572 +0,0 @@
|
|||||||
--[[
|
|
||||||
Name: AceHook-2.0
|
|
||||||
Revision: $Rev: 11577 $
|
|
||||||
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: 11577 $"
|
|
||||||
|
|
||||||
-- 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",
|
|
||||||
}
|
|
||||||
|
|
||||||
local table_setn
|
|
||||||
do
|
|
||||||
local version = GetBuildInfo()
|
|
||||||
if string.find(version, "^2%.") then
|
|
||||||
-- 2.0.0
|
|
||||||
table_setn = function() end
|
|
||||||
else
|
|
||||||
table_setn = table.setn
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--[[---------------------------------------------------------------------------------
|
|
||||||
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)
|
|
||||||
@@ -1,568 +0,0 @@
|
|||||||
--[[
|
|
||||||
Name: AceHook-2.1
|
|
||||||
Revision: $Rev: 15485 $
|
|
||||||
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: 15485 $"
|
|
||||||
|
|
||||||
-- 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",
|
|
||||||
"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][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 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(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: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)
|
|
||||||
@@ -1,723 +0,0 @@
|
|||||||
--[[
|
|
||||||
Name: AceLibrary
|
|
||||||
Revision: $Rev: 11612 $
|
|
||||||
Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team)
|
|
||||||
Inspired By: Iriel (iriel@vigilance-committee.org)
|
|
||||||
Tekkub (tekkub@gmail.com)
|
|
||||||
Revision: $Rev: 11612 $
|
|
||||||
Website: http://www.wowace.com/
|
|
||||||
Documentation: http://www.wowace.com/index.php/AceLibrary
|
|
||||||
SVN: http://svn.wowace.com/root/trunk/Ace2/AceLibrary
|
|
||||||
Description: Versioning library to handle other library instances, upgrading,
|
|
||||||
and proper access.
|
|
||||||
It also provides a base for libraries to work off of, providing
|
|
||||||
proper error tools. It is handy because all the errors occur in the
|
|
||||||
file that called it, not in the library file itself.
|
|
||||||
Dependencies: None
|
|
||||||
]]
|
|
||||||
|
|
||||||
local ACELIBRARY_MAJOR = "AceLibrary"
|
|
||||||
local ACELIBRARY_MINOR = "$Revision: 11612 $"
|
|
||||||
|
|
||||||
-- CHANGE DEBUG TO ``false`` ON RELEASE -------------------
|
|
||||||
local DEBUG = true
|
|
||||||
-- CHANGE DEBUG TO ``false`` ON RELEASE -------------------
|
|
||||||
|
|
||||||
local table_setn
|
|
||||||
do
|
|
||||||
local version = GetBuildInfo()
|
|
||||||
if string.find(version, "^2%.") then
|
|
||||||
-- 2.0.0
|
|
||||||
table_setn = function() end
|
|
||||||
else
|
|
||||||
table_setn = table.setn
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local string_gfind = string.gmatch or string.gfind
|
|
||||||
|
|
||||||
local _G = getfenv(0)
|
|
||||||
local previous = _G[ACELIBRARY_MAJOR]
|
|
||||||
if previous and not previous:IsNewVersion(ACELIBRARY_MAJOR, ACELIBRARY_MINOR) then return end
|
|
||||||
|
|
||||||
-- @table AceLibrary
|
|
||||||
-- @brief System to handle all versioning of libraries.
|
|
||||||
local AceLibrary = {}
|
|
||||||
local AceLibrary_mt = {}
|
|
||||||
setmetatable(AceLibrary, AceLibrary_mt)
|
|
||||||
|
|
||||||
local tmp
|
|
||||||
local function error(self, message, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
|
||||||
if type(self) ~= "table" then
|
|
||||||
_G.error(string.format("Bad argument #1 to `error' (table expected, got %s)", type(self)), 2)
|
|
||||||
end
|
|
||||||
if not tmp then
|
|
||||||
tmp = {}
|
|
||||||
else
|
|
||||||
for k in pairs(tmp) do tmp[k] = nil end
|
|
||||||
table_setn(tmp, 0)
|
|
||||||
end
|
|
||||||
|
|
||||||
table.insert(tmp, a1)
|
|
||||||
table.insert(tmp, a2)
|
|
||||||
table.insert(tmp, a3)
|
|
||||||
table.insert(tmp, a4)
|
|
||||||
table.insert(tmp, a5)
|
|
||||||
table.insert(tmp, a6)
|
|
||||||
table.insert(tmp, a7)
|
|
||||||
table.insert(tmp, a8)
|
|
||||||
table.insert(tmp, a9)
|
|
||||||
table.insert(tmp, a10)
|
|
||||||
table.insert(tmp, a11)
|
|
||||||
table.insert(tmp, a12)
|
|
||||||
table.insert(tmp, a13)
|
|
||||||
table.insert(tmp, a14)
|
|
||||||
table.insert(tmp, a15)
|
|
||||||
table.insert(tmp, a16)
|
|
||||||
table.insert(tmp, a17)
|
|
||||||
table.insert(tmp, a18)
|
|
||||||
table.insert(tmp, a19)
|
|
||||||
table.insert(tmp, a20)
|
|
||||||
|
|
||||||
local stack = debugstack()
|
|
||||||
if not message then
|
|
||||||
local _,_,second = string.find(stack, "\n(.-)\n")
|
|
||||||
message = "error raised! " .. second
|
|
||||||
else
|
|
||||||
for i = 1,table.getn(tmp) do
|
|
||||||
tmp[i] = tostring(tmp[i])
|
|
||||||
end
|
|
||||||
for i = 1,10 do
|
|
||||||
table.insert(tmp, "nil")
|
|
||||||
end
|
|
||||||
message = string.format(message, unpack(tmp))
|
|
||||||
end
|
|
||||||
|
|
||||||
if getmetatable(self) and getmetatable(self).__tostring then
|
|
||||||
message = string.format("%s: %s", tostring(self), message)
|
|
||||||
elseif type(rawget(self, 'GetLibraryVersion')) == "function" and AceLibrary:HasInstance(self:GetLibraryVersion()) then
|
|
||||||
message = string.format("%s: %s", self:GetLibraryVersion(), message)
|
|
||||||
elseif type(rawget(self, 'class')) == "table" and type(rawget(self.class, 'GetLibraryVersion')) == "function" and AceLibrary:HasInstance(self.class:GetLibraryVersion()) then
|
|
||||||
message = string.format("%s: %s", self.class:GetLibraryVersion(), message)
|
|
||||||
end
|
|
||||||
|
|
||||||
local first = string.gsub(stack, "\n.*", "")
|
|
||||||
local file = string.gsub(first, ".*\\(.*).lua:%d+: .*", "%1")
|
|
||||||
file = string.gsub(file, "([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1")
|
|
||||||
|
|
||||||
local i = 0
|
|
||||||
for s in string_gfind(stack, "\n([^\n]*)") do
|
|
||||||
i = i + 1
|
|
||||||
if not string.find(s, file .. "%.lua:%d+:") then
|
|
||||||
file = string.gsub(s, "^.*\\(.*).lua:%d+: .*", "%1")
|
|
||||||
file = string.gsub(file, "([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1")
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local j = 0
|
|
||||||
for s in string_gfind(stack, "\n([^\n]*)") do
|
|
||||||
j = j + 1
|
|
||||||
if j > i and not string.find(s, file .. "%.lua:%d+:") then
|
|
||||||
_G.error(message, j + 1)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
_G.error(message, 2)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local function assert(self, condition, message, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
|
||||||
if not condition then
|
|
||||||
if not message then
|
|
||||||
local stack = debugstack()
|
|
||||||
local _,_,second = string.find(stack, "\n(.-)\n")
|
|
||||||
message = "assertion failed! " .. second
|
|
||||||
end
|
|
||||||
error(self, message, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
return condition
|
|
||||||
end
|
|
||||||
|
|
||||||
local function argCheck(self, arg, num, kind, kind2, kind3, kind4, kind5)
|
|
||||||
if type(num) ~= "number" then
|
|
||||||
error(self, "Bad argument #3 to `argCheck' (number expected, got %s)", type(num))
|
|
||||||
elseif type(kind) ~= "string" then
|
|
||||||
error(self, "Bad argument #4 to `argCheck' (string expected, got %s)", type(kind))
|
|
||||||
end
|
|
||||||
local errored = false
|
|
||||||
arg = type(arg)
|
|
||||||
if arg ~= kind and arg ~= kind2 and arg ~= kind3 and arg ~= kind4 and arg ~= kind5 then
|
|
||||||
local _,_,func = string.find(debugstack(), "`argCheck'.-([`<].-['>])")
|
|
||||||
if not func then
|
|
||||||
_,_,func = string.find(debugstack(), "([`<].-['>])")
|
|
||||||
end
|
|
||||||
if kind5 then
|
|
||||||
error(self, "Bad argument #%s to %s (%s, %s, %s, %s, or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, kind3, kind4, kind5, arg)
|
|
||||||
elseif kind4 then
|
|
||||||
error(self, "Bad argument #%s to %s (%s, %s, %s, or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, kind3, kind4, arg)
|
|
||||||
elseif kind3 then
|
|
||||||
error(self, "Bad argument #%s to %s (%s, %s, or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, kind3, arg)
|
|
||||||
elseif kind2 then
|
|
||||||
error(self, "Bad argument #%s to %s (%s or %s expected, got %s)", tonumber(num) or 0/0, func, kind, kind2, arg)
|
|
||||||
else
|
|
||||||
error(self, "Bad argument #%s to %s (%s expected, got %s)", tonumber(num) or 0/0, func, kind, arg)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function pcall(self, func, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
|
||||||
a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20 = _G.pcall(func, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
|
||||||
if not a1 then
|
|
||||||
error(self, string.gsub(a2, ".-%.lua:%d-: ", ""))
|
|
||||||
else
|
|
||||||
return a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local recurse = {}
|
|
||||||
local function addToPositions(t, major)
|
|
||||||
if not AceLibrary.positions[t] or AceLibrary.positions[t] == major then
|
|
||||||
rawset(t, recurse, true)
|
|
||||||
AceLibrary.positions[t] = major
|
|
||||||
for k,v in pairs(t) do
|
|
||||||
if type(v) == "table" and not rawget(v, recurse) then
|
|
||||||
addToPositions(v, major)
|
|
||||||
end
|
|
||||||
if type(k) == "table" and not rawget(k, recurse) then
|
|
||||||
addToPositions(k, major)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local mt = getmetatable(t)
|
|
||||||
if mt and not rawget(mt, recurse) then
|
|
||||||
addToPositions(mt, major)
|
|
||||||
end
|
|
||||||
rawset(t, recurse, nil)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function svnRevisionToNumber(text)
|
|
||||||
if type(text) == "string" then
|
|
||||||
if string.find(text, "^%$Revision: (%d+) %$$") then
|
|
||||||
return tonumber((string.gsub(text, "^%$Revision: (%d+) %$$", "%1")))
|
|
||||||
elseif string.find(text, "^%$Rev: (%d+) %$$") then
|
|
||||||
return tonumber((string.gsub(text, "^%$Rev: (%d+) %$$", "%1")))
|
|
||||||
elseif string.find(text, "^%$LastChangedRevision: (%d+) %$$") then
|
|
||||||
return tonumber((string.gsub(text, "^%$LastChangedRevision: (%d+) %$$", "%1")))
|
|
||||||
end
|
|
||||||
elseif type(text) == "number" then
|
|
||||||
return text
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
|
|
||||||
local crawlReplace
|
|
||||||
do
|
|
||||||
local recurse = {}
|
|
||||||
local function func(t, to, from)
|
|
||||||
if recurse[t] then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
recurse[t] = true
|
|
||||||
local mt = getmetatable(t)
|
|
||||||
setmetatable(t, nil)
|
|
||||||
rawset(t, to, rawget(t, from))
|
|
||||||
rawset(t, from, nil)
|
|
||||||
for k,v in pairs(t) do
|
|
||||||
if v == from then
|
|
||||||
t[k] = to
|
|
||||||
elseif type(v) == "table" then
|
|
||||||
if not recurse[v] then
|
|
||||||
func(v, to, from)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if type(k) == "table" then
|
|
||||||
if not recurse[k] then
|
|
||||||
func(k, to, from)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
setmetatable(t, mt)
|
|
||||||
if mt then
|
|
||||||
if mt == from then
|
|
||||||
setmetatable(t, to)
|
|
||||||
elseif not recurse[mt] then
|
|
||||||
func(mt, to, from)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function crawlReplace(t, to, from)
|
|
||||||
func(t, to, from)
|
|
||||||
for k in pairs(recurse) do
|
|
||||||
recurse[k] = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- @function destroyTable
|
|
||||||
-- @brief remove all the contents of a table
|
|
||||||
-- @param t table to destroy
|
|
||||||
local function destroyTable(t)
|
|
||||||
setmetatable(t, nil)
|
|
||||||
for k,v in pairs(t) do t[k] = nil end
|
|
||||||
table_setn(t, 0)
|
|
||||||
end
|
|
||||||
|
|
||||||
local function isFrame(frame)
|
|
||||||
return type(frame) == "table" and type(rawget(frame, 0)) == "userdata" and type(rawget(frame, 'IsFrameType')) == "function" and getmetatable(frame) and type(rawget(getmetatable(frame), '__index')) == "function"
|
|
||||||
end
|
|
||||||
|
|
||||||
local new, del
|
|
||||||
do
|
|
||||||
local tables = setmetatable({}, {__mode = "k"})
|
|
||||||
|
|
||||||
function new()
|
|
||||||
local t = next(tables)
|
|
||||||
if t then
|
|
||||||
tables[t] = nil
|
|
||||||
return t
|
|
||||||
else
|
|
||||||
return {}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function del(t, depth)
|
|
||||||
if depth and depth > 0 then
|
|
||||||
for k,v in pairs(t) do
|
|
||||||
if type(v) == "table" and not isFrame(v) then
|
|
||||||
del(v, depth - 1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
destroyTable(t)
|
|
||||||
tables[t] = true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- @function copyTable
|
|
||||||
-- @brief Create a shallow copy of a table and return it.
|
|
||||||
-- @param from The table to copy from
|
|
||||||
-- @return A shallow copy of the table
|
|
||||||
local function copyTable(from)
|
|
||||||
local to = new()
|
|
||||||
for k,v in pairs(from) do to[k] = v end
|
|
||||||
table_setn(to, table.getn(from))
|
|
||||||
setmetatable(to, getmetatable(from))
|
|
||||||
return to
|
|
||||||
end
|
|
||||||
|
|
||||||
-- @function deepTransfer
|
|
||||||
-- @brief Fully transfer all data, keeping proper previous table
|
|
||||||
-- backreferences stable.
|
|
||||||
-- @param to The table with which data is to be injected into
|
|
||||||
-- @param from The table whose data will be injected into the first
|
|
||||||
-- @param saveFields If available, a shallow copy of the basic data is saved
|
|
||||||
-- in here.
|
|
||||||
-- @param list The account of table references
|
|
||||||
-- @param list2 The current status on which tables have been traversed.
|
|
||||||
local deepTransfer
|
|
||||||
do
|
|
||||||
-- @function examine
|
|
||||||
-- @brief Take account of all the table references to be shared
|
|
||||||
-- between the to and from tables.
|
|
||||||
-- @param to The table with which data is to be injected into
|
|
||||||
-- @param from The table whose data will be injected into the first
|
|
||||||
-- @param list An account of the table references
|
|
||||||
local function examine(to, from, list, major)
|
|
||||||
list[from] = to
|
|
||||||
for k,v in pairs(from) do
|
|
||||||
if rawget(to, k) and type(from[k]) == "table" and type(to[k]) == "table" and not list[from[k]] then
|
|
||||||
if from[k] == to[k] then
|
|
||||||
list[from[k]] = to[k]
|
|
||||||
elseif AceLibrary.positions[from[v]] ~= major and AceLibrary.positions[from[v]] then
|
|
||||||
list[from[k]] = from[k]
|
|
||||||
elseif not list[from[k]] then
|
|
||||||
examine(to[k], from[k], list, major)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return list
|
|
||||||
end
|
|
||||||
|
|
||||||
function deepTransfer(to, from, saveFields, major, list, list2)
|
|
||||||
setmetatable(to, nil)
|
|
||||||
local createdList
|
|
||||||
if not list then
|
|
||||||
createdList = true
|
|
||||||
list = new()
|
|
||||||
list2 = new()
|
|
||||||
examine(to, from, list, major)
|
|
||||||
end
|
|
||||||
list2[to] = to
|
|
||||||
for k,v in pairs(to) do
|
|
||||||
if type(rawget(from, k)) ~= "table" or type(v) ~= "table" or isFrame(v) then
|
|
||||||
if saveFields then
|
|
||||||
saveFields[k] = v
|
|
||||||
end
|
|
||||||
to[k] = nil
|
|
||||||
elseif v ~= _G then
|
|
||||||
if saveFields then
|
|
||||||
saveFields[k] = copyTable(v)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
for k in pairs(from) do
|
|
||||||
if rawget(to, k) and to[k] ~= from[k] and AceLibrary.positions[to[k]] == major and from[k] ~= _G then
|
|
||||||
if not list2[to[k]] then
|
|
||||||
deepTransfer(to[k], from[k], nil, major, list, list2)
|
|
||||||
end
|
|
||||||
to[k] = list[to[k]] or list2[to[k]]
|
|
||||||
else
|
|
||||||
rawset(to, k, from[k])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
table_setn(to, table.getn(from))
|
|
||||||
setmetatable(to, getmetatable(from))
|
|
||||||
local mt = getmetatable(to)
|
|
||||||
if mt then
|
|
||||||
if list[mt] then
|
|
||||||
setmetatable(to, list[mt])
|
|
||||||
elseif mt.__index and list[mt.__index] then
|
|
||||||
mt.__index = list[mt.__index]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
destroyTable(from)
|
|
||||||
if createdList then
|
|
||||||
del(list)
|
|
||||||
del(list2)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- @method IsNewVersion
|
|
||||||
-- @brief Obtain whether the supplied version would be an upgrade to the
|
|
||||||
-- current version. This allows for bypass code in library
|
|
||||||
-- declaration.
|
|
||||||
-- @param major A string representing the major version
|
|
||||||
-- @param minor An integer or an svn revision string representing the minor version
|
|
||||||
-- @return whether the supplied version would be newer than what is
|
|
||||||
-- currently available.
|
|
||||||
function AceLibrary:IsNewVersion(major, minor)
|
|
||||||
argCheck(self, major, 2, "string")
|
|
||||||
if type(minor) == "string" then
|
|
||||||
local m = svnRevisionToNumber(minor)
|
|
||||||
if m then
|
|
||||||
minor = m
|
|
||||||
else
|
|
||||||
_G.error(string.format("Bad argument #3 to `IsNewVersion'. Must be a number or SVN revision string. %q is not appropriate", minor), 2)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
argCheck(self, minor, 3, "number")
|
|
||||||
local data = self.libs[major]
|
|
||||||
if not data then
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
return data.minor < minor
|
|
||||||
end
|
|
||||||
|
|
||||||
-- @method HasInstance
|
|
||||||
-- @brief Returns whether an instance exists. This allows for optional support of a library.
|
|
||||||
-- @param major A string representing the major version.
|
|
||||||
-- @param minor (optional) An integer or an svn revision string representing the minor version.
|
|
||||||
-- @return Whether an instance exists.
|
|
||||||
function AceLibrary:HasInstance(major, minor)
|
|
||||||
argCheck(self, major, 2, "string")
|
|
||||||
if minor then
|
|
||||||
if type(minor) == "string" then
|
|
||||||
local m = svnRevisionToNumber(minor)
|
|
||||||
if m then
|
|
||||||
minor = m
|
|
||||||
else
|
|
||||||
_G.error(string.format("Bad argument #3 to `HasInstance'. Must be a number or SVN revision string. %q is not appropriate", minor), 2)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
argCheck(self, minor, 3, "number")
|
|
||||||
if not self.libs[major] then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
return self.libs[major].minor == minor
|
|
||||||
end
|
|
||||||
return self.libs[major] and true
|
|
||||||
end
|
|
||||||
|
|
||||||
-- @method GetInstance
|
|
||||||
-- @brief Returns the library with the given major/minor version.
|
|
||||||
-- @param major A string representing the major version.
|
|
||||||
-- @param minor (optional) An integer or an svn revision string representing the minor version.
|
|
||||||
-- @return The library with the given major/minor version.
|
|
||||||
function AceLibrary:GetInstance(major, minor)
|
|
||||||
argCheck(self, major, 2, "string")
|
|
||||||
|
|
||||||
local data = self.libs[major]
|
|
||||||
if not data then
|
|
||||||
_G.error(string.format("Cannot find a library instance of %s.", major), 2)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
if minor then
|
|
||||||
if type(minor) == "string" then
|
|
||||||
local m = svnRevisionToNumber(minor)
|
|
||||||
if m then
|
|
||||||
minor = m
|
|
||||||
else
|
|
||||||
_G.error(string.format("Bad argument #3 to `GetInstance'. Must be a number or SVN revision string. %q is not appropriate", minor), 2)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
argCheck(self, minor, 2, "number")
|
|
||||||
if data.minor ~= minor then
|
|
||||||
_G.error(string.format("Cannot find a library instance of %s, minor version %d.", major, minor), 2)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return data.instance
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Syntax sugar. AceLibrary("FooBar-1.0")
|
|
||||||
AceLibrary_mt.__call = AceLibrary.GetInstance
|
|
||||||
|
|
||||||
local donothing
|
|
||||||
|
|
||||||
local AceEvent
|
|
||||||
|
|
||||||
-- @method Register
|
|
||||||
-- @brief Registers a new version of a given library.
|
|
||||||
-- @param newInstance the library to register
|
|
||||||
-- @param major the major version of the library
|
|
||||||
-- @param minor the minor version of the library
|
|
||||||
-- @param activateFunc (optional) A function to be called when the library is
|
|
||||||
-- fully activated. Takes the arguments
|
|
||||||
-- (newInstance [, oldInstance, oldDeactivateFunc]). If
|
|
||||||
-- oldInstance is given, you should probably call
|
|
||||||
-- oldDeactivateFunc(oldInstance).
|
|
||||||
-- @param deactivateFunc (optional) A function to be called by a newer library's
|
|
||||||
-- activateFunc.
|
|
||||||
-- @param externalFunc (optional) A function to be called whenever a new
|
|
||||||
-- library is registered.
|
|
||||||
function AceLibrary:Register(newInstance, major, minor, activateFunc, deactivateFunc, externalFunc)
|
|
||||||
argCheck(self, newInstance, 2, "table")
|
|
||||||
argCheck(self, major, 3, "string")
|
|
||||||
if type(minor) == "string" then
|
|
||||||
local m = svnRevisionToNumber(minor)
|
|
||||||
if m then
|
|
||||||
minor = m
|
|
||||||
else
|
|
||||||
_G.error(string.format("Bad argument #4 to `Register'. Must be a number or SVN revision string. %q is not appropriate", minor), 2)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
argCheck(self, minor, 4, "number")
|
|
||||||
if math.floor(minor) ~= minor or minor < 0 then
|
|
||||||
error(self, "Bad argument #4 to `Register' (integer >= 0 expected, got %s)", minor)
|
|
||||||
end
|
|
||||||
argCheck(self, activateFunc, 5, "function", "nil")
|
|
||||||
argCheck(self, deactivateFunc, 6, "function", "nil")
|
|
||||||
argCheck(self, externalFunc, 7, "function", "nil")
|
|
||||||
if not deactivateFunc then
|
|
||||||
if not donothing then
|
|
||||||
donothing = function() end
|
|
||||||
end
|
|
||||||
deactivateFunc = donothing
|
|
||||||
end
|
|
||||||
local data = self.libs[major]
|
|
||||||
if not data then
|
|
||||||
-- This is new
|
|
||||||
local instance = copyTable(newInstance)
|
|
||||||
crawlReplace(instance, instance, newInstance)
|
|
||||||
destroyTable(newInstance)
|
|
||||||
if AceLibrary == newInstance then
|
|
||||||
self = instance
|
|
||||||
AceLibrary = instance
|
|
||||||
end
|
|
||||||
self.libs[major] = {
|
|
||||||
instance = instance,
|
|
||||||
minor = minor,
|
|
||||||
deactivateFunc = deactivateFunc,
|
|
||||||
externalFunc = externalFunc,
|
|
||||||
}
|
|
||||||
rawset(instance, 'GetLibraryVersion', function(self)
|
|
||||||
return major, minor
|
|
||||||
end)
|
|
||||||
if not rawget(instance, 'error') then
|
|
||||||
rawset(instance, 'error', error)
|
|
||||||
end
|
|
||||||
if not rawget(instance, 'assert') then
|
|
||||||
rawset(instance, 'assert', assert)
|
|
||||||
end
|
|
||||||
if not rawget(instance, 'argCheck') then
|
|
||||||
rawset(instance, 'argCheck', argCheck)
|
|
||||||
end
|
|
||||||
if not rawget(instance, 'pcall') then
|
|
||||||
rawset(instance, 'pcall', pcall)
|
|
||||||
end
|
|
||||||
addToPositions(instance, major)
|
|
||||||
if activateFunc then
|
|
||||||
activateFunc(instance, nil, nil) -- no old version, so explicit nil
|
|
||||||
end
|
|
||||||
|
|
||||||
if externalFunc then
|
|
||||||
for k,data in pairs(self.libs) do
|
|
||||||
if k ~= major then
|
|
||||||
externalFunc(instance, k, data.instance)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
for k,data in pairs(self.libs) do
|
|
||||||
if k ~= major and data.externalFunc then
|
|
||||||
data.externalFunc(data.instance, major, instance)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if major == "AceEvent-2.0" then
|
|
||||||
AceEvent = instance
|
|
||||||
end
|
|
||||||
if AceEvent then
|
|
||||||
AceEvent.TriggerEvent(self, "AceLibrary_Register", major, instance)
|
|
||||||
end
|
|
||||||
|
|
||||||
return instance
|
|
||||||
end
|
|
||||||
local instance = data.instance
|
|
||||||
if minor <= data.minor then
|
|
||||||
if DEBUG then
|
|
||||||
-- This one is already obsolete, raise an error.
|
|
||||||
error(string.format("Obsolete library registered. %s is already registered at version %d. You are trying to register version %d. Hint: if not AceLibrary:IsNewVersion(%q, %d) then return end", major, data.minor, minor, major, minor), 2)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
return instance
|
|
||||||
end
|
|
||||||
-- This is an update
|
|
||||||
local oldInstance = new()
|
|
||||||
|
|
||||||
addToPositions(newInstance, major)
|
|
||||||
local isAceLibrary = (AceLibrary == newInstance)
|
|
||||||
local old_error, old_assert, old_argCheck, old_pcall
|
|
||||||
if isAceLibrary then
|
|
||||||
self = instance
|
|
||||||
AceLibrary = instance
|
|
||||||
|
|
||||||
old_error = instance.error
|
|
||||||
old_assert = instance.assert
|
|
||||||
old_argCheck = instance.argCheck
|
|
||||||
old_pcall = instance.pcall
|
|
||||||
|
|
||||||
self.error = error
|
|
||||||
self.assert = assert
|
|
||||||
self.argCheck = argCheck
|
|
||||||
self.pcall = pcall
|
|
||||||
end
|
|
||||||
deepTransfer(instance, newInstance, oldInstance, major)
|
|
||||||
crawlReplace(instance, instance, newInstance)
|
|
||||||
local oldDeactivateFunc = data.deactivateFunc
|
|
||||||
data.minor = minor
|
|
||||||
data.deactivateFunc = deactivateFunc
|
|
||||||
data.externalFunc = externalFunc
|
|
||||||
rawset(instance, 'GetLibraryVersion', function(self)
|
|
||||||
return major, minor
|
|
||||||
end)
|
|
||||||
if not rawget(instance, 'error') then
|
|
||||||
rawset(instance, 'error', error)
|
|
||||||
end
|
|
||||||
if not rawget(instance, 'assert') then
|
|
||||||
rawset(instance, 'assert', assert)
|
|
||||||
end
|
|
||||||
if not rawget(instance, 'argCheck') then
|
|
||||||
rawset(instance, 'argCheck', argCheck)
|
|
||||||
end
|
|
||||||
if not rawget(instance, 'pcall') then
|
|
||||||
rawset(instance, 'pcall', pcall)
|
|
||||||
end
|
|
||||||
if isAceLibrary then
|
|
||||||
for _,v in pairs(self.libs) do
|
|
||||||
local i = type(v) == "table" and v.instance
|
|
||||||
if type(i) == "table" then
|
|
||||||
if not rawget(i, 'error') or i.error == old_error then
|
|
||||||
rawset(i, 'error', error)
|
|
||||||
end
|
|
||||||
if not rawget(i, 'assert') or i.assert == old_assert then
|
|
||||||
rawset(i, 'assert', assert)
|
|
||||||
end
|
|
||||||
if not rawget(i, 'argCheck') or i.argCheck == old_argCheck then
|
|
||||||
rawset(i, 'argCheck', argCheck)
|
|
||||||
end
|
|
||||||
if not rawget(i, 'pcall') or i.pcall == old_pcall then
|
|
||||||
rawset(i, 'pcall', pcall)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if activateFunc then
|
|
||||||
activateFunc(instance, oldInstance, oldDeactivateFunc)
|
|
||||||
else
|
|
||||||
oldDeactivateFunc(oldInstance)
|
|
||||||
end
|
|
||||||
del(oldInstance)
|
|
||||||
|
|
||||||
if externalFunc then
|
|
||||||
for k,data in pairs(self.libs) do
|
|
||||||
if k ~= major then
|
|
||||||
externalFunc(instance, k, data.instance)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return instance
|
|
||||||
end
|
|
||||||
|
|
||||||
local iter
|
|
||||||
function AceLibrary:IterateLibraries()
|
|
||||||
if not iter then
|
|
||||||
local function iter(t, k)
|
|
||||||
k = next(t, k)
|
|
||||||
if not k then
|
|
||||||
return nil
|
|
||||||
else
|
|
||||||
return k, t[k].instance
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return iter, self.libs, nil
|
|
||||||
end
|
|
||||||
|
|
||||||
-- @function Activate
|
|
||||||
-- @brief The activateFunc for AceLibrary itself. Called when
|
|
||||||
-- AceLibrary properly registers.
|
|
||||||
-- @param self Reference to AceLibrary
|
|
||||||
-- @param oldLib (optional) Reference to an old version of AceLibrary
|
|
||||||
-- @param oldDeactivate (optional) Function to deactivate the old lib
|
|
||||||
local function activate(self, oldLib, oldDeactivate)
|
|
||||||
if not self.libs then
|
|
||||||
if oldLib then
|
|
||||||
self.libs = oldLib.libs
|
|
||||||
end
|
|
||||||
if not self.libs then
|
|
||||||
self.libs = {}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if not self.positions then
|
|
||||||
if oldLib then
|
|
||||||
self.positions = oldLib.positions
|
|
||||||
end
|
|
||||||
if not self.positions then
|
|
||||||
self.positions = setmetatable({}, { __mode = "k" })
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Expose the library in the global environment
|
|
||||||
_G[ACELIBRARY_MAJOR] = self
|
|
||||||
|
|
||||||
if oldDeactivate then
|
|
||||||
oldDeactivate(oldLib)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if not previous then
|
|
||||||
previous = AceLibrary
|
|
||||||
end
|
|
||||||
if not previous.libs then
|
|
||||||
previous.libs = {}
|
|
||||||
end
|
|
||||||
AceLibrary.libs = previous.libs
|
|
||||||
if not previous.positions then
|
|
||||||
previous.positions = setmetatable({}, { __mode = "k" })
|
|
||||||
end
|
|
||||||
AceLibrary.positions = previous.positions
|
|
||||||
AceLibrary:Register(AceLibrary, ACELIBRARY_MAJOR, ACELIBRARY_MINOR, activate)
|
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user