mirror of
https://github.com/OldManAlpha/Puppeteer.git
synced 2025-11-28 23:48:35 +00:00
Add aggro border and high damage flash
Finally added the ace library bloat
This commit is contained in:
parent
29ba027d88
commit
d4eee5cfd4
@ -140,6 +140,11 @@ function StartsWith(str, starts)
|
||||
return string.sub(str, 1, string.len(starts)) == starts
|
||||
end
|
||||
|
||||
function RoundNumber(number, decimalPlaces)
|
||||
decimalPlaces = decimalPlaces or 0
|
||||
return math.floor(number * 10^decimalPlaces + 0.5) / 10^decimalPlaces
|
||||
end
|
||||
|
||||
-- Courtesy of ChatGPT
|
||||
function InterpolateColors(colors, t)
|
||||
local numColors = table.getn(colors)
|
||||
|
||||
77
HealUI.lua
77
HealUI.lua
@ -23,6 +23,12 @@ HealUI.scrollingHealFrame = nil -- Unimplemented
|
||||
HealUI.auraIconPool = {} -- map: {"frame", "icon", "stackText"}
|
||||
HealUI.auraIcons = {} -- map: {"frame", "icon", "stackText"}
|
||||
|
||||
HealUI.aggroBorder = nil
|
||||
|
||||
HealUI.flashTexture = nil -- {"frame", "texture"}
|
||||
HealUI.flashTime = 0
|
||||
HealUI.lastHealthPercent = 0
|
||||
|
||||
HealUI.incomingHealing = 0
|
||||
|
||||
HealUI.hovered = false
|
||||
@ -217,6 +223,36 @@ function HealUI:UpdateOpacity()
|
||||
self.container:SetAlpha(alpha)
|
||||
end
|
||||
|
||||
function HealUI:SetAggroBorderEnabled(enabled)
|
||||
if enabled then
|
||||
self.aggroBorder:Show()
|
||||
else
|
||||
self.aggroBorder:Hide()
|
||||
end
|
||||
end
|
||||
|
||||
function HealUI:Flash()
|
||||
local FLASH_TIME = 0.15
|
||||
local START_OPACITY = self:GetProfile().FlashOpacity / 100
|
||||
|
||||
self.flashTime = FLASH_TIME
|
||||
local frame = self.flashTexture.frame
|
||||
frame:Show()
|
||||
frame:SetAlpha(START_OPACITY)
|
||||
|
||||
if not frame:GetScript("OnUpdate") then
|
||||
frame:SetScript("OnUpdate", function()
|
||||
self.flashTime = self.flashTime - arg1
|
||||
frame:SetAlpha(START_OPACITY - (((FLASH_TIME - self.flashTime) / FLASH_TIME) * START_OPACITY))
|
||||
|
||||
if self.flashTime <= 0 then
|
||||
frame:Hide()
|
||||
frame:SetScript("OnUpdate", nil)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function HealUI:GetCurrentHealth()
|
||||
if self:IsFake() then
|
||||
if not self.fakeStats.online then
|
||||
@ -256,7 +292,8 @@ function HealUI:ShouldShowMissingHealth()
|
||||
end
|
||||
local missingHealth = self:GetMaxHealth() - currentHealth
|
||||
return (missingHealth > 0 or profile.AlwaysShowMissingHealth) and profile.MissingHealthDisplay ~= "Hidden"
|
||||
and (profile.ShowEnemyMissingHealth or not self:IsEnemy()) and not UnitIsGhost(self.unit)
|
||||
and (profile.ShowEnemyMissingHealth or not self:IsEnemy())
|
||||
and not UnitIsGhost(self.unit) and (UnitIsConnected(self.unit) or self:IsFake())
|
||||
end
|
||||
|
||||
function HealUI.GetColorizedText(color, class, theText)
|
||||
@ -327,7 +364,8 @@ function HealUI:UpdateHealth()
|
||||
local text = util.Colorize("DEAD", 1, 0.3, 0.3)
|
||||
|
||||
-- Check for Feign Death so the healer doesn't get alarmed
|
||||
if util.IsFeigning(unit) then
|
||||
local feign = util.IsFeigning(unit)
|
||||
if feign then
|
||||
text = "Feign"
|
||||
end
|
||||
|
||||
@ -335,6 +373,12 @@ function HealUI:UpdateHealth()
|
||||
missingHealthText:SetText("")
|
||||
self.healthBar:SetValue(0)
|
||||
self.powerBar:SetValue(0)
|
||||
if self.lastHealthPercent > 0 and not self:IsEnemy() then
|
||||
if not feign then
|
||||
self:Flash()
|
||||
end
|
||||
self.lastHealthPercent = 0
|
||||
end
|
||||
elseif UnitIsGhost(unit) then
|
||||
healthText:SetText(util.Colorize("Ghost", 1, 0.3, 0.3))
|
||||
missingHealthText:SetText("")
|
||||
@ -378,6 +422,12 @@ function HealUI:UpdateHealth()
|
||||
missingHealthText:SetText(missingText)
|
||||
|
||||
self.healthBar:SetValue(currentHealth / maxHealth)
|
||||
|
||||
local healthPercent = (currentHealth / maxHealth) * 100
|
||||
if healthPercent < self.lastHealthPercent - profile.FlashThreshold and not self:IsEnemy() then
|
||||
self:Flash()
|
||||
end
|
||||
self.lastHealthPercent = healthPercent
|
||||
end
|
||||
|
||||
self:UpdateOpacity()
|
||||
@ -858,6 +908,20 @@ function HealUI:Initialize()
|
||||
self.auraPanel = buffPanel
|
||||
buffPanel:SetFrameLevel(container:GetFrameLevel() + 2)
|
||||
|
||||
local aggroBorder = CreateFrame("Frame", "$parentAggroBorder", container)
|
||||
self.aggroBorder = aggroBorder
|
||||
aggroBorder:SetBackdrop({edgeFile = "Interface\\Buttons\\WHITE8X8", edgeSize = profile.AggroBorder.Thickness})
|
||||
aggroBorder:SetBackdropBorderColor(1, 0, 0, 0.75)
|
||||
aggroBorder:SetFrameLevel(container:GetFrameLevel() + 10)
|
||||
aggroBorder:Hide()
|
||||
|
||||
local flashFrame = CreateFrame("Frame", "$parentFlash", container)
|
||||
flashFrame:SetFrameLevel(container:GetFrameLevel() + 9)
|
||||
local flashTexture = flashFrame:CreateTexture(nil, "OVERLAY")
|
||||
self.flashTexture = {frame = flashFrame, texture = flashTexture}
|
||||
flashTexture:SetTexture(1, 1, 1)
|
||||
flashFrame:Hide()
|
||||
|
||||
--[[
|
||||
local scrollingDamageFrame = CreateFrame("Frame", unit.."ScrollingDamageFrame", container)
|
||||
self.scrollingDamageFrame = scrollingDamageFrame
|
||||
@ -947,6 +1011,11 @@ function HealUI:SizeElements()
|
||||
local auraPanel = self.auraPanel
|
||||
self:UpdateComponent(auraPanel, profile.AuraTracker)
|
||||
|
||||
self:UpdateComponent(self.aggroBorder, profile.AggroBorder)
|
||||
|
||||
self:UpdateComponent(self.flashTexture.frame, profile.Flash)
|
||||
self.flashTexture.texture:SetAllPoints(self.flashTexture.frame)
|
||||
|
||||
rootContainer:SetHeight(self:GetHeight())
|
||||
overlayContainer:SetHeight(self:GetHeight())
|
||||
container:SetHeight(self:GetHeight())
|
||||
@ -1002,8 +1071,8 @@ function HealUI:UpdateComponent(component, props, xOffset, yOffset)
|
||||
component:SetJustifyH(props.AlignmentH)
|
||||
component:SetJustifyV(props.AlignmentV)
|
||||
else
|
||||
component:SetWidth(props.Width == "Anchor" and anchor:GetWidth() or props.Width)
|
||||
component:SetHeight(props.Height == "Anchor" and anchor:GetHeight() or props.Height)
|
||||
component:SetWidth(props:GetWidth(self))
|
||||
component:SetHeight(props:GetHeight(self))
|
||||
end
|
||||
local alignment = alignmentAnchorMap[props.AlignmentH][props.AlignmentV]
|
||||
component:SetPoint(alignment, anchor, alignment, props:GetOffsetX() + xOffset, props:GetOffsetY() + yOffset)
|
||||
|
||||
@ -77,6 +77,8 @@ SlashCmdList["HEALERSMATE"] = function(args)
|
||||
end
|
||||
end
|
||||
|
||||
HealersMateLib = AceLibrary("AceAddon-2.0"):new("AceEvent-2.0")
|
||||
Banzai = AceLibrary("Banzai-1.0")
|
||||
HealersMate = {}
|
||||
local _G = getfenv(0)
|
||||
setmetatable(HealersMate, {__index = getfenv(1)})
|
||||
@ -624,6 +626,12 @@ function UpdateAllIncomingHealing()
|
||||
end
|
||||
end
|
||||
|
||||
function UpdateAllAggro()
|
||||
for unit, ui in pairs(HealUIs) do
|
||||
ui:SetAggroBorderEnabled(Banzai:GetUnitAggroByUnitId(unit))
|
||||
end
|
||||
end
|
||||
|
||||
local function createUIGroup(groupName, environment, units, petGroup, profile)
|
||||
local uiGroup = HealUIGroup:New(groupName, environment, units, petGroup, profile)
|
||||
for _, unit in ipairs(units) do
|
||||
@ -708,6 +716,17 @@ function EventAddonLoaded()
|
||||
|
||||
initUIs()
|
||||
|
||||
HealersMateLib:RegisterEvent("Banzai_UnitGainedAggro", function(unit)
|
||||
if HealUIs[unit] then
|
||||
HealUIs[unit]:SetAggroBorderEnabled(true)
|
||||
end
|
||||
end)
|
||||
HealersMateLib:RegisterEvent("Banzai_UnitLostAggro", function(unit)
|
||||
if HealUIs[unit] then
|
||||
HealUIs[unit]:SetAggroBorderEnabled(false)
|
||||
end
|
||||
end)
|
||||
|
||||
if HMOnLoadInfoDisabled == nil then
|
||||
HMOnLoadInfoDisabled = false
|
||||
end
|
||||
@ -1134,6 +1153,7 @@ function CheckGroup()
|
||||
if superwow then
|
||||
HMHealPredict.SetRelevantGUIDs(util.ToArray(GUIDUnitMap))
|
||||
end
|
||||
UpdateAllAggro()
|
||||
end
|
||||
|
||||
|
||||
@ -1208,9 +1228,12 @@ function EventHandler()
|
||||
HealUIGroups["Target"]:Hide()
|
||||
local friendly = not UnitCanAttack("player", "target")
|
||||
if (friendly and HMOptions.ShowTargets.Friendly) or (not friendly and HMOptions.ShowTargets.Hostile) then
|
||||
local ui = HealUIs["target"]
|
||||
ui.lastHealthPercent = (ui:GetCurrentHealth() / ui:GetMaxHealth()) * 100
|
||||
ui:CheckRange()
|
||||
ui:CheckSight()
|
||||
ui:UpdateRole()
|
||||
HealUIGroups["Target"]:Show()
|
||||
HealUIs["target"]:CheckRange()
|
||||
HealUIs["target"]:CheckSight()
|
||||
|
||||
if guid then -- If the guid isn't nil, then SuperWoW is present
|
||||
for guidInMap, units in pairs(GUIDUnitMap) do
|
||||
@ -1228,9 +1251,8 @@ function EventHandler()
|
||||
end
|
||||
table.insert(GUIDUnitMap[guid], "target")
|
||||
HMHealPredict.SetRelevantGUIDs(util.ToArray(GUIDUnitMap))
|
||||
HealUIs["target"].incomingHealing = HMHealPredict.GetIncomingHealing(guid)
|
||||
HealUIs["target"]:UpdateHealth()
|
||||
HealUIs["target"]:UpdateRole()
|
||||
ui.incomingHealing = HMHealPredict.GetIncomingHealing(guid)
|
||||
ui:UpdateHealth()
|
||||
end
|
||||
end
|
||||
else
|
||||
|
||||
@ -6,6 +6,20 @@
|
||||
## SavedVariables: HMOnLoadInfoDisabled, HMHealCache, HMPlayerHealCache, HMRoleCache
|
||||
## SavedVariablesPerCharacter: HMSpells, HMOptions
|
||||
|
||||
libs\ace\AceLibrary\AceLibrary.lua
|
||||
libs\ace\AceLocale-2.2\AceLocale-2.2.lua
|
||||
libs\ace\AceOO-2.0\AceOO-2.0.lua
|
||||
libs\ace\AceDebug-2.0\AceDebug-2.0.lua
|
||||
libs\ace\AceAddon-2.0\AceAddon-2.0.lua
|
||||
libs\ace\AceConsole-2.0\AceConsole-2.0.lua
|
||||
libs\ace\AceEvent-2.0\AceEvent-2.0.lua
|
||||
libs\ace\AceHook-2.1\AceHook-2.1.lua
|
||||
libs\ace\Compost-2.0\Compost-2.0.lua
|
||||
libs\ace\Gratuity-2.0\Gratuity-2.0.lua
|
||||
libs\ace\RosterLib-2.0\RosterLib-2.0.lua
|
||||
libs\ace\Deformat-2.0\Deformat-2.0.lua
|
||||
libs\ace\Banzai-1.0\Banzai-1.0.lua
|
||||
|
||||
HMUtil.lua
|
||||
HealUI.lua
|
||||
HealUIGroup.lua
|
||||
|
||||
23
Profile.lua
23
Profile.lua
@ -25,6 +25,12 @@ function HMUIProfile.CreatePositionedObject()
|
||||
obj.OffsetY = 0
|
||||
obj.Anchor = "Health Bar" -- Health Bar, Power Bar, Button, Container
|
||||
obj.Opacity = 100
|
||||
obj.GetWidth = function(self, ui)
|
||||
return (self.Width ~= "Anchor" and self.Width or self:GetAnchorComponent(ui):GetWidth()) + (self.Width2 or 0)
|
||||
end
|
||||
obj.GetHeight = function(self, ui)
|
||||
return (self.Height ~= "Anchor" and self.Height or self:GetAnchorComponent(ui):GetHeight()) + (self.Height2 or 0)
|
||||
end
|
||||
obj.GetOffsetX = function(self)
|
||||
if self.AlignmentH == "LEFT" then
|
||||
return self.PaddingH + self.OffsetX
|
||||
@ -202,6 +208,23 @@ function HMUIProfile.SetDefaults()
|
||||
profile.TrackedAurasSpacing = 2
|
||||
profile.TrackedAurasAlignment = "TOP"
|
||||
|
||||
profile.AggroBorder = createSizedObject({
|
||||
["Height"] = "Anchor",
|
||||
["Width"] = "Anchor",
|
||||
["Height2"] = 2,
|
||||
["Width2"] = 2,
|
||||
["Anchor"] = "Button",
|
||||
["Thickness"] = 2
|
||||
})
|
||||
|
||||
profile.Flash = createSizedObject({
|
||||
["Height"] = "Anchor",
|
||||
["Width"] = "Anchor",
|
||||
["Anchor"] = "Health Bar"
|
||||
})
|
||||
profile.FlashThreshold = 25
|
||||
profile.FlashOpacity = 70
|
||||
|
||||
profile.MaxUnitsInAxis = 5
|
||||
profile.Orientation = "Vertical" --"Vertical", "Horizontal"
|
||||
profile.HorizontalSpacing = 1
|
||||
|
||||
1001
libs/ace/AceAddon-2.0/AceAddon-2.0.lua
Normal file
1001
libs/ace/AceAddon-2.0/AceAddon-2.0.lua
Normal file
File diff suppressed because it is too large
Load Diff
1898
libs/ace/AceConsole-2.0/AceConsole-2.0.lua
Normal file
1898
libs/ace/AceConsole-2.0/AceConsole-2.0.lua
Normal file
File diff suppressed because it is too large
Load Diff
242
libs/ace/AceDebug-2.0/AceDebug-2.0.lua
Normal file
242
libs/ace/AceDebug-2.0/AceDebug-2.0.lua
Normal file
@ -0,0 +1,242 @@
|
||||
--[[
|
||||
Name: AceDebug-2.0
|
||||
Revision: $Rev: 99999 $
|
||||
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/AceDebug-2.0
|
||||
SVN: http://svn.wowace.com/root/trunk/Ace2/AceDebug-2.0
|
||||
Description: Mixin to allow for simple debugging capabilities.
|
||||
Dependencies: AceLibrary, AceOO-2.0
|
||||
]]
|
||||
|
||||
local MAJOR_VERSION = "AceDebug-2.0"
|
||||
local MINOR_VERSION = "$Revision: 99999 $"
|
||||
|
||||
if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end
|
||||
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
|
||||
|
||||
if loadstring("return function(...) return ... end") and AceLibrary:HasInstance(MAJOR_VERSION) then return end -- lua51 check
|
||||
if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0") end
|
||||
|
||||
local DEBUGGING, TOGGLE_DEBUGGING
|
||||
|
||||
if GetLocale() == "frFR" then
|
||||
DEBUGGING = "D\195\169boguage"
|
||||
TOGGLE_DEBUGGING = "Activer/d\195\169sactiver le d\195\169boguage"
|
||||
elseif GetLocale() == "deDE" then
|
||||
DEBUGGING = "Debuggen"
|
||||
TOGGLE_DEBUGGING = "Aktiviert/Deaktiviert Debugging"
|
||||
elseif GetLocale() == "koKR" then
|
||||
DEBUGGING = "디버깅"
|
||||
TOGGLE_DEBUGGING = "디버깅 기능 사용함/사용안함"
|
||||
elseif GetLocale() == "zhTW" then
|
||||
DEBUGGING = "除錯"
|
||||
TOGGLE_DEBUGGING = "啟用/停用除錯功能"
|
||||
elseif GetLocale() == "zhCN" then
|
||||
DEBUGGING = "\232\176\131\232\175\149"
|
||||
TOGGLE_DEBUGGING = "\229\144\175\231\148\168/\231\166\129\231\148\168 \232\176\131\232\175\149"
|
||||
elseif GetLocale() == "ruRU" then
|
||||
DEBUGGING = "Отладка"
|
||||
TOGGLE_DEBUGGING = "Вкл./Выкл. отладку для этого аддона."
|
||||
else -- enUS
|
||||
DEBUGGING = "Debugging"
|
||||
TOGGLE_DEBUGGING = "Enable/disable debugging"
|
||||
end
|
||||
|
||||
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 math_mod = math.mod or math.fmod
|
||||
|
||||
local AceOO = AceLibrary:GetInstance("AceOO-2.0")
|
||||
local AceDebug = AceOO.Mixin {"Debug", "CustomDebug", "IsDebugging", "SetDebugging", "SetDebugLevel", "LevelDebug", "CustomLevelDebug", "GetDebugLevel"}
|
||||
|
||||
local function print(text, r, g, b, frame, delay)
|
||||
(frame or DEFAULT_CHAT_FRAME):AddMessage(text, r, g, b, 1, delay or 5)
|
||||
end
|
||||
|
||||
local tmp
|
||||
|
||||
function AceDebug:CustomDebug(r, g, b, frame, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
if not self.debugging then return end
|
||||
|
||||
local output = string.format("|cff7fff7f(DEBUG) %s:[%s%3d]|r", tostring(self), date("%H:%M:%S"), math_mod(GetTime(), 1) * 1000)
|
||||
|
||||
if string.find(tostring(a1), "%%") then
|
||||
output = output .. " " .. string.format(tostring(a1), tostring(a2), tostring(a3), tostring(a4), tostring(a5), tostring(a6), tostring(a7), tostring(a8), tostring(a9), tostring(a10), tostring(a11), tostring(a12), tostring(a13), tostring(a14), tostring(a15), tostring(a16), tostring(a17), tostring(a18), tostring(a19), tostring(a20))
|
||||
else
|
||||
if not tmp then
|
||||
tmp = {}
|
||||
end
|
||||
|
||||
-- This block dynamically rebuilds the tmp array stopping on the first nil.
|
||||
table.insert(tmp, output)
|
||||
|
||||
table.insert(tmp, tostring(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)
|
||||
while tmp[table.getn(tmp)] == nil do
|
||||
table.remove(tmp)
|
||||
end
|
||||
for k = 1, table.getn(tmp) do
|
||||
tmp[k] = tostring(tmp[k])
|
||||
end
|
||||
|
||||
output = table.concat(tmp, " ")
|
||||
|
||||
for k,v in pairs(tmp) do
|
||||
tmp[k] = nil
|
||||
end
|
||||
table_setn(tmp, 0)
|
||||
end
|
||||
|
||||
print(output, r, g, b, frame or self.debugFrame, delay)
|
||||
end
|
||||
|
||||
function AceDebug:Debug(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
AceDebug.CustomDebug(self, nil, nil, nil, nil, nil, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
end
|
||||
|
||||
function AceDebug:IsDebugging()
|
||||
return self.debugging
|
||||
end
|
||||
|
||||
function AceDebug:SetDebugging(debugging)
|
||||
self.debugging = debugging
|
||||
end
|
||||
|
||||
-- Takes a number 1-3
|
||||
-- Level 1: Critical messages that every user should receive
|
||||
-- Level 2: Should be used for local debugging (function calls, etc)
|
||||
-- Level 3: Very verbose debugging, will dump everything and anything
|
||||
-- If set to nil, you will receive no debug information
|
||||
function AceDebug:SetDebugLevel(level)
|
||||
AceDebug:argCheck(level, 1, "number", "nil")
|
||||
if not level then
|
||||
self.debuglevel = nil
|
||||
return
|
||||
end
|
||||
if level < 1 or level > 3 then
|
||||
AceDebug:error("Bad argument #1 to `SetDebugLevel`, must be a number 1-3")
|
||||
end
|
||||
self.debuglevel = level
|
||||
end
|
||||
|
||||
function AceDebug:GetDebugLevel()
|
||||
return self.debuglevel
|
||||
end
|
||||
|
||||
function AceDebug:CustomLevelDebug(level, r, g, b, frame, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
if not self.debugging or not self.debuglevel then return end
|
||||
AceDebug:argCheck(level, 1, "number")
|
||||
if level < 1 or level > 3 then
|
||||
AceDebug:error("Bad argument #1 to `LevelDebug`, must be a number 1-3")
|
||||
end
|
||||
if level > self.debuglevel then return end
|
||||
|
||||
local output = string.format("|cff7fff7f(DEBUG) %s:[%s.%3d]|r", tostring(self), date("%H:%M:%S"), math_mod(GetTime(), 1) * 1000)
|
||||
|
||||
if string.find(tostring(a1), "%%") then
|
||||
output = output .. " " .. string.format(tostring(a1), tostring(a2), tostring(a3), tostring(a4), tostring(a5), tostring(a6), tostring(a7), tostring(a8), tostring(a9), tostring(a10), tostring(a11), tostring(a12), tostring(a13), tostring(a14), tostring(a15), tostring(a16), tostring(a17), tostring(a18), tostring(a19), tostring(a20))
|
||||
else
|
||||
if not tmp then
|
||||
tmp = {}
|
||||
end
|
||||
|
||||
-- This block dynamically rebuilds the tmp array stopping on the first nil.
|
||||
table.insert(tmp, output)
|
||||
|
||||
table.insert(tmp, tostring(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)
|
||||
while tmp[table.getn(tmp)] == nil do
|
||||
table.remove(tmp)
|
||||
end
|
||||
for k = 1, table.getn(tmp) do
|
||||
tmp[k] = tostring(tmp[k])
|
||||
end
|
||||
|
||||
output = table.concat(tmp, " ")
|
||||
|
||||
for k,v in pairs(tmp) do
|
||||
tmp[k] = nil
|
||||
end
|
||||
table_setn(tmp, 0)
|
||||
end
|
||||
|
||||
print(output, r, g, b, frame or self.debugFrame, delay)
|
||||
end
|
||||
|
||||
function AceDebug:LevelDebug(level, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
if not self.debugging or not self.debuglevel then return end
|
||||
AceDebug:argCheck(level, 1, "number")
|
||||
if level < 1 or level > 3 then
|
||||
AceDebug:error("Bad argument #1 to `LevelDebug`, must be a number 1-3")
|
||||
end
|
||||
if level > self.debuglevel then return end
|
||||
|
||||
AceDebug.CustomLevelDebug(self, level, nil, nil, nil, nil, nil, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
|
||||
end
|
||||
|
||||
|
||||
local options
|
||||
function AceDebug:GetAceOptionsDataTable(target)
|
||||
if not options then
|
||||
options = {
|
||||
debug = {
|
||||
name = DEBUGGING,
|
||||
desc = TOGGLE_DEBUGGING,
|
||||
type = "toggle",
|
||||
get = "IsDebugging",
|
||||
set = "SetDebugging",
|
||||
order = -2,
|
||||
}
|
||||
}
|
||||
end
|
||||
return options
|
||||
end
|
||||
AceLibrary:Register(AceDebug, MAJOR_VERSION, MINOR_VERSION, AceDebug.activate)
|
||||
AceDebug = AceLibrary(MAJOR_VERSION)
|
||||
970
libs/ace/AceEvent-2.0/AceEvent-2.0.lua
Normal file
970
libs/ace/AceEvent-2.0/AceEvent-2.0.lua
Normal file
@ -0,0 +1,970 @@
|
||||
--[[
|
||||
Name: AceEvent-2.0
|
||||
Revision: $Rev: 17638 $
|
||||
Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team)
|
||||
Inspired By: Ace 1.x by Turan (turan@gryphon.com)
|
||||
Website: http://www.wowace.com/
|
||||
Documentation: http://www.wowace.com/index.php/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: 17638 $"
|
||||
|
||||
if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end
|
||||
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
|
||||
|
||||
if loadstring("return function(...) return ... end") and AceLibrary:HasInstance(MAJOR_VERSION) then return end -- lua51 check
|
||||
if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0") end
|
||||
|
||||
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 lastEvent = AceEvent.currentEvent
|
||||
AceEvent.currentEvent = 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
|
||||
AceEvent.currentEvent = lastEvent
|
||||
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 tmp = {}
|
||||
local function OnUpdate()
|
||||
local t = GetTime()
|
||||
for k,v in pairs(delayRegistry) do
|
||||
tmp[k] = true
|
||||
end
|
||||
for k in pairs(tmp) do
|
||||
local v = delayRegistry[k]
|
||||
if v then
|
||||
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
|
||||
end
|
||||
end
|
||||
for k in pairs(tmp) do
|
||||
tmp[k] = nil
|
||||
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(self, event)
|
||||
else
|
||||
for _,v in ipairs(event) do
|
||||
AceEvent.UnregisterEvent(self, 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()
|
||||
|
||||
registeringFromAceEvent = true
|
||||
self:RegisterEvent("LOOT_OPENED", function()
|
||||
SendAddonMessage("LOOT_OPENED", "", "RAID")
|
||||
end)
|
||||
registeringFromAceEvent = nil
|
||||
|
||||
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)
|
||||
569
libs/ace/AceHook-2.1/AceHook-2.1.lua
Normal file
569
libs/ace/AceHook-2.1/AceHook-2.1.lua
Normal file
@ -0,0 +1,569 @@
|
||||
--[[
|
||||
Name: AceHook-2.1
|
||||
Revision: $Rev: 17638 $
|
||||
Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team)
|
||||
Inspired By: Ace 1.x by Turan (turan@gryphon.com)
|
||||
Website: http://www.wowace.com/
|
||||
Documentation: http://www.wowace.com/index.php/AceHook-2.1
|
||||
SVN: http://svn.wowace.com/root/trunk/Ace2/AceHook-2.1
|
||||
Description: Mixin to allow for safe hooking of functions, methods, and scripts.
|
||||
Dependencies: AceLibrary, AceOO-2.0
|
||||
]]
|
||||
|
||||
local MAJOR_VERSION = "AceHook-2.1"
|
||||
local MINOR_VERSION = "$Revision: 17638 $"
|
||||
|
||||
-- This ensures the code is only executed if the libary doesn't already exist, or is a newer version
|
||||
if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary.") end
|
||||
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
|
||||
|
||||
if loadstring("return function(...) return ... end") and AceLibrary:HasInstance(MAJOR_VERSION) then return end -- lua51 check
|
||||
if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0") end
|
||||
|
||||
--[[---------------------------------------------------------------------------------
|
||||
Create the library object
|
||||
----------------------------------------------------------------------------------]]
|
||||
|
||||
local AceOO = AceLibrary:GetInstance("AceOO-2.0")
|
||||
local AceHook = AceOO.Mixin {
|
||||
"Hook",
|
||||
"HookScript",
|
||||
"SecureHook",
|
||||
"Unhook",
|
||||
"UnhookAll",
|
||||
"HookReport",
|
||||
"IsHooked",
|
||||
}
|
||||
|
||||
--[[---------------------------------------------------------------------------------
|
||||
Library Definitions
|
||||
----------------------------------------------------------------------------------]]
|
||||
|
||||
local protFuncs = {
|
||||
CameraOrSelectOrMoveStart = true, CameraOrSelectOrMoveStop = true,
|
||||
TurnOrActionStart = true, TurnOrActionStop = true,
|
||||
PitchUpStart = true, PitchUpStop = true,
|
||||
PitchDownStart = true, PitchDownStop = true,
|
||||
MoveBackwardStart = true, MoveBackwardStop = true,
|
||||
MoveForwardStart = true, MoveForwardStop = true,
|
||||
Jump = true, StrafeLeftStart = true,
|
||||
StrafeLeftStop = true, StrafeRightStart = true,
|
||||
StrafeRightStop = true, ToggleMouseMove = true,
|
||||
ToggleRun = true, TurnLeftStart = true,
|
||||
TurnLeftStop = true, TurnRightStart = true,
|
||||
TurnRightStop = true,
|
||||
}
|
||||
|
||||
local function issecurevariable(x)
|
||||
if protFuncs[x] then
|
||||
return 1
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
local _G = getfenv(0)
|
||||
|
||||
local function hooksecurefunc(arg1, arg2, arg3)
|
||||
if type(arg1) == "string" then
|
||||
arg1, arg2, arg3 = _G, arg1, arg2
|
||||
end
|
||||
local orig = arg1[arg2]
|
||||
arg1[arg2] = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
local x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15,x16,x17,x18,x19,x20 = orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
|
||||
arg3(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
|
||||
return x1,x2,x3,x4,x5,x6,x7,x8,x9,x10,x11,x12,x13,x14,x15,x16,x17,x18,x19,x20
|
||||
end
|
||||
end
|
||||
|
||||
local protectedScripts = {
|
||||
OnClick = true,
|
||||
}
|
||||
|
||||
|
||||
local handlers, scripts, actives, registry
|
||||
|
||||
--[[---------------------------------------------------------------------------------
|
||||
Private definitions (Not exposed)
|
||||
----------------------------------------------------------------------------------]]
|
||||
|
||||
local new, del
|
||||
do
|
||||
local list = setmetatable({}, {__mode = "k"})
|
||||
function new()
|
||||
local t = next(list)
|
||||
if not t then
|
||||
return {}
|
||||
end
|
||||
list[t] = nil
|
||||
return t
|
||||
end
|
||||
|
||||
function del(t)
|
||||
setmetatable(t, nil)
|
||||
for k in pairs(t) do
|
||||
t[k] = nil
|
||||
end
|
||||
list[t] = true
|
||||
end
|
||||
end
|
||||
|
||||
local function createFunctionHook(self, func, handler, orig, secure)
|
||||
if not secure then
|
||||
if type(handler) == "string" then
|
||||
-- The handler is a method, need to self it
|
||||
local uid
|
||||
uid = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
if actives[uid] then
|
||||
return self[handler](self, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
else
|
||||
return orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
end
|
||||
end
|
||||
return uid
|
||||
else
|
||||
-- The handler is a function, just call it
|
||||
local uid
|
||||
uid = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
if actives[uid] then
|
||||
return handler(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
else
|
||||
return orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
end
|
||||
end
|
||||
return uid
|
||||
end
|
||||
else
|
||||
-- secure hooks don't call the original method
|
||||
if type(handler) == "string" then
|
||||
-- The handler is a method, need to self it
|
||||
local uid
|
||||
uid = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
if actives[uid] then
|
||||
return self[handler](self, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
end
|
||||
end
|
||||
return uid
|
||||
else
|
||||
-- The handler is a function, just call it
|
||||
local uid
|
||||
uid = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
if actives[uid] then
|
||||
return handler(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
end
|
||||
end
|
||||
return uid
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function createMethodHook(self, object, method, handler, orig, secure, script)
|
||||
if script then
|
||||
if type(handler) == "string" then
|
||||
local uid
|
||||
uid = function()
|
||||
if actives[uid] then
|
||||
return self[handler](self, object)
|
||||
else
|
||||
return orig()
|
||||
end
|
||||
end
|
||||
return uid
|
||||
else
|
||||
-- The handler is a function, just call it
|
||||
local uid
|
||||
uid = function()
|
||||
if actives[uid] then
|
||||
return handler(object)
|
||||
else
|
||||
return orig()
|
||||
end
|
||||
end
|
||||
return uid
|
||||
end
|
||||
elseif not secure then
|
||||
if type(handler) == "string" then
|
||||
local uid
|
||||
uid = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
if actives[uid] then
|
||||
return self[handler](self, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
else
|
||||
return orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
end
|
||||
end
|
||||
return uid
|
||||
else
|
||||
-- The handler is a function, just call it
|
||||
local uid
|
||||
uid = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
if actives[uid] then
|
||||
return handler(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
else
|
||||
return orig(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
end
|
||||
end
|
||||
return uid
|
||||
end
|
||||
else
|
||||
-- secure hooks don't call the original method
|
||||
if type(handler) == "string" then
|
||||
local uid
|
||||
uid = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
if actives[uid] then
|
||||
return self[handler](self, a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
end
|
||||
end
|
||||
return uid
|
||||
else
|
||||
-- The handler is a function, just call it
|
||||
local uid
|
||||
uid = function(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
if actives[uid] then
|
||||
return handler(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
end
|
||||
end
|
||||
return uid
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function hookFunction(self, func, handler, secure)
|
||||
local orig = _G[func]
|
||||
|
||||
if not orig or type(orig) ~= "function" then
|
||||
AceHook:error("Attempt to hook a non-existant function %q", func)
|
||||
end
|
||||
|
||||
if not handler then
|
||||
handler = func
|
||||
end
|
||||
|
||||
if registry[self][func] then
|
||||
local uid = registry[self][func]
|
||||
|
||||
if actives[uid] then
|
||||
-- We have an active hook from this source. Don't multi-hook
|
||||
AceHook:error("%q already has an active hook from this source.", func)
|
||||
end
|
||||
|
||||
if handlers[uid] == handler then
|
||||
-- The hook is inactive, so reactivate it
|
||||
actives[uid] = true
|
||||
return
|
||||
else
|
||||
AceHook:error("There is a stale hook for %q can't hook or reactivate.", func)
|
||||
end
|
||||
end
|
||||
|
||||
if type(handler) == "string" then
|
||||
if type(self[handler]) ~= "function" then
|
||||
AceHook:error("Could not find the the handler %q when hooking function %q", handler, func)
|
||||
end
|
||||
elseif type(handler) ~= "function" then
|
||||
AceHook:error("Could not find the handler you supplied when hooking %q", func)
|
||||
end
|
||||
|
||||
local uid = createFunctionHook(self, func, handler, orig, secure)
|
||||
registry[self][func] = uid
|
||||
actives[uid] = true
|
||||
handlers[uid] = handler
|
||||
|
||||
if not secure then
|
||||
_G[func] = uid
|
||||
self.hooks[func] = orig
|
||||
else
|
||||
hooksecurefunc(func, uid)
|
||||
end
|
||||
end
|
||||
|
||||
local function unhookFunction(self, func)
|
||||
if not registry[self][func] then
|
||||
AceHook:error("Tried to unhook %q which is not currently hooked.", func)
|
||||
end
|
||||
|
||||
local uid = registry[self][func]
|
||||
|
||||
if actives[uid] then
|
||||
-- See if we own the global function
|
||||
if self.hooks[func] and _G[func] == uid then
|
||||
_G[func] = self.hooks[func]
|
||||
self.hooks[func] = nil
|
||||
registry[self][func] = nil
|
||||
handlers[uid] = nil
|
||||
scripts[uid] = nil
|
||||
actives[uid] = nil
|
||||
-- Magically all-done
|
||||
else
|
||||
actives[uid] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function hookMethod(self, obj, method, handler, script, secure)
|
||||
if not handler then
|
||||
handler = method
|
||||
end
|
||||
|
||||
if not obj or type(obj) ~= "table" then
|
||||
AceHook:error("The object you supplied could not be found, or isn't a table.")
|
||||
end
|
||||
|
||||
local uid = registry[self][obj] and registry[self][obj][method]
|
||||
if uid then
|
||||
if actives[uid] then
|
||||
-- We have an active hook from this source. Don't multi-hook
|
||||
AceHook:error("%q already has an active hook from this source.", method)
|
||||
end
|
||||
|
||||
if handlers[uid] == handler then
|
||||
-- The hook is inactive, reactivate it.
|
||||
actives[uid] = true
|
||||
return
|
||||
else
|
||||
AceHook:error("There is a stale hook for %q can't hook or reactivate.", method)
|
||||
end
|
||||
end
|
||||
|
||||
if type(handler) == "string" then
|
||||
if type(self[handler]) ~= "function" then
|
||||
AceHook:error("Could not find the handler %q you supplied when hooking method %q", handler, method)
|
||||
end
|
||||
elseif type(handler) ~= "function" then
|
||||
AceHook:error("Could not find the handler you supplied when hooking method %q", method)
|
||||
end
|
||||
|
||||
local orig
|
||||
if script then
|
||||
if not obj.GetScript then
|
||||
AceHook:error("The object you supplied does not have a GetScript method.")
|
||||
end
|
||||
if not obj:HasScript(method) then
|
||||
AceHook:error("The object you supplied doesn't allow the %q method.", method)
|
||||
end
|
||||
|
||||
orig = obj:GetScript(method)
|
||||
if type(orig) ~= "function" then
|
||||
-- Sometimes there is not a original function for a script.
|
||||
orig = function() end
|
||||
end
|
||||
else
|
||||
orig = obj[method]
|
||||
end
|
||||
if not orig then
|
||||
AceHook:error("Could not find the method or script %q you are trying to hook.", method)
|
||||
end
|
||||
|
||||
if not registry[self][obj] then
|
||||
registry[self][obj] = new()
|
||||
end
|
||||
|
||||
if not self.hooks[obj] then
|
||||
self.hooks[obj] = new()
|
||||
end
|
||||
|
||||
local uid = createMethodHook(self, obj, method, handler, orig, secure, script)
|
||||
registry[self][obj][method] = uid
|
||||
actives[uid] = true
|
||||
handlers[uid] = handler
|
||||
scripts[uid] = script and true or nil
|
||||
|
||||
if script then
|
||||
obj:SetScript(method, uid)
|
||||
self.hooks[obj][method] = orig
|
||||
elseif not secure then
|
||||
obj[method] = uid
|
||||
self.hooks[obj][method] = orig
|
||||
else
|
||||
hooksecurefunc(obj, method, uid)
|
||||
end
|
||||
end
|
||||
|
||||
local function unhookMethod(self, obj, method)
|
||||
if not registry[self][obj] or not registry[self][obj][method] then
|
||||
AceHook:error("Attempt to unhook a method %q that is not currently hooked.", method)
|
||||
return
|
||||
end
|
||||
|
||||
local uid = registry[self][obj][method]
|
||||
|
||||
if actives[uid] then
|
||||
if scripts[uid] then -- If this is a script
|
||||
if obj:GetScript(method) == uid then
|
||||
-- We own the script. Revert to normal.
|
||||
obj:SetScript(method, self.hooks[obj][method])
|
||||
self.hooks[obj][method] = nil
|
||||
registry[self][obj][method] = nil
|
||||
handlers[uid] = nil
|
||||
scripts[uid] = nil
|
||||
actives[uid] = nil
|
||||
else
|
||||
actives[uid] = nil
|
||||
end
|
||||
else
|
||||
if self.hooks[obj] and self.hooks[obj][method] and obj[method] == uid then
|
||||
-- We own the method. Revert to normal.
|
||||
obj[method] = self.hooks[obj][method]
|
||||
self.hooks[obj][method] = nil
|
||||
registry[self][obj][method] = nil
|
||||
handlers[uid] = nil
|
||||
actives[uid] = nil
|
||||
else
|
||||
actives[uid] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
if self.hooks[obj] and not next(self.hooks[obj]) then
|
||||
self.hooks[obj] = del(self.hooks[obj])
|
||||
end
|
||||
if not next(registry[self][obj]) then
|
||||
registry[self][obj] = del(registry[self][obj])
|
||||
end
|
||||
end
|
||||
|
||||
-- ("function" [, handler] [, hookSecure]) or (object, "method" [, handler] [, hookSecure])
|
||||
function AceHook:Hook(object, method, handler, hookSecure)
|
||||
if type(object) == "string" then
|
||||
method, handler, hookSecure = object, method, handler
|
||||
if handler == true then
|
||||
handler, hookSecure = nil, true
|
||||
end
|
||||
if not hookSecure and issecurevariable(method) then
|
||||
AceHook:error("Attempt to hook secure function %q. Use `SecureHook' or add `true' to the argument list to override.", method)
|
||||
end
|
||||
AceHook:argCheck(handler, 3, "function", "string", "nil")
|
||||
AceHook:argCheck(hookSecure, 4, "boolean", "nil")
|
||||
hookFunction(self, method, handler, false)
|
||||
else
|
||||
if handler == true then
|
||||
handler, hookSecure = nil, true
|
||||
end
|
||||
if not hookSecure and issecurevariable(object, method) then
|
||||
AceHook:error("Attempt to hook secure method %q. Use `SecureHook' or add `true' to the argument list to override.", method)
|
||||
end
|
||||
AceHook:argCheck(object, 2, "table")
|
||||
AceHook:argCheck(method, 3, "string")
|
||||
AceHook:argCheck(handler, 4, "function", "string", "nil")
|
||||
AceHook:argCheck(hookSecure, 5, "boolean", "nil")
|
||||
hookMethod(self, object, method, handler, false, false)
|
||||
end
|
||||
end
|
||||
|
||||
-- ("function", handler) or (object, "method", handler)
|
||||
function AceHook:SecureHook(object, method, handler)
|
||||
if type(object) == "string" then
|
||||
method, handler = object, method
|
||||
AceHook:argCheck(handler, 3, "function", "string", "nil")
|
||||
hookFunction(self, method, handler, true)
|
||||
else
|
||||
AceHook:argCheck(object, 2, "table")
|
||||
AceHook:argCheck(method, 3, "string")
|
||||
AceHook:argCheck(handler, 4, "function", "string", "nil")
|
||||
hookMethod(self, object, method, handler, false, true)
|
||||
end
|
||||
end
|
||||
|
||||
function AceHook:HookScript(frame, script, handler)
|
||||
AceHook:argCheck(frame, 2, "table")
|
||||
if not frame[0] or type(frame.IsFrameType) ~= "function" then
|
||||
AceHook:error("Bad argument #2 to `HookScript'. Expected frame.")
|
||||
end
|
||||
AceHook:argCheck(script, 3, "string")
|
||||
AceHook:argCheck(handler, 4, "function", "string", "nil")
|
||||
hookMethod(self, frame, script, handler, true, false)
|
||||
end
|
||||
|
||||
-- ("function") or (object, "method")
|
||||
function AceHook:IsHooked(obj, method)
|
||||
if type(obj) == "string" then
|
||||
if registry[self][obj] and actives[registry[self][obj]] then
|
||||
return true, handlers[registry[self][obj]]
|
||||
end
|
||||
else
|
||||
AceHook:argCheck(obj, 2, "string", "table")
|
||||
AceHook:argCheck(method, 3, "string")
|
||||
if registry[self][obj] and registry[self][obj][method] and actives[registry[self][obj][method]] then
|
||||
return true, handlers[registry[self][obj][method]]
|
||||
end
|
||||
end
|
||||
|
||||
return false, nil
|
||||
end
|
||||
|
||||
-- ("function") or (object, "method")
|
||||
function AceHook:Unhook(obj, method)
|
||||
if type(obj) == "string" then
|
||||
unhookFunction(self, obj)
|
||||
else
|
||||
AceHook:argCheck(obj, 2, "string", "table")
|
||||
AceHook:argCheck(method, 3, "string")
|
||||
unhookMethod(self, obj, method)
|
||||
end
|
||||
end
|
||||
|
||||
function AceHook:UnhookAll()
|
||||
for key, value in pairs(registry[self]) do
|
||||
if type(key) == "table" then
|
||||
for method in pairs(value) do
|
||||
self:Unhook(key, method)
|
||||
end
|
||||
else
|
||||
self:Unhook(key)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function AceHook:HookReport()
|
||||
DEFAULT_CHAT_FRAME:AddMessage("This is a list of all active hooks for this object:")
|
||||
if not next(registry[self]) then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("No hooks")
|
||||
end
|
||||
|
||||
for key, value in pairs(registry[self]) do
|
||||
if type(value) == "table" then
|
||||
for method, uid in pairs(value) do
|
||||
DEFAULT_CHAT_FRAME:AddMessage(string.format("object: %s method: %q |cff%s|r%s", tostring(key), method, actives[uid] and "00ff00Active" or "ffff00Inactive", not self.hooks[key][method] and " |cff7f7fff-Secure-|r" or ""))
|
||||
end
|
||||
else
|
||||
DEFAULT_CHAT_FRAME:AddMessage(string.format("function: %q |cff%s|r%s", tostring(key), actives[value] and "00ff00Active" or "ffff00Inactive", not self.hooks[key] and " |cff7f7fff-Secure-|r" or ""))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function AceHook:OnInstanceInit(object)
|
||||
if not object.hooks then
|
||||
object.hooks = new()
|
||||
end
|
||||
if not registry[object] then
|
||||
registry[object] = new()
|
||||
end
|
||||
end
|
||||
|
||||
AceHook.OnManualEmbed = AceHook.OnInstanceInit
|
||||
|
||||
function AceHook:OnEmbedDisable(target)
|
||||
self.UnhookAll(target)
|
||||
end
|
||||
|
||||
local function activate(self, oldLib, oldDeactivate)
|
||||
AceHook = self
|
||||
|
||||
self.handlers = oldLib and oldLib.handlers or {}
|
||||
self.registry = oldLib and oldLib.registry or {}
|
||||
self.scripts = oldLib and oldLib.scripts or {}
|
||||
self.actives = oldLib and oldLib.actives or {}
|
||||
|
||||
handlers = self.handlers
|
||||
registry = self.registry
|
||||
scripts = self.scripts
|
||||
actives = self.actives
|
||||
|
||||
AceHook.super.activate(self, oldLib, oldDeactivate)
|
||||
|
||||
if oldDeactivate then
|
||||
oldDeactivate(oldLib)
|
||||
end
|
||||
end
|
||||
|
||||
AceLibrary:Register(AceHook, MAJOR_VERSION, MINOR_VERSION, activate)
|
||||
752
libs/ace/AceLibrary/AceLibrary.lua
Normal file
752
libs/ace/AceLibrary/AceLibrary.lua
Normal file
@ -0,0 +1,752 @@
|
||||
--[[
|
||||
Name: AceLibrary
|
||||
Revision: $Rev: 17638 $
|
||||
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: 17638 $
|
||||
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: 17638 $"
|
||||
|
||||
if loadstring("return function(...) return ... end") and AceLibrary:HasInstance(ACELIBRARY_MINOR) then return end -- lua51 check
|
||||
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 TryToLoadStandalone
|
||||
-- @brief Attempt to find and load a standalone version of the requested library
|
||||
-- @param major A string representing the major version
|
||||
-- @return If library is found, return values from the call to LoadAddOn are returned
|
||||
-- If the library has been requested previously, nil is returned.
|
||||
local function TryToLoadStandalone(major)
|
||||
if not AceLibrary.scannedlibs then AceLibrary.scannedlibs = {} end
|
||||
if AceLibrary.scannedlibs[major] then return end
|
||||
|
||||
AceLibrary.scannedlibs[major] = true
|
||||
|
||||
local name, _, _, enabled, loadable = GetAddOnInfo(major)
|
||||
if loadable then
|
||||
return LoadAddOn(name)
|
||||
end
|
||||
|
||||
for i=1,GetNumAddOns() do
|
||||
if GetAddOnMetadata(i, "X-AceLibrary-"..major) then
|
||||
local name, _, _, enabled, loadable = GetAddOnInfo(i)
|
||||
if loadable then
|
||||
return LoadAddOn(name)
|
||||
end
|
||||
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")
|
||||
TryToLoadStandalone(major)
|
||||
|
||||
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")
|
||||
TryToLoadStandalone(major)
|
||||
|
||||
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")
|
||||
TryToLoadStandalone(major)
|
||||
|
||||
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
|
||||
-- This one is already obsolete, raise an error.
|
||||
_G.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
|
||||
-- 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
|
||||
self.scannedlibs = oldLib.scannedlibs
|
||||
end
|
||||
if not self.libs then
|
||||
self.libs = {}
|
||||
end
|
||||
if not self.scannedlibs then
|
||||
self.scannedlibs = {}
|
||||
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)
|
||||
538
libs/ace/AceLocale-2.2/AceLocale-2.2.lua
Normal file
538
libs/ace/AceLocale-2.2/AceLocale-2.2.lua
Normal file
@ -0,0 +1,538 @@
|
||||
--[[
|
||||
Name: AceLocale-2.2
|
||||
Revision: $Rev: 17638 $
|
||||
Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team)
|
||||
Inspired By: Ace 1.x by Turan (turan@gryphon.com)
|
||||
Website: http://www.wowace.com/
|
||||
Documentation: http://www.wowace.com/index.php/AceLocale-2.2
|
||||
SVN: http://svn.wowace.com/root/trunk/Ace2/AceLocale-2.2
|
||||
Description: Localization library for addons to use to handle proper
|
||||
localization and internationalization.
|
||||
Dependencies: AceLibrary
|
||||
]]
|
||||
|
||||
local MAJOR_VERSION = "AceLocale-2.2"
|
||||
local MINOR_VERSION = "$Revision: 17638 $"
|
||||
|
||||
if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary.") end
|
||||
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
|
||||
|
||||
if loadstring("return function(...) return ... end") and AceLibrary:HasInstance(MAJOR_VERSION) then return end -- lua51 check
|
||||
local AceLocale = {}
|
||||
|
||||
local DEFAULT_LOCALE = "enUS"
|
||||
local _G = getfenv(0)
|
||||
|
||||
local BASE_TRANSLATIONS, DEBUGGING, TRANSLATIONS, BASE_LOCALE, TRANSLATION_TABLES, REVERSE_TRANSLATIONS, STRICTNESS, DYNAMIC_LOCALES, CURRENT_LOCALE, NAME
|
||||
|
||||
local rawget = rawget
|
||||
local rawset = rawset
|
||||
local type = type
|
||||
|
||||
local newRegistries = {}
|
||||
local scheduleClear
|
||||
|
||||
local lastSelf
|
||||
local __index = function(self, key)
|
||||
lastSelf = self
|
||||
local value = (rawget(self, TRANSLATIONS) or AceLocale.prototype)[key]
|
||||
rawset(self, key, value)
|
||||
return value
|
||||
end
|
||||
|
||||
local __newindex = function(self, k, v)
|
||||
if type(v) ~= "function" and type(k) ~= "table" then
|
||||
AceLocale.error(self, "Cannot change the values of an AceLocale instance.")
|
||||
end
|
||||
rawset(self, k, v)
|
||||
end
|
||||
|
||||
local __tostring = function(self)
|
||||
if type(rawget(self, 'GetLibraryVersion')) == "function" then
|
||||
return self:GetLibraryVersion()
|
||||
else
|
||||
return "AceLocale(" .. self[NAME] .. ")"
|
||||
end
|
||||
end
|
||||
|
||||
local function clearCache(self)
|
||||
if not rawget(self, BASE_TRANSLATIONS) then
|
||||
return
|
||||
end
|
||||
|
||||
local cache = self[BASE_TRANSLATIONS]
|
||||
rawset(self, REVERSE_TRANSLATIONS, nil)
|
||||
|
||||
for k in pairs(self) do
|
||||
if rawget(cache, k) ~= nil then
|
||||
self[k] = nil
|
||||
end
|
||||
end
|
||||
rawset(self, 'tmp', true)
|
||||
self.tmp = nil
|
||||
end
|
||||
|
||||
local function refixInstance(instance)
|
||||
if getmetatable(instance) then
|
||||
setmetatable(instance, nil)
|
||||
end
|
||||
local translations = instance[TRANSLATIONS]
|
||||
if translations then
|
||||
if getmetatable(translations) then
|
||||
setmetatable(translations, nil)
|
||||
end
|
||||
local baseTranslations = instance[BASE_TRANSLATIONS]
|
||||
if getmetatable(baseTranslations) then
|
||||
setmetatable(baseTranslations, nil)
|
||||
end
|
||||
if translations == baseTranslations or instance[STRICTNESS] then
|
||||
setmetatable(instance, {
|
||||
__index = __index,
|
||||
__newindex = __newindex,
|
||||
__tostring = __tostring
|
||||
})
|
||||
|
||||
setmetatable(translations, {
|
||||
__index = AceLocale.prototype
|
||||
})
|
||||
else
|
||||
setmetatable(instance, {
|
||||
__index = __index,
|
||||
__newindex = __newindex,
|
||||
__tostring = __tostring
|
||||
})
|
||||
|
||||
setmetatable(translations, {
|
||||
__index = baseTranslations,
|
||||
})
|
||||
|
||||
setmetatable(baseTranslations, {
|
||||
__index = AceLocale.prototype,
|
||||
})
|
||||
end
|
||||
else
|
||||
setmetatable(instance, {
|
||||
__index = __index,
|
||||
__newindex = __newindex,
|
||||
__tostring = __tostring,
|
||||
})
|
||||
end
|
||||
clearCache(instance)
|
||||
newRegistries[instance] = true
|
||||
scheduleClear()
|
||||
return instance
|
||||
end
|
||||
|
||||
function AceLocale:new(name)
|
||||
self:argCheck(name, 2, "string")
|
||||
|
||||
if self.registry[name] and type(rawget(self.registry[name], 'GetLibraryVersion')) ~= "function" then
|
||||
return self.registry[name]
|
||||
end
|
||||
|
||||
AceLocale.registry[name] = refixInstance({
|
||||
[STRICTNESS] = false,
|
||||
[NAME] = name,
|
||||
})
|
||||
newRegistries[AceLocale.registry[name]] = true
|
||||
return AceLocale.registry[name]
|
||||
end
|
||||
|
||||
AceLocale.prototype = { class = AceLocale }
|
||||
|
||||
function AceLocale.prototype:EnableDebugging()
|
||||
if rawget(self, BASE_TRANSLATIONS) then
|
||||
AceLocale.error(self, "Cannot enable debugging after a translation has been registered.")
|
||||
end
|
||||
rawset(self, DEBUGGING, true)
|
||||
end
|
||||
|
||||
function AceLocale.prototype:EnableDynamicLocales(override)
|
||||
AceLocale.argCheck(self, override, 2, "boolean", "nil")
|
||||
if not override and rawget(self, BASE_TRANSLATIONS) then
|
||||
AceLocale.error(self, "Cannot enable dynamic locales after a translation has been registered.")
|
||||
end
|
||||
if not rawget(self, DYNAMIC_LOCALES) then
|
||||
rawset(self, DYNAMIC_LOCALES, true)
|
||||
if rawget(self, BASE_LOCALE) then
|
||||
if not rawget(self, TRANSLATION_TABLES) then
|
||||
rawset(self, TRANSLATION_TABLES, {})
|
||||
end
|
||||
self[TRANSLATION_TABLES][self[BASE_LOCALE]] = self[BASE_TRANSLATIONS]
|
||||
self[TRANSLATION_TABLES][self[CURRENT_LOCALE]] = self[TRANSLATIONS]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function AceLocale.prototype:RegisterTranslations(locale, func)
|
||||
AceLocale.argCheck(self, locale, 2, "string")
|
||||
AceLocale.argCheck(self, func, 3, "function")
|
||||
|
||||
if locale == rawget(self, BASE_LOCALE) then
|
||||
AceLocale.error(self, "Cannot provide the same locale more than once. %q provided twice.", locale)
|
||||
end
|
||||
|
||||
if rawget(self, BASE_TRANSLATIONS) and GetLocale() ~= locale then
|
||||
if rawget(self, DEBUGGING) or rawget(self, DYNAMIC_LOCALES) then
|
||||
if not rawget(self, TRANSLATION_TABLES) then
|
||||
rawset(self, TRANSLATION_TABLES, {})
|
||||
end
|
||||
if self[TRANSLATION_TABLES][locale] then
|
||||
AceLocale.error(self, "Cannot provide the same locale more than once. %q provided twice.", locale)
|
||||
end
|
||||
local t = func()
|
||||
func = nil
|
||||
if type(t) ~= "table" then
|
||||
AceLocale.error(self, "Bad argument #3 to `RegisterTranslations'. function did not return a table. (expected table, got %s)", type(t))
|
||||
end
|
||||
self[TRANSLATION_TABLES][locale] = t
|
||||
t = nil
|
||||
end
|
||||
func = nil
|
||||
return
|
||||
end
|
||||
local t = func()
|
||||
func = nil
|
||||
if type(t) ~= "table" then
|
||||
AceLocale.error(self, "Bad argument #3 to `RegisterTranslations'. function did not return a table. (expected table, got %s)", type(t))
|
||||
end
|
||||
|
||||
rawset(self, TRANSLATIONS, t)
|
||||
if not rawget(self, BASE_TRANSLATIONS) then
|
||||
rawset(self, BASE_TRANSLATIONS, t)
|
||||
rawset(self, BASE_LOCALE, locale)
|
||||
for key,value in pairs(t) do
|
||||
if value == true then
|
||||
t[key] = key
|
||||
end
|
||||
end
|
||||
else
|
||||
for key, value in pairs(self[TRANSLATIONS]) do
|
||||
if not rawget(self[BASE_TRANSLATIONS], key) then
|
||||
AceLocale.error(self, "Improper translation exists. %q is likely misspelled for locale %s.", key, locale)
|
||||
end
|
||||
if value == true then
|
||||
AceLocale.error(self, "Can only accept true as a value on the base locale. %q is the base locale, %q is not.", rawget(self, BASE_LOCALE), locale)
|
||||
end
|
||||
end
|
||||
end
|
||||
rawset(self, CURRENT_LOCALE, locale)
|
||||
refixInstance(self)
|
||||
if rawget(self, DEBUGGING) or rawget(self, DYNAMIC_LOCALES) then
|
||||
if not rawget(self, TRANSLATION_TABLES) then
|
||||
rawset(self, TRANSLATION_TABLES, {})
|
||||
end
|
||||
self[TRANSLATION_TABLES][locale] = t
|
||||
end
|
||||
t = nil
|
||||
end
|
||||
|
||||
function AceLocale.prototype:SetLocale(locale)
|
||||
AceLocale.argCheck(self, locale, 2, "string", "boolean")
|
||||
if not rawget(self, DYNAMIC_LOCALES) then
|
||||
AceLocale.error(self, "Cannot call `SetLocale' without first calling `EnableDynamicLocales'.")
|
||||
end
|
||||
if not rawget(self, TRANSLATION_TABLES) then
|
||||
AceLocale.error(self, "Cannot call `SetLocale' without first calling `RegisterTranslations'.")
|
||||
end
|
||||
if locale == true then
|
||||
locale = GetLocale()
|
||||
if not self[TRANSLATION_TABLES][locale] then
|
||||
locale = self[BASE_LOCALE]
|
||||
end
|
||||
end
|
||||
|
||||
if self[CURRENT_LOCALE] == locale then
|
||||
return
|
||||
end
|
||||
|
||||
if not self[TRANSLATION_TABLES][locale] then
|
||||
AceLocale.error(self, "Locale %q not registered.", locale)
|
||||
end
|
||||
|
||||
self[TRANSLATIONS] = self[TRANSLATION_TABLES][locale]
|
||||
self[CURRENT_LOCALE] = locale
|
||||
refixInstance(self)
|
||||
end
|
||||
|
||||
function AceLocale.prototype:GetLocale()
|
||||
if not rawget(self, TRANSLATION_TABLES) then
|
||||
AceLocale.error(self, "Cannot call `GetLocale' without first calling `RegisterTranslations'.")
|
||||
end
|
||||
return self[CURRENT_LOCALE]
|
||||
end
|
||||
|
||||
local function iter(t, position)
|
||||
return (next(t, position))
|
||||
end
|
||||
|
||||
function AceLocale.prototype:IterateAvailableLocales()
|
||||
if not rawget(self, DYNAMIC_LOCALES) then
|
||||
AceLocale.error(self, "Cannot call `IterateAvailableLocales' without first calling `EnableDynamicLocales'.")
|
||||
end
|
||||
if not rawget(self, TRANSLATION_TABLES) then
|
||||
AceLocale.error(self, "Cannot call `IterateAvailableLocales' without first calling `RegisterTranslations'.")
|
||||
end
|
||||
return iter, self[TRANSLATION_TABLES], nil
|
||||
end
|
||||
|
||||
function AceLocale.prototype:HasLocale(locale)
|
||||
if not rawget(self, DYNAMIC_LOCALES) then
|
||||
AceLocale.error(self, "Cannot call `HasLocale' without first calling `EnableDynamicLocales'.")
|
||||
end
|
||||
AceLocale.argCheck(self, locale, 2, "string")
|
||||
return rawget(self, TRANSLATION_TABLES) and self[TRANSLATION_TABLES][locale] ~= nil
|
||||
end
|
||||
|
||||
function AceLocale.prototype:SetStrictness(strict)
|
||||
AceLocale.argCheck(self, strict, 2, "boolean")
|
||||
local mt = getmetatable(self)
|
||||
if not mt then
|
||||
AceLocale.error(self, "Cannot call `SetStrictness' without a metatable.")
|
||||
end
|
||||
if not rawget(self, TRANSLATIONS) then
|
||||
AceLocale.error(self, "No translations registered.")
|
||||
end
|
||||
rawset(self, STRICTNESS, strict)
|
||||
refixInstance(self)
|
||||
end
|
||||
|
||||
local function initReverse(self)
|
||||
rawset(self, REVERSE_TRANSLATIONS, {})
|
||||
local alpha = self[TRANSLATIONS]
|
||||
local bravo = self[REVERSE_TRANSLATIONS]
|
||||
for base, localized in pairs(alpha) do
|
||||
bravo[localized] = base
|
||||
end
|
||||
end
|
||||
|
||||
function AceLocale.prototype:GetTranslation(text)
|
||||
AceLocale.argCheck(self, text, 1, "string", "number")
|
||||
if not rawget(self, TRANSLATIONS) then
|
||||
AceLocale.error(self, "No translations registered")
|
||||
end
|
||||
return self[text]
|
||||
end
|
||||
|
||||
function AceLocale.prototype:GetStrictTranslation(text)
|
||||
AceLocale.argCheck(self, text, 1, "string", "number")
|
||||
local x = rawget(self, TRANSLATIONS)
|
||||
if not x then
|
||||
AceLocale.error(self, "No translations registered")
|
||||
end
|
||||
local value = rawget(x, text)
|
||||
if value == nil then
|
||||
AceLocale.error(self, "Translation %q does not exist for locale %s", text, self[CURRENT_LOCALE])
|
||||
end
|
||||
return value
|
||||
end
|
||||
|
||||
function AceLocale.prototype:GetReverseTranslation(text)
|
||||
local x = rawget(self, REVERSE_TRANSLATIONS)
|
||||
if not x then
|
||||
if not rawget(self, TRANSLATIONS) then
|
||||
AceLocale.error(self, "No translations registered")
|
||||
end
|
||||
initReverse(self)
|
||||
x = self[REVERSE_TRANSLATIONS]
|
||||
end
|
||||
local translation = x[text]
|
||||
if not translation then
|
||||
AceLocale.error(self, "Reverse translation for %q does not exist", text)
|
||||
end
|
||||
return translation
|
||||
end
|
||||
|
||||
function AceLocale.prototype:GetIterator()
|
||||
local x = rawget(self, TRANSLATIONS)
|
||||
if not x then
|
||||
AceLocale.error(self, "No translations registered")
|
||||
end
|
||||
return next, x, nil
|
||||
end
|
||||
|
||||
function AceLocale.prototype:GetReverseIterator()
|
||||
local x = rawget(self, REVERSE_TRANSLATIONS)
|
||||
if not x then
|
||||
if not rawget(self, TRANSLATIONS) then
|
||||
AceLocale.error(self, "No translations registered")
|
||||
end
|
||||
initReverse(self)
|
||||
x = self[REVERSE_TRANSLATIONS]
|
||||
end
|
||||
return next, x, nil
|
||||
end
|
||||
|
||||
function AceLocale.prototype:HasTranslation(text)
|
||||
AceLocale.argCheck(self, text, 1, "string", "number")
|
||||
local x = rawget(self, TRANSLATIONS)
|
||||
if not x then
|
||||
AceLocale.error(self, "No translations registered")
|
||||
end
|
||||
return rawget(x, text) and true
|
||||
end
|
||||
|
||||
function AceLocale.prototype:HasReverseTranslation(text)
|
||||
local x = rawget(self, REVERSE_TRANSLATIONS)
|
||||
if not x then
|
||||
if not rawget(self, TRANSLATIONS) then
|
||||
AceLocale.error(self, "No translations registered")
|
||||
end
|
||||
initReverse(self)
|
||||
x = self[REVERSE_TRANSLATIONS]
|
||||
end
|
||||
return x[text] and true
|
||||
end
|
||||
|
||||
function AceLocale.prototype:Debug()
|
||||
if not rawget(self, DEBUGGING) then
|
||||
return
|
||||
end
|
||||
local words = {}
|
||||
local locales = {"enUS", "deDE", "frFR", "koKR", "zhCN", "zhTW", "esES"}
|
||||
local localizations = {}
|
||||
DEFAULT_CHAT_FRAME:AddMessage("--- AceLocale Debug ---")
|
||||
for _,locale in ipairs(locales) do
|
||||
if not self[TRANSLATION_TABLES][locale] then
|
||||
DEFAULT_CHAT_FRAME:AddMessage(string.format("Locale %q not found", locale))
|
||||
else
|
||||
localizations[locale] = self[TRANSLATION_TABLES][locale]
|
||||
end
|
||||
end
|
||||
local localeDebug = {}
|
||||
for locale, localization in pairs(localizations) do
|
||||
localeDebug[locale] = {}
|
||||
for word in pairs(localization) do
|
||||
if type(localization[word]) == "table" then
|
||||
if type(words[word]) ~= "table" then
|
||||
words[word] = {}
|
||||
end
|
||||
for bit in pairs(localization[word]) do
|
||||
if type(localization[word][bit]) == "string" then
|
||||
words[word][bit] = true
|
||||
end
|
||||
end
|
||||
elseif type(localization[word]) == "string" then
|
||||
words[word] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
for word in pairs(words) do
|
||||
if type(words[word]) == "table" then
|
||||
for bit in pairs(words[word]) do
|
||||
for locale, localization in pairs(localizations) do
|
||||
if not rawget(localization, word) or not localization[word][bit] then
|
||||
localeDebug[locale][word .. "::" .. bit] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
for locale, localization in pairs(localizations) do
|
||||
if not rawget(localization, word) then
|
||||
localeDebug[locale][word] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for locale, t in pairs(localeDebug) do
|
||||
if not next(t) then
|
||||
DEFAULT_CHAT_FRAME:AddMessage(string.format("Locale %q complete", locale))
|
||||
else
|
||||
DEFAULT_CHAT_FRAME:AddMessage(string.format("Locale %q missing:", locale))
|
||||
for word in pairs(t) do
|
||||
DEFAULT_CHAT_FRAME:AddMessage(string.format(" %q", word))
|
||||
end
|
||||
end
|
||||
end
|
||||
DEFAULT_CHAT_FRAME:AddMessage("--- End AceLocale Debug ---")
|
||||
end
|
||||
|
||||
setmetatable(AceLocale.prototype, {
|
||||
__index = function(self, k)
|
||||
if type(k) ~= "table" and k ~= 0 and k ~= "GetLibraryVersion" and k ~= "error" and k ~= "assert" and k ~= "argCheck" and k ~= "pcall" then -- HACK: remove "GetLibraryVersion" and such later.
|
||||
AceLocale.error(lastSelf or self, "Translation %q does not exist.", k)
|
||||
end
|
||||
return nil
|
||||
end
|
||||
})
|
||||
|
||||
local function activate(self, oldLib, oldDeactivate)
|
||||
AceLocale = self
|
||||
|
||||
self.frame = oldLib and oldLib.frame or CreateFrame("Frame")
|
||||
self.registry = oldLib and oldLib.registry or {}
|
||||
self.BASE_TRANSLATIONS = oldLib and oldLib.BASE_TRANSLATIONS or {}
|
||||
self.DEBUGGING = oldLib and oldLib.DEBUGGING or {}
|
||||
self.TRANSLATIONS = oldLib and oldLib.TRANSLATIONS or {}
|
||||
self.BASE_LOCALE = oldLib and oldLib.BASE_LOCALE or {}
|
||||
self.TRANSLATION_TABLES = oldLib and oldLib.TRANSLATION_TABLES or {}
|
||||
self.REVERSE_TRANSLATIONS = oldLib and oldLib.REVERSE_TRANSLATIONS or {}
|
||||
self.STRICTNESS = oldLib and oldLib.STRICTNESS or {}
|
||||
self.NAME = oldLib and oldLib.NAME or {}
|
||||
self.DYNAMIC_LOCALES = oldLib and oldLib.DYNAMIC_LOCALES or {}
|
||||
self.CURRENT_LOCALE = oldLib and oldLib.CURRENT_LOCALE or {}
|
||||
|
||||
BASE_TRANSLATIONS = self.BASE_TRANSLATIONS
|
||||
DEBUGGING = self.DEBUGGING
|
||||
TRANSLATIONS = self.TRANSLATIONS
|
||||
BASE_LOCALE = self.BASE_LOCALE
|
||||
TRANSLATION_TABLES = self.TRANSLATION_TABLES
|
||||
REVERSE_TRANSLATIONS = self.REVERSE_TRANSLATIONS
|
||||
STRICTNESS = self.STRICTNESS
|
||||
NAME = self.NAME
|
||||
DYNAMIC_LOCALES = self.DYNAMIC_LOCALES
|
||||
CURRENT_LOCALE = self.CURRENT_LOCALE
|
||||
|
||||
|
||||
local GetTime = GetTime
|
||||
local timeUntilClear = GetTime() + 5
|
||||
scheduleClear = function()
|
||||
if next(newRegistries) then
|
||||
self.frame:Show()
|
||||
timeUntilClear = GetTime() + 5
|
||||
end
|
||||
end
|
||||
|
||||
if not self.registry then
|
||||
self.registry = {}
|
||||
else
|
||||
for name, instance in pairs(self.registry) do
|
||||
local name = name
|
||||
local mt = getmetatable(instance)
|
||||
setmetatable(instance, nil)
|
||||
instance[NAME] = name
|
||||
local strict
|
||||
if instance[STRICTNESS] ~= nil then
|
||||
strict = instance[STRICTNESS]
|
||||
elseif instance[TRANSLATIONS] ~= instance[BASE_TRANSLATIONS] then
|
||||
if getmetatable(instance[TRANSLATIONS]).__index == oldLib.prototype then
|
||||
strict = true
|
||||
end
|
||||
end
|
||||
instance[STRICTNESS] = strict and true or false
|
||||
refixInstance(instance)
|
||||
end
|
||||
end
|
||||
|
||||
self.frame:SetScript("OnEvent", scheduleClear)
|
||||
self.frame:SetScript("OnUpdate", function() -- (this, elapsed)
|
||||
if timeUntilClear - GetTime() <= 0 then
|
||||
self.frame:Hide()
|
||||
for k in pairs(newRegistries) do
|
||||
clearCache(k)
|
||||
newRegistries[k] = nil
|
||||
k = nil
|
||||
end
|
||||
end
|
||||
end)
|
||||
self.frame:UnregisterAllEvents()
|
||||
self.frame:RegisterEvent("ADDON_LOADED")
|
||||
self.frame:RegisterEvent("PLAYER_ENTERING_WORLD")
|
||||
self.frame:Show()
|
||||
|
||||
if oldDeactivate then
|
||||
oldDeactivate(oldLib)
|
||||
end
|
||||
end
|
||||
|
||||
AceLibrary:Register(AceLocale, MAJOR_VERSION, MINOR_VERSION, activate)
|
||||
1004
libs/ace/AceOO-2.0/AceOO-2.0.lua
Normal file
1004
libs/ace/AceOO-2.0/AceOO-2.0.lua
Normal file
File diff suppressed because it is too large
Load Diff
169
libs/ace/Banzai-1.0/Banzai-1.0.lua
Normal file
169
libs/ace/Banzai-1.0/Banzai-1.0.lua
Normal file
@ -0,0 +1,169 @@
|
||||
--[[
|
||||
Name: Banzai-1.0
|
||||
Revision: $Rev: 14544 $
|
||||
Author(s): Rabbit (rabbit.magtheridon@gmail.com), maia
|
||||
Documentation: http://www.wowace.com/index.php/Banzai-1.0_API_Documentation
|
||||
SVN: http://svn.wowace.com/root/trunk/BanzaiLib/Banzai-1.0
|
||||
Description: Aggro notification library.
|
||||
Dependencies: AceLibrary, AceEvent-2.0, RosterLib-2.0
|
||||
]]
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Locals
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
local MAJOR_VERSION = "Banzai-1.0"
|
||||
local MINOR_VERSION = "$Revision: 14544 $"
|
||||
|
||||
if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end
|
||||
if not AceLibrary:HasInstance("RosterLib-2.0") then error(MAJOR_VERSION .. " requires RosterLib-2.0.") end
|
||||
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
|
||||
|
||||
local lib = {}
|
||||
AceLibrary("AceEvent-2.0"):embed(lib)
|
||||
|
||||
local RL = nil
|
||||
local roster = nil
|
||||
local playerName = nil
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Compost Heap, courtesy of Tekkub/SEEA.
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
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 heap = {}
|
||||
setmetatable(heap, {__mode = "kv"})
|
||||
|
||||
local function acquire()
|
||||
local t = next(heap)
|
||||
if t then
|
||||
heap[t] = nil
|
||||
assert(not next(t), "A table in the compost heap has been modified!")
|
||||
end
|
||||
t = t or {}
|
||||
return t
|
||||
end
|
||||
|
||||
|
||||
local function reclaim(t, d)
|
||||
if type(t) ~= "table" then return end
|
||||
if d and d > 0 then
|
||||
for i in pairs(t) do
|
||||
if type(t[i]) == "table" then reclaim(t[i], d - 1) end
|
||||
end
|
||||
end
|
||||
for i in pairs(t) do t[i] = nil end
|
||||
table_setn(t, 0)
|
||||
heap[t] = true
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Initialization
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
-- Activate a new instance of this library
|
||||
function activate(self, oldLib, oldDeactivate)
|
||||
if oldLib then
|
||||
self.vars = oldLib.vars
|
||||
if oldLib:IsEventScheduled("UpdateAggroList") then
|
||||
oldLib:CancelScheduledEvent("UpdateAggroList")
|
||||
end
|
||||
end
|
||||
|
||||
RL = AceLibrary("RosterLib-2.0")
|
||||
roster = RL.roster
|
||||
playerName = UnitName("player")
|
||||
self:ScheduleRepeatingEvent("UpdateAggroList", self.UpdateAggroList, 0.2, self)
|
||||
|
||||
if oldDeactivate then oldDeactivate(oldLib) end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Library
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
function lib:UpdateAggroList()
|
||||
local oldBanzai = acquire()
|
||||
|
||||
if not roster then return end
|
||||
for i, unit in pairs(roster) do
|
||||
oldBanzai[unit.unitid] = unit.banzai
|
||||
|
||||
-- deduct aggro for all, increase it later for everyone with aggro
|
||||
if not unit.banzaiModifier then unit.banzaiModifier = 0 end
|
||||
unit.banzaiModifier = math.max(0, unit.banzaiModifier - 5)
|
||||
|
||||
-- check for aggro
|
||||
local targetId = unit.unitid .. "target"
|
||||
local targetName = UnitName(targetId .. "target")
|
||||
if roster[targetName] and UnitCanAttack("player", targetId) and UnitCanAttack(targetId, "player") then
|
||||
if not roster[targetName].banzaiModifier then roster[targetName].banzaiModifier = 0 end
|
||||
roster[targetName].banzaiModifier = roster[targetName].banzaiModifier + 10
|
||||
if not roster[targetName].banzaiTarget then roster[targetName].banzaiTarget = acquire() end
|
||||
table.insert(roster[targetName].banzaiTarget, targetId)
|
||||
end
|
||||
|
||||
-- cleanup
|
||||
unit.banzaiModifier = math.max(0, unit.banzaiModifier)
|
||||
unit.banzaiModifier = math.min(25, unit.banzaiModifier)
|
||||
|
||||
-- set aggro
|
||||
unit.banzai = (unit.banzaiModifier > 15)
|
||||
end
|
||||
|
||||
for i, unit in pairs(roster) do
|
||||
if oldBanzai[unit.unitid] ~= nil and oldBanzai[unit.unitid] ~= unit.banzai then
|
||||
-- Aggro status has changed.
|
||||
if unit.banzai == true and unit.banzaiTarget then
|
||||
-- Unit has aggro
|
||||
self:TriggerEvent("Banzai_UnitGainedAggro", unit.unitid, unit.banzaiTarget)
|
||||
if unit.name == playerName then
|
||||
self:TriggerEvent("Banzai_PlayerGainedAggro", unit.banzaiTarget)
|
||||
end
|
||||
elseif unit.banzai == false then
|
||||
-- Unit lost aggro
|
||||
self:TriggerEvent("Banzai_UnitLostAggro", unit.unitid)
|
||||
if unit.name == playerName then
|
||||
self:TriggerEvent("Banzai_PlayerLostAggro", unit.unitid)
|
||||
end
|
||||
end
|
||||
end
|
||||
reclaim(unit.banzaiTarget)
|
||||
unit.banzaiTarget = nil
|
||||
end
|
||||
|
||||
reclaim(oldBanzai)
|
||||
oldBanzai = nil
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- API
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
function lib:GetUnitAggroByUnitId( unitId )
|
||||
local rosterUnit = RL:GetUnitObjectFromUnit(unitId)
|
||||
if not rosterUnit then return nil end
|
||||
return rosterUnit.banzai
|
||||
end
|
||||
|
||||
function lib:GetUnitAggroByUnitName( unitName )
|
||||
local rosterUnit = RL:GetUnitObjectFromName(unitName)
|
||||
if not rosterUnit then return nil end
|
||||
return rosterUnit.banzai
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- Register
|
||||
-------------------------------------------------------------------------------
|
||||
AceLibrary:Register(lib, MAJOR_VERSION, MINOR_VERSION, activate)
|
||||
|
||||
277
libs/ace/Compost-2.0/Compost-2.0.lua
Normal file
277
libs/ace/Compost-2.0/Compost-2.0.lua
Normal file
@ -0,0 +1,277 @@
|
||||
|
||||
--[[
|
||||
Name: Compost-2.0
|
||||
Revision: $Rev: 11579 $
|
||||
Author: Tekkub Stoutwrithe (tekkub@gmail.com)
|
||||
Website: http://wiki.wowace.com/index.php/CompostLib
|
||||
Documentation: http://wiki.wowace.com/index.php/Compost-2.0_API_Documentation
|
||||
SVN: svn://svn.wowace.com/root/trunk/CompostLib/Compost-2.0
|
||||
Description: Recycle tables to reduce garbage generation
|
||||
Dependencies: AceLibrary
|
||||
]]
|
||||
|
||||
local vmajor, vminor = "Compost-2.0", "$Revision: 11579 $"
|
||||
|
||||
if not AceLibrary then error(vmajor .. " requires AceLibrary.") end
|
||||
if not AceLibrary:IsNewVersion(vmajor, vminor) then return end
|
||||
|
||||
local lib = {}
|
||||
|
||||
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
|
||||
|
||||
-- Activate a new instance of this library
|
||||
local function activate(self, oldLib, oldDeactivate)
|
||||
if oldLib then -- if upgrading
|
||||
self.var, self.k = oldLib.var, oldLib.k
|
||||
else
|
||||
self.k = { -- Constants go here
|
||||
maxcache = 10, -- I think this is a good number, I'll change it later if necessary
|
||||
}
|
||||
self.var = { -- "Local" variables go here
|
||||
cache = {},
|
||||
secondarycache = {},
|
||||
}
|
||||
|
||||
-- This makes the secondary cache table a weak table, any values in it will be reclaimed
|
||||
-- during a GC if there are no other references to them
|
||||
setmetatable(self.var.secondarycache, {__mode = "v"})
|
||||
end
|
||||
if not self.var.tablechecks then
|
||||
self.var.tablechecks = {}
|
||||
setmetatable(self.var.tablechecks, {__mode = "kv"})
|
||||
for i,v in ipairs(self.var.cache) do self.var.tablechecks[v] = true end
|
||||
for i,v in ipairs(self.var.secondarycache) do self.var.tablechecks[v] = true end
|
||||
end
|
||||
if oldDeactivate then oldDeactivate(oldLib) end
|
||||
end
|
||||
|
||||
|
||||
-- Removes an empty table from the cache and returns it
|
||||
-- or generates a new table if none available
|
||||
function lib:GetTable()
|
||||
if self.var.disabled then return {} end
|
||||
|
||||
if table.getn(self.var.cache) > 0 then
|
||||
for i in pairs(self.var.cache) do
|
||||
local t = table.remove(self.var.cache, i)
|
||||
self.var.tablechecks[t] = nil
|
||||
if next(t) then -- Table has been modified, someone holds a ref still, discard it
|
||||
error("Someone is modifying tables reclaimed by Compost!")
|
||||
self:IncDec("numdiscarded", 1)
|
||||
else -- It's clean, we think... return it.
|
||||
self:IncDec("totn", -1)
|
||||
self:IncDec("numrecycled", 1)
|
||||
return t
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if next(self.var.secondarycache) then
|
||||
for i in pairs(self.var.secondarycache) do
|
||||
local t = table.remove(self.var.secondarycache, i)
|
||||
self.var.tablechecks[t] = nil
|
||||
if next(t) then -- Table has been modified, someone holds a ref still, discard it
|
||||
error("Someone is modifying tables reclaimed by Compost!")
|
||||
self:IncDec("numdiscarded", 1)
|
||||
else -- It's clean, we think... return it.
|
||||
self:IncDec("totn", -1)
|
||||
self:IncDec("numrecycled", 1)
|
||||
return t
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self:IncDec("numnew", 1)
|
||||
return {}
|
||||
end
|
||||
|
||||
|
||||
-- Returns a table, populated with any variables passed
|
||||
-- basically: return {a1, a2, ... a20}
|
||||
function lib:Acquire(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
local t = self:GetTable()
|
||||
return self:Populate(t,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
end
|
||||
|
||||
|
||||
-- Acquires a table and fills it with values, hash style
|
||||
-- basically: return {k1 = v1, k2 = v2, ... k10 = v10}
|
||||
function lib:AcquireHash(k1,v1,k2,v2,k3,v3,k4,v4,k5,v5,k6,v6,k7,v7,k8,v8,k9,v9,k10,v10)
|
||||
local t = self:GetTable()
|
||||
return self:PopulateHash(t,k1,v1,k2,v2,k3,v3,k4,v4,k5,v5,k6,v6,k7,v7,k8,v8,k9,v9,k10,v10)
|
||||
end
|
||||
|
||||
|
||||
-- Erases the table passed, fills it with the args passed, and returns it
|
||||
-- Essentially the same as doing Reclaim then Acquire, except the same table is reused
|
||||
function lib:Recycle(t,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
t = self:Erase(t)
|
||||
return self:Populate(t,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
end
|
||||
|
||||
|
||||
-- Erases the table passed, fills it with the args passed, and returns it
|
||||
-- Essentially the same as doing Reclaim then AcquireHash, except the same table is reused
|
||||
function lib:RecycleHash(t,k1,v1,k2,v2,k3,v3,k4,v4,k5,v5,k6,v6,k7,v7,k8,v8,k9,v9,k10,v10)
|
||||
t = self:Erase(t)
|
||||
return self:PopulateHash(t,k1,v1,k2,v2,k3,v3,k4,v4,k5,v5,k6,v6,k7,v7,k8,v8,k9,v9,k10,v10)
|
||||
end
|
||||
|
||||
|
||||
-- Returns a table to the cache
|
||||
-- All tables referenced inside the passed table will be reclaimed also
|
||||
-- If a depth is passed, Reclaim will call itsself recursivly
|
||||
-- to reclaim all tables contained in t to the depth specified
|
||||
function lib:Reclaim(t, depth)
|
||||
if type(t) ~= "table" or self.var.disabled then return end
|
||||
self:assert(not self.var.tablechecks[t], "Cannot reclaim a table twice")
|
||||
|
||||
if not self:ItemsInSecondaryCache() then self.var.totn = table.getn(self.var.cache) end
|
||||
|
||||
if depth and depth > 0 then
|
||||
for i in pairs(t) do
|
||||
if type(t[i]) == "table" then self:Reclaim(t[i], depth - 1) end
|
||||
end
|
||||
end
|
||||
self:Erase(t)
|
||||
if self.k.maxcache and table.getn(self.var.cache) >= self.k.maxcache then
|
||||
table.insert(self.var.secondarycache, t)
|
||||
else
|
||||
table.insert(self.var.cache, t)
|
||||
end
|
||||
self:IncDec("numreclaim", 1)
|
||||
self:IncDec("totn", 1)
|
||||
self.var.maxn = math.max(self.var.maxn or 0, self.var.totn)
|
||||
self.var.tablechecks[t] = true
|
||||
end
|
||||
|
||||
|
||||
-- Reclaims multiple tables, can take 10 recursive sets or 20 non-recursives,
|
||||
-- or any combination of the two. Pass args in the following manner:
|
||||
-- table1, depth1, tabl2, depth2, table3, table4, table5, depth5, ...
|
||||
function lib:ReclaimMulti(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
if not a1 then return end
|
||||
if type(a2) == "number" then
|
||||
self:Reclaim(a1, a2)
|
||||
self:ReclaimMulti(a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
else
|
||||
self:Reclaim(a1)
|
||||
self:ReclaimMulti(a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Erases the table passed, nothing more nothing less :)
|
||||
-- Tables referenced inside the passed table are NOT erased
|
||||
function lib:Erase(t)
|
||||
if type(t) ~= "table" then return end
|
||||
if self.var.disabled then return {} end
|
||||
local mem = gcinfo()
|
||||
setmetatable(t, nil)
|
||||
for i in pairs(t) do
|
||||
t[i] = nil
|
||||
end
|
||||
t.reset = 1
|
||||
t.reset = nil
|
||||
table_setn(t, 0)
|
||||
self:IncDec("memfreed", math.abs(gcinfo() - mem))
|
||||
self:IncDec("numerased", 1)
|
||||
return t
|
||||
end
|
||||
|
||||
|
||||
-- Fills the table passed with the args passed
|
||||
function lib:Populate(t,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15,a16,a17,a18,a19,a20)
|
||||
if not t then return end
|
||||
if a1 ~= nil then table.insert(t, a1) end
|
||||
if a2 ~= nil then table.insert(t, a2) end
|
||||
if a3 ~= nil then table.insert(t, a3) end
|
||||
if a4 ~= nil then table.insert(t, a4) end
|
||||
if a5 ~= nil then table.insert(t, a5) end
|
||||
if a6 ~= nil then table.insert(t, a6) end
|
||||
if a7 ~= nil then table.insert(t, a7) end
|
||||
if a8 ~= nil then table.insert(t, a8) end
|
||||
if a9 ~= nil then table.insert(t, a9) end
|
||||
if a10 ~= nil then table.insert(t, a10) end
|
||||
if a11 ~= nil then table.insert(t, a11) end
|
||||
if a12 ~= nil then table.insert(t, a12) end
|
||||
if a13 ~= nil then table.insert(t, a13) end
|
||||
if a14 ~= nil then table.insert(t, a14) end
|
||||
if a15 ~= nil then table.insert(t, a15) end
|
||||
if a16 ~= nil then table.insert(t, a16) end
|
||||
if a17 ~= nil then table.insert(t, a17) end
|
||||
if a18 ~= nil then table.insert(t, a18) end
|
||||
if a19 ~= nil then table.insert(t, a19) end
|
||||
if a20 ~= nil then table.insert(t, a20) end
|
||||
return t
|
||||
end
|
||||
|
||||
|
||||
-- Same as Populate, but takes 10 key-value pairs instead
|
||||
function lib:PopulateHash(t,k1,v1,k2,v2,k3,v3,k4,v4,k5,v5,k6,v6,k7,v7,k8,v8,k9,v9,k10,v10)
|
||||
if not t then return end
|
||||
if k1 ~= nil then t[k1] = v1 end
|
||||
if k2 ~= nil then t[k2] = v2 end
|
||||
if k3 ~= nil then t[k3] = v3 end
|
||||
if k4 ~= nil then t[k4] = v4 end
|
||||
if k5 ~= nil then t[k5] = v5 end
|
||||
if k6 ~= nil then t[k6] = v6 end
|
||||
if k7 ~= nil then t[k7] = v7 end
|
||||
if k8 ~= nil then t[k8] = v8 end
|
||||
if k9 ~= nil then t[k9] = v9 end
|
||||
if k10 ~= nil then t[k10] = v10 end
|
||||
return t
|
||||
end
|
||||
|
||||
|
||||
function lib:IncDec(variable, diff)
|
||||
self.var[variable] = (self.var[variable] or 0) + diff
|
||||
end
|
||||
|
||||
|
||||
function lib:ItemsInSecondaryCache()
|
||||
for i in pairs(self.var.secondarycache) do return true end
|
||||
end
|
||||
|
||||
|
||||
function lib:GetSecondaryCacheSize()
|
||||
local n = 0
|
||||
for i in pairs(self.var.secondarycache) do n = n + 1 end
|
||||
return n
|
||||
end
|
||||
|
||||
|
||||
-- Prints out statistics on table recycling
|
||||
-- /script CompostLib:GetInstance("compost-1"):Stats()
|
||||
function lib:Stats()
|
||||
if self.var.disabled then ChatFrame1:AddMessage("CompostLib is disabled!")
|
||||
else ChatFrame1:AddMessage(
|
||||
string.format(
|
||||
"|cff00ff00New: %d|r | |cffffff00Recycled: %d|r | |cff00ffffMain: %d|r | |cffff0000Secondary: %d|r | |cffff8800Max %d|r | |cff888888Erases: %d|r | |cffff00ffMem Saved: %d KiB|r | |cffff0088Lost to GC: %d",
|
||||
self.var.numnew or 0,
|
||||
self.var.numrecycled or 0,
|
||||
table.getn(self.var.cache),
|
||||
self:GetSecondaryCacheSize(),
|
||||
self.var.maxn or 0,
|
||||
(self.var.numerased or 0) - (self.var.numreclaim or 0),
|
||||
(self.var.memfreed or 0) + 32/1024*(self.var.numrecycled or 0),
|
||||
(self.var.numreclaim or 0) - (self.var.numrecycled or 0) - table.getn(self.var.cache)))
|
||||
end
|
||||
end
|
||||
|
||||
setmetatable(lib, { __call = lib.Acquire })
|
||||
|
||||
--------------------------------
|
||||
-- Load this bitch! --
|
||||
--------------------------------
|
||||
AceLibrary:Register(lib, vmajor, vminor, activate)
|
||||
lib = nil
|
||||
343
libs/ace/Deformat-2.0/Deformat-2.0.lua
Normal file
343
libs/ace/Deformat-2.0/Deformat-2.0.lua
Normal file
@ -0,0 +1,343 @@
|
||||
--[[
|
||||
Name: Deformat-2.0
|
||||
Revision: $Rev: 6804 $
|
||||
Author(s): ckknight (ckknight@gmail.com)
|
||||
Website: http://ckknight.wowinterface.com/
|
||||
Documentation: http://wiki.wowace.com/index.php/Deformat-2.0
|
||||
SVN: http://svn.wowace.com/root/trunk/Deformat/Deformat-2.0
|
||||
Description: A library to deformat format strings.
|
||||
Dependencies: AceLibrary
|
||||
]]
|
||||
|
||||
local MAJOR_VERSION = "Deformat-2.0"
|
||||
local MINOR_VERSION = "$Revision: 6804 $"
|
||||
|
||||
|
||||
if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end
|
||||
if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
|
||||
|
||||
local Deformat = {}
|
||||
|
||||
do
|
||||
local sequences = {
|
||||
["%d*d"] = "%%-?%%d+",
|
||||
["s"] = ".+",
|
||||
["[fg]"] = "%%-?%%d+%%.%%d+",
|
||||
["%%%.%d[fg]"] = "%%-?%%d+%%.?%%d*",
|
||||
["c"] = ".",
|
||||
}
|
||||
local curries = {}
|
||||
|
||||
local function doNothing(item)
|
||||
return item
|
||||
end
|
||||
local v = {}
|
||||
|
||||
local function concat(a1, a2, a3, a4, a5)
|
||||
local left, right
|
||||
if not a2 then
|
||||
return a1
|
||||
elseif not a3 then
|
||||
left, right = a1, a2
|
||||
elseif not a4 then
|
||||
return concat(concat(a1, a2), a3)
|
||||
elseif not a5 then
|
||||
return concat(concat(concat(a1, a2), a3), a4)
|
||||
else
|
||||
return concat(concat(concat(concat(a1, a2), a3), a4), a5)
|
||||
end
|
||||
if not string.find(left, "%%1%$") and not string.find(right, "%%1%$") then
|
||||
return left .. right
|
||||
elseif not string.find(right, "%%1%$") then
|
||||
local i
|
||||
for j = 9, 1, -1 do
|
||||
if string.find(left, "%%" .. j .. "%$") then
|
||||
i = j
|
||||
break
|
||||
end
|
||||
end
|
||||
while true do
|
||||
local first
|
||||
local firstPat
|
||||
for x, y in pairs(sequences) do
|
||||
local i = string.find(right, "%%" .. x)
|
||||
if not first or (i and i < first) then
|
||||
first = i
|
||||
firstPat = x
|
||||
end
|
||||
end
|
||||
if not first then
|
||||
break
|
||||
end
|
||||
i = i + 1
|
||||
right = string.gsub(right, "%%(" .. firstPat .. ")", "%%" .. i .. "$%1")
|
||||
end
|
||||
return left .. right
|
||||
elseif not string.find(left, "%%1%$") then
|
||||
local i = 1
|
||||
while true do
|
||||
local first
|
||||
local firstPat
|
||||
for x, y in pairs(sequences) do
|
||||
local i = string.find(left, "%%" .. x)
|
||||
if not first or (i and i < first) then
|
||||
first = i
|
||||
firstPat = x
|
||||
end
|
||||
end
|
||||
if not first then
|
||||
break
|
||||
end
|
||||
i = i + 1
|
||||
left = string.gsub(left, "%%(" .. firstPat .. ")", "%%" .. i .. "$%1")
|
||||
end
|
||||
return concat(left, right)
|
||||
else
|
||||
local i
|
||||
for j = 9, 1, -1 do
|
||||
if string.find(left, "%%" .. j .. "%$") then
|
||||
i = j
|
||||
break
|
||||
end
|
||||
end
|
||||
local j
|
||||
for k = 9, 1, -1 do
|
||||
if string.find(right, "%%" .. k .. "%$") then
|
||||
j = k
|
||||
break
|
||||
end
|
||||
end
|
||||
for k = j, 1, -1 do
|
||||
right = string.gsub(right, "%%" .. k .. "%$", "%%" .. k + i .. "%$")
|
||||
end
|
||||
return left .. right
|
||||
end
|
||||
end
|
||||
|
||||
local function Curry(a1, a2, a3, a4, a5)
|
||||
local pattern = concat(a1, a2, a3, a4, a5)
|
||||
if not string.find(pattern, "%%1%$") then
|
||||
local unpattern = string.gsub(pattern, "([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1")
|
||||
local f = {}
|
||||
local i = 0
|
||||
while true do
|
||||
local first
|
||||
local firstPat
|
||||
for x, y in pairs(sequences) do
|
||||
local i = string.find(unpattern, "%%%%" .. x)
|
||||
if not first or (i and i < first) then
|
||||
first = i
|
||||
firstPat = x
|
||||
end
|
||||
end
|
||||
if not first then
|
||||
break
|
||||
end
|
||||
unpattern = string.gsub(unpattern, "%%%%" .. firstPat, "(" .. sequences[firstPat] .. ")", 1)
|
||||
i = i + 1
|
||||
if firstPat == "c" or firstPat == "s" then
|
||||
table.insert(f, doNothing)
|
||||
else
|
||||
table.insert(f, tonumber)
|
||||
end
|
||||
end
|
||||
unpattern = "^" .. unpattern .. "$"
|
||||
local _,alpha, bravo, charlie, delta, echo, foxtrot, golf, hotel, india
|
||||
if i == 0 then
|
||||
return
|
||||
elseif i == 1 then
|
||||
return function(text)
|
||||
_,_,alpha = string.find(text, unpattern)
|
||||
if alpha then
|
||||
return f[1](alpha)
|
||||
end
|
||||
end
|
||||
elseif i == 2 then
|
||||
return function(text)
|
||||
_,_,alpha, bravo = string.find(text, unpattern)
|
||||
if alpha then
|
||||
return f[1](alpha), f[2](bravo)
|
||||
end
|
||||
end
|
||||
elseif i == 3 then
|
||||
return function(text)
|
||||
_,_,alpha, bravo, charlie = string.find(text, unpattern)
|
||||
if alpha then
|
||||
return f[1](alpha), f[2](bravo), f[3](charlie)
|
||||
end
|
||||
end
|
||||
elseif i == 4 then
|
||||
return function(text)
|
||||
_,_,alpha, bravo, charlie, delta = string.find(text, unpattern)
|
||||
if alpha then
|
||||
return f[1](alpha), f[2](bravo), f[3](charlie), f[4](delta)
|
||||
end
|
||||
end
|
||||
elseif i == 5 then
|
||||
return function(text)
|
||||
_,_,alpha, bravo, charlie, delta, echo = string.find(text, unpattern)
|
||||
if alpha then
|
||||
return f[1](alpha), f[2](bravo), f[3](charlie), f[4](delta), f[5](echo)
|
||||
end
|
||||
end
|
||||
elseif i == 6 then
|
||||
return function(text)
|
||||
_,_,alpha, bravo, charlie, delta, echo, foxtrot = string.find(text, unpattern)
|
||||
if alpha then
|
||||
return f[1](alpha), f[2](bravo), f[3](charlie), f[4](delta), f[5](echo), f[6](foxtrot)
|
||||
end
|
||||
end
|
||||
elseif i == 7 then
|
||||
return function(text)
|
||||
_,_,alpha, bravo, charlie, delta, echo, foxtrot, golf = string.find(text, unpattern)
|
||||
if alpha then
|
||||
return f[1](alpha), f[2](bravo), f[3](charlie), f[4](delta), f[5](echo), f[6](foxtrot), f[7](golf)
|
||||
end
|
||||
end
|
||||
elseif i == 8 then
|
||||
return function(text)
|
||||
_,_,alpha, bravo, charlie, delta, echo, foxtrot, golf, hotel = string.find(text, unpattern)
|
||||
if alpha then
|
||||
return f[1](alpha), f[2](bravo), f[3](charlie), f[4](delta), f[5](echo), f[6](foxtrot), f[7](golf), f[8](hotel)
|
||||
end
|
||||
end
|
||||
else
|
||||
return function(text)
|
||||
_,_,alpha, bravo, charlie, delta, echo, foxtrot, golf, hotel, india = string.find(text, unpattern)
|
||||
if alpha then
|
||||
return f[1](alpha), f[2](bravo), f[3](charlie), f[4](delta), f[5](echo), f[6](foxtrot), f[7](golf), f[8](hotel), f[9](india)
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
local o = {}
|
||||
local f = {}
|
||||
local unpattern = string.gsub(pattern, "([%(%)%.%*%+%-%[%]%?%^%$%%])", "%%%1")
|
||||
local i = 1
|
||||
while true do
|
||||
local pat
|
||||
for x, y in pairs(sequences) do
|
||||
if not pat and string.find(unpattern, "%%%%" .. i .. "%%%$" .. x) then
|
||||
pat = x
|
||||
break
|
||||
end
|
||||
end
|
||||
if not pat then
|
||||
break
|
||||
end
|
||||
unpattern = string.gsub(unpattern, "%%%%" .. i .. "%%%$" .. pat, "(" .. sequences[pat] .. ")", 1)
|
||||
if pat == "c" or pat == "s" then
|
||||
table.insert(f, doNothing)
|
||||
else
|
||||
table.insert(f, tonumber)
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
i = 1
|
||||
string.gsub(pattern, "%%(%d)%$", function(w) o[i] = tonumber(w); i = i + 1; end)
|
||||
v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9] = nil
|
||||
for x, y in pairs(f) do
|
||||
v[x] = f[y]
|
||||
end
|
||||
for x, y in pairs(v) do
|
||||
f[x] = v[x]
|
||||
end
|
||||
unpattern = "^" .. unpattern .. "$"
|
||||
i = i - 1
|
||||
if i == 0 then
|
||||
return function(text)
|
||||
return
|
||||
end
|
||||
elseif i == 1 then
|
||||
return function(text)
|
||||
_,_,v[1] = string.find(text, unpattern)
|
||||
if v[1] then
|
||||
return f[1](v[1])
|
||||
end
|
||||
end
|
||||
elseif i == 2 then
|
||||
return function(text)
|
||||
_,_,v[1],v[2] = string.find(text, unpattern)
|
||||
if v[1] then
|
||||
return f[1](v[o[1]]), f[2](v[o[2]])
|
||||
end
|
||||
end
|
||||
elseif i == 3 then
|
||||
return function(text)
|
||||
_,_,v[1],v[2],v[3] = string.find(text, unpattern)
|
||||
if v[1] then
|
||||
return f[1](v[o[1]]), f[2](v[o[2]]), f[3](v[o[3]])
|
||||
end
|
||||
end
|
||||
elseif i == 4 then
|
||||
return function(text)
|
||||
_,_,v[1],v[2],v[3],v[4] = string.find(text, unpattern)
|
||||
if v[1] then
|
||||
return f[1](v[o[1]]), f[2](v[o[2]]), f[3](v[o[3]]), f[4](v[o[4]])
|
||||
end
|
||||
end
|
||||
elseif i == 5 then
|
||||
return function(text)
|
||||
_,_,v[1],v[2],v[3],v[4],v[5] = string.find(text, unpattern)
|
||||
if v[1] then
|
||||
return f[1](v[o[1]]), f[2](v[o[2]]), f[3](v[o[3]]), f[4](v[o[4]]), f[5](v[o[5]])
|
||||
end
|
||||
end
|
||||
elseif i == 6 then
|
||||
return function(text)
|
||||
_,_,v[1],v[2],v[3],v[4],v[5],v[6] = string.find(text, unpattern)
|
||||
if v[1] then
|
||||
return f[1](v[o[1]]), f[2](v[o[2]]), f[3](v[o[3]]), f[4](v[o[4]]), f[5](v[o[5]]), f[6](v[o[6]])
|
||||
end
|
||||
end
|
||||
elseif i == 7 then
|
||||
return function(text)
|
||||
_,_,v[1],v[2],v[3],v[4],v[5],v[6],v[7] = string.find(text, unpattern)
|
||||
if v[1] then
|
||||
return f[1](v[o[1]]), f[2](v[o[2]]), f[3](v[o[3]]), f[4](v[o[4]]), f[5](v[o[5]]), f[6](v[o[6]]), f[7](v[o[7]])
|
||||
end
|
||||
end
|
||||
elseif i == 8 then
|
||||
return function(text)
|
||||
_,_,v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8] = string.find(text, unpattern)
|
||||
if v[1] then
|
||||
return f[1](v[o[1]]), f[2](v[o[2]]), f[3](v[o[3]]), f[4](v[o[4]]), f[5](v[o[5]]), f[6](v[o[6]]), f[7](v[o[7]]), f[8](v[o[8]])
|
||||
end
|
||||
end
|
||||
else
|
||||
return function(text)
|
||||
_,_,v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9] = string.find(text, unpattern)
|
||||
if v[1] then
|
||||
return f[1](v[o[1]]), f[2](v[o[2]]), f[3](v[o[3]]), f[4](v[o[4]]), f[5](v[o[5]]), f[6](v[o[6]]), f[7](v[o[7]]), f[8](v[o[8]]), f[9](v[o[9]])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Deformat:Deformat(text, a1, a2, a3, a4, a5)
|
||||
self:argCheck(text, 2, "string")
|
||||
self:argCheck(a1, 3, "string")
|
||||
local pattern = a1
|
||||
if a5 then
|
||||
pattern = a1 .. a2 .. a3 .. a4 .. a5
|
||||
elseif a4 then
|
||||
pattern = a1 .. a2 .. a3 .. a4
|
||||
elseif a3 then
|
||||
pattern = a1 .. a2 .. a3
|
||||
elseif a2 then
|
||||
pattern = a1 .. a2
|
||||
end
|
||||
if curries[pattern] == nil then
|
||||
curries[pattern] = Curry(a1, a2, a3, a4, a5)
|
||||
end
|
||||
return curries[pattern](text)
|
||||
end
|
||||
end
|
||||
|
||||
local mt = getmetatable(Deformat) or {}
|
||||
mt.__call = Deformat.Deformat
|
||||
setmetatable(Deformat, mt)
|
||||
|
||||
AceLibrary:Register(Deformat, MAJOR_VERSION, MINOR_VERSION)
|
||||
Deformat = nil
|
||||
220
libs/ace/Gratuity-2.0/Gratuity-2.0.lua
Normal file
220
libs/ace/Gratuity-2.0/Gratuity-2.0.lua
Normal file
@ -0,0 +1,220 @@
|
||||
--[[
|
||||
Name: Gratuity-2.0
|
||||
Revision: $Rev: 11053 $
|
||||
Author: Tekkub Stoutwrithe (tekkub@gmail.com)
|
||||
Website: http://wiki.wowace.com/index.php/GratuityLib
|
||||
Documentation: http://wiki.wowace.com/index.php/Gratuity-2.0_API_Documentation
|
||||
SVN: svn://svn.wowace.com/root/trunk/GratuityLib/Gratuity-2.0
|
||||
Description: Tooltip parsing library
|
||||
Dependencies: AceLibrary, (optional) Compost-2.0, (optional) Deformat-2.0
|
||||
]]
|
||||
|
||||
local vmajor, vminor = "Gratuity-2.0", "$Revision: 11053 $"
|
||||
|
||||
if not AceLibrary then error(vmajor .. " requires AceLibrary.") end
|
||||
if not AceLibrary:IsNewVersion(vmajor, vminor) then return end
|
||||
|
||||
local lib = {}
|
||||
local methods = {
|
||||
"SetBagItem", "SetAction", "SetAuctionItem", "SetAuctionSellItem", "SetBuybackItem",
|
||||
"SetCraftItem", "SetCraftSpell", "SetHyperlink", "SetInboxItem", "SetInventoryItem",
|
||||
"SetLootItem", "SetLootRollItem", "SetMerchantItem", "SetPetAction", "SetPlayerBuff",
|
||||
"SetQuestItem", "SetQuestLogItem", "SetQuestRewardSpell", "SetSendMailItem", "SetShapeshift",
|
||||
"SetSpell", "SetTalent", "SetTrackingSpell", "SetTradePlayerItem", "SetTradeSkillItem", "SetTradeTargetItem",
|
||||
"SetTrainerService", "SetUnit", "SetUnitBuff", "SetUnitDebuff",
|
||||
}
|
||||
|
||||
|
||||
-- Activate a new instance of this library
|
||||
local function activate(self, oldLib, oldDeactivate)
|
||||
if oldLib then self.vars = oldLib.vars
|
||||
else
|
||||
self.vars = {}
|
||||
self:CreateTooltip()
|
||||
end
|
||||
|
||||
self:CreateSetMethods()
|
||||
|
||||
if oldDeactivate then oldDeactivate(oldLib) end
|
||||
end
|
||||
|
||||
|
||||
function lib:InitCompost()
|
||||
if not self.vars.compost and AceLibrary:HasInstance("Compost-2.0") then self.vars.compost = AceLibrary("Compost-2.0") end
|
||||
end
|
||||
|
||||
|
||||
function lib:CreateTooltip()
|
||||
local tt = CreateFrame("GameTooltip")
|
||||
|
||||
self.vars.tooltip = tt
|
||||
tt:SetOwner(tt, "ANCHOR_NONE")
|
||||
-- tooltip:SetParent()
|
||||
|
||||
self.vars.Llines, self.vars.Rlines = {}, {}
|
||||
for i=1,30 do
|
||||
self.vars.Llines[i], self.vars.Rlines[i] = tt:CreateFontString(), tt:CreateFontString()
|
||||
self.vars.Llines[i]:SetFontObject(GameFontNormal)
|
||||
self.vars.Rlines[i]:SetFontObject(GameFontNormal)
|
||||
tt:AddFontStrings(self.vars.Llines[i], self.vars.Rlines[i])
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Clears the tooltip completely, none of this "erase left, hide right" crap blizzard does
|
||||
function lib:Erase()
|
||||
self.vars.tooltip:ClearLines() -- Ensures tooltip's NumLines is reset
|
||||
for i=1,30 do self.vars.Rlines[i]:SetText() end -- Clear text from right side (ClearLines only hides them)
|
||||
if not self.vars.tooltip:IsOwned(self.vars.tooltip) then self.vars.tooltip:SetOwner(self.vars.tooltip, "ANCHOR_NONE") end
|
||||
self:assert(self.vars.tooltip:IsOwned(self.vars.tooltip), "Gratuity's tooltip is not scanable")
|
||||
end
|
||||
|
||||
|
||||
-- Get the number of lines
|
||||
-- Arg: endln - If passed and tooltip's NumLines is higher, endln is returned back
|
||||
function lib:NumLines(endln)
|
||||
local num = self.vars.tooltip:NumLines()
|
||||
return endln and num > endln and endln or num or 0
|
||||
end
|
||||
|
||||
local FindDefault = function(str, pattern)
|
||||
return string.find(str, pattern);
|
||||
end;
|
||||
|
||||
local FindExact = function(str, pattern)
|
||||
if (str == pattern) then
|
||||
return string.find(str, pattern);
|
||||
end;
|
||||
end;
|
||||
|
||||
-- If text is found on tooltip then results of string.find are returned
|
||||
-- Args:
|
||||
-- txt - The text string to find
|
||||
-- startln - First tooltip line to check, default 1
|
||||
-- endln - Last line to test, default 30
|
||||
-- ignoreleft / ignoreright - Causes text on one side of the tooltip to be ignored
|
||||
-- exact - the compare will be an exact match vs the default behaviour of
|
||||
function lib:Find(txt, startln, endln, ignoreleft, ignoreright, exact)
|
||||
local searchFunction = FindDefault;
|
||||
if (exact == true) then
|
||||
searchFunction = FindExact;
|
||||
end;
|
||||
self:argCheck(txt, 2, "string", "number")
|
||||
local t1, t2 = type(startln or 1), type(self:NumLines(endln))
|
||||
if (t1 ~= "number" or t2 ~= "number") then print(t1, t2, (startln or 1),self:NumLines(endln)) end
|
||||
for i=(startln or 1),self:NumLines(endln) do
|
||||
if not ignoreleft then
|
||||
local txtl = self.vars.Llines[i]:GetText()
|
||||
if (txtl and searchFunction(txtl, txt)) then return string.find(txtl, txt) end
|
||||
end
|
||||
|
||||
if not ignoreright then
|
||||
local txtr = self.vars.Rlines[i]:GetText()
|
||||
if (txtr and searchFunction(txtr, txt)) then return string.find(txtr, txt) end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Calls Find many times.
|
||||
-- Args are passed directly to Find, t1-t10 replace the txt arg
|
||||
-- Returns Find results for the first match found, if any
|
||||
function lib:MultiFind(startln, endln, ignoreleft, ignoreright, t1,t2,t3,t4,t5,t6,t7,t8,t9,t10)
|
||||
self:argCheck(t1, 6, "string", "number")
|
||||
if t1 and self:Find(t1, startln, endln, ignoreleft, ignoreright) then return self:Find(t1, startln, endln, ignoreleft, ignoreright)
|
||||
elseif t2 then return self:MultiFind(startln, endln, ignoreleft, ignoreright, t2,t3,t4,t5,t6,t7,t8,t9,t10) end
|
||||
end
|
||||
|
||||
|
||||
local deformat
|
||||
-- If text is found on tooltip then results of deformat:Deformat are returned
|
||||
-- Args:
|
||||
-- txt - The text string to deformat and serach for
|
||||
-- startln - First tooltip line to check, default 1
|
||||
-- endln - Last line to test, default 30
|
||||
-- ignoreleft / ignoreright - Causes text on one side of the tooltip to be ignored
|
||||
function lib:FindDeformat(txt, startln, endln, ignoreleft, ignoreright)
|
||||
self:argCheck(txt, 2, "string", "number")
|
||||
if not deformat then
|
||||
self:assert(AceLibrary:HasInstance("Deformat-2.0"), "FindDeformat requires Deformat-2.0 to be available")
|
||||
deformat = AceLibrary("Deformat-2.0")
|
||||
end
|
||||
|
||||
for i=(startln or 1),self:NumLines(endln) do
|
||||
if not ignoreleft then
|
||||
local txtl = self.vars.Llines[i]:GetText()
|
||||
if (txtl and deformat(txtl, txt)) then return deformat(txtl, txt) end
|
||||
end
|
||||
|
||||
if not ignoreright then
|
||||
local txtr = self.vars.Rlines[i]:GetText()
|
||||
if (txtr and deformat(txtr, txt)) then return deformat(txtr, txt) end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Returns a table of strings pulled from the tooltip, or nil if no strings in tooltip
|
||||
-- Args:
|
||||
-- startln - First tooltip line to check, default 1
|
||||
-- endln - Last line to test, default 30
|
||||
-- ignoreleft / ignoreright - Causes text on one side of the tooltip to be ignored
|
||||
function lib:GetText(startln, endln, ignoreleft, ignoreright)
|
||||
self:InitCompost()
|
||||
local retval
|
||||
|
||||
for i=(startln or 1),(endln or 30) do
|
||||
local txtl, txtr
|
||||
if not ignoreleft then txtl = self.vars.Llines[i]:GetText() end
|
||||
if not ignoreright then txtr = self.vars.Rlines[i]:GetText() end
|
||||
if txtl or txtr then
|
||||
if not retval then retval = self.vars.compost and self.vars.compost:Acquire() or {} end
|
||||
local t = self.vars.compost and self.vars.compost:Acquire(txtl, txtr) or {txtl, txtr}
|
||||
table.insert(retval, t)
|
||||
end
|
||||
end
|
||||
|
||||
return retval
|
||||
end
|
||||
|
||||
|
||||
-- Returns the text from a specific line (both left and right unless second arg is true)
|
||||
-- Args:
|
||||
-- line - the line number you wish to retrieve
|
||||
-- getright - if passed the right line will be returned, if not the left will be returned
|
||||
function lib:GetLine(line, getright)
|
||||
self:argCheck(line, 2, "number")
|
||||
if self.vars.tooltip:NumLines() < line then return end
|
||||
if getright then return self.vars.Rlines[line] and self.vars.Rlines[line]:GetText()
|
||||
elseif self.vars.Llines[line] then
|
||||
return self.vars.Llines[line]:GetText(), self.vars.Rlines[line]:GetText()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-----------------------------------
|
||||
-- Set tooltip methods --
|
||||
-----------------------------------
|
||||
|
||||
-- These methods are designed to immitate the GameTooltip API
|
||||
local testmethods = {
|
||||
SetAction = function(id) return HasAction(id) end,
|
||||
}
|
||||
local gettrue = function() return true end
|
||||
function lib:CreateSetMethods()
|
||||
for _,m in pairs(methods) do
|
||||
local meth = m
|
||||
local func = testmethods[meth] or gettrue
|
||||
self[meth] = function(self,a1,a2,a3,a4)
|
||||
self:Erase()
|
||||
if not func(a1,a2,a3,a4) then return end
|
||||
return self:pcall(self.vars.tooltip[meth], self.vars.tooltip,a1,a2,a3,a4) end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--------------------------------
|
||||
-- Load this bitch! --
|
||||
--------------------------------
|
||||
AceLibrary:Register(lib, vmajor, vminor, activate)
|
||||
lib = nil
|
||||
393
libs/ace/RosterLib-2.0/RosterLib-2.0.lua
Normal file
393
libs/ace/RosterLib-2.0/RosterLib-2.0.lua
Normal file
@ -0,0 +1,393 @@
|
||||
--[[
|
||||
Name: RosterLib-2.0
|
||||
Revision: $Revision: 16213 $
|
||||
X-ReleaseDate: $Date: 2006-08-10 08:55:29 +0200 (Thu, 10 Aug 2006) $
|
||||
Author: Maia (maia.proudmoore@gmail.com)
|
||||
Website: http://wiki.wowace.com/index.php/RosterLib-2.0
|
||||
Documentation: http://wiki.wowace.com/index.php/RosterLib-2.0_API_Documentation
|
||||
SVN: http://svn.wowace.com/root/trunk/RosterLib-2.0/
|
||||
Description: party/raid roster management
|
||||
Dependencies: AceLibrary, AceOO-2.0, AceEvent-2.0
|
||||
]]
|
||||
|
||||
local MAJOR_VERSION = "RosterLib-2.0"
|
||||
local MINOR_VERSION = "$Revision: 16213 $"
|
||||
|
||||
if not AceLibrary then error(vmajor .. " 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
|
||||
if not AceLibrary:HasInstance("AceEvent-2.0") then error(MAJOR_VERSION .. " requires AceEvent-2.0") end
|
||||
|
||||
local updatedUnits = {}
|
||||
local unknownUnits = {}
|
||||
local RosterLib = {}
|
||||
local roster
|
||||
|
||||
------------------------------------------------
|
||||
-- activate, enable, disable
|
||||
------------------------------------------------
|
||||
|
||||
local function print(text)
|
||||
ChatFrame3:AddMessage(text)
|
||||
end
|
||||
|
||||
local function activate(self, oldLib, oldDeactivate)
|
||||
RosterLib = self
|
||||
if oldLib then
|
||||
self.roster = oldLib.roster
|
||||
oldLib:UnregisterAllEvents()
|
||||
oldLib:CancelAllScheduledEvents()
|
||||
end
|
||||
if not self.roster then self.roster = {} end
|
||||
if oldDeactivate then oldDeactivate(oldLib) end
|
||||
roster = self.roster
|
||||
end
|
||||
|
||||
|
||||
local function external(self, major, instance)
|
||||
if major == "AceEvent-2.0" then
|
||||
AceEvent = instance
|
||||
AceEvent:embed(self)
|
||||
self:UnregisterAllEvents()
|
||||
self:CancelAllScheduledEvents()
|
||||
if AceEvent:IsFullyInitialized() then
|
||||
self:AceEvent_FullyInitialized()
|
||||
else
|
||||
self:RegisterEvent("AceEvent_FullyInitialized", "AceEvent_FullyInitialized", true)
|
||||
end
|
||||
elseif major == "Compost-2.0" then
|
||||
Compost = instance
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function RosterLib:Enable()
|
||||
-- not used anymore, but as addons still might be calling this method, we're keeping it.
|
||||
end
|
||||
|
||||
|
||||
function RosterLib:Disable()
|
||||
-- not used anymore, but as addons still might be calling this method, we're keeping it.
|
||||
end
|
||||
|
||||
------------------------------------------------
|
||||
-- Internal functions
|
||||
------------------------------------------------
|
||||
|
||||
function RosterLib:AceEvent_FullyInitialized()
|
||||
self:TriggerEvent("RosterLib_Enabled")
|
||||
self:RegisterEvent("RAID_ROSTER_UPDATE","ScanFullRoster")
|
||||
self:RegisterEvent("PARTY_MEMBERS_CHANGED","ScanFullRoster")
|
||||
self:RegisterEvent("UNIT_PET","ScanPet")
|
||||
self:ScanFullRoster()
|
||||
end
|
||||
|
||||
|
||||
------------------------------------------------
|
||||
-- Unit iterator
|
||||
------------------------------------------------
|
||||
|
||||
local playersent, petsent, unitcount, petcount, pmem, rmem, unit
|
||||
|
||||
local function NextUnit()
|
||||
-- STEP 1: pet
|
||||
if not petsent then
|
||||
petsent = true
|
||||
if rmem == 0 then
|
||||
unit = "pet"
|
||||
if UnitExists(unit) then return unit end
|
||||
end
|
||||
end
|
||||
-- STEP 2: player
|
||||
if not playersent then
|
||||
playersent = true
|
||||
if rmem == 0 then
|
||||
unit = "player"
|
||||
if UnitExists(unit) then return unit end
|
||||
end
|
||||
end
|
||||
-- STEP 3: raid units
|
||||
if rmem > 0 then
|
||||
-- STEP 3a: pet units
|
||||
for i = petcount, rmem do
|
||||
unit = string.format("raidpet%d", i)
|
||||
petcount = petcount + 1
|
||||
if UnitExists(unit) then return unit end
|
||||
end
|
||||
-- STEP 3b: player units
|
||||
for i = unitcount, rmem do
|
||||
unit = string.format("raid%d", i)
|
||||
unitcount = unitcount + 1
|
||||
if UnitExists(unit) then return unit end
|
||||
end
|
||||
-- STEP 4: party units
|
||||
elseif pmem > 0 then
|
||||
-- STEP 3a: pet units
|
||||
for i = petcount, pmem do
|
||||
unit = string.format("partypet%d", i)
|
||||
petcount = petcount + 1
|
||||
if UnitExists(unit) then return unit end
|
||||
end
|
||||
-- STEP 3b: player units
|
||||
for i = unitcount, pmem do
|
||||
unit = string.format("party%d", i)
|
||||
unitcount = unitcount + 1
|
||||
if UnitExists(unit) then return unit end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function UnitIterator()
|
||||
playersent, petsent, unitcount, petcount, pmem, rmem = false, false, 1, 1, GetNumPartyMembers(), GetNumRaidMembers()
|
||||
return NextUnit
|
||||
end
|
||||
|
||||
------------------------------------------------
|
||||
-- Roster code
|
||||
------------------------------------------------
|
||||
|
||||
|
||||
function RosterLib:ScanFullRoster()
|
||||
-- save all units we currently have, this way we can check who to remove from roster later.
|
||||
local temp = Compost and Compost:Acquire() or {}
|
||||
for name in pairs(roster) do
|
||||
temp[name] = true
|
||||
end
|
||||
-- update data
|
||||
for unitid in UnitIterator() do
|
||||
local name = self:CreateOrUpdateUnit(unitid)
|
||||
-- we successfully added a unit, so we don't need to remove it next step
|
||||
if name then temp[name] = nil end
|
||||
end
|
||||
-- clear units we had in roster that either left the raid or are unknown for some reason.
|
||||
for name in pairs(temp) do
|
||||
self:RemoveUnit(name)
|
||||
end
|
||||
if Compost then Compost:Reclaim(temp) end
|
||||
self:ProcessRoster()
|
||||
end
|
||||
|
||||
|
||||
function RosterLib:ScanPet(owner)
|
||||
local unitid = self:GetPetFromOwner(owner)
|
||||
if not unitid then
|
||||
return
|
||||
elseif not UnitExists(unitid) then
|
||||
unknownUnits[unitid] = nil
|
||||
-- find the pet in the roster we need to delete
|
||||
for _,u in pairs(roster) do
|
||||
if u.unitid == unitid then
|
||||
self:RemoveUnit(u.name)
|
||||
end
|
||||
end
|
||||
else
|
||||
self:CreateOrUpdateUnit(unitid)
|
||||
end
|
||||
self:ProcessRoster()
|
||||
end
|
||||
|
||||
|
||||
function RosterLib:GetPetFromOwner(id)
|
||||
-- convert party3 crap to raid IDs when in raid.
|
||||
local owner = self:GetUnitIDFromUnit(id)
|
||||
if not owner then
|
||||
return
|
||||
end
|
||||
-- get ID
|
||||
if string.find(owner,"raid") then
|
||||
return string.gsub(owner, "raid", "raidpet")
|
||||
elseif string.find(owner,"party") then
|
||||
return string.gsub(owner, "party", "partypet")
|
||||
elseif owner == "player" then
|
||||
return "pet"
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function RosterLib:ScanUnknownUnits()
|
||||
local name
|
||||
for unitid in pairs(unknownUnits) do
|
||||
if UnitExists(unitid) then
|
||||
name = self:CreateOrUpdateUnit(unitid)
|
||||
else
|
||||
unknownUnits[unitid] = nil
|
||||
end
|
||||
-- some pets never have a name. too bad for them, farewell!
|
||||
if not name and string.find(unitid,"pet") then
|
||||
unknownUnits[unitid] = nil
|
||||
end
|
||||
end
|
||||
self:ProcessRoster()
|
||||
end
|
||||
|
||||
|
||||
function RosterLib:ProcessRoster()
|
||||
if next(updatedUnits, nil) then
|
||||
self:TriggerEvent("RosterLib_RosterChanged", updatedUnits)
|
||||
for name in pairs(updatedUnits) do
|
||||
local u = updatedUnits[name]
|
||||
self:TriggerEvent("RosterLib_UnitChanged", u.unitid, u.name, u.class, u.subgroup, u.rank, u.oldname, u.oldunitid, u.oldclass, u.oldsubgroup, u.oldrank)
|
||||
if Compost then Compost:Reclaim(updatedUnits[name]) end
|
||||
updatedUnits[name] = nil
|
||||
end
|
||||
end
|
||||
if next(unknownUnits, nil) then
|
||||
self:CancelScheduledEvent("ScanUnknownUnits")
|
||||
self:ScheduleEvent("ScanUnknownUnits",self.ScanUnknownUnits, 1, self)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function RosterLib:CreateOrUpdateUnit(unitid)
|
||||
local old = nil
|
||||
-- check for name
|
||||
local name = UnitName(unitid)
|
||||
if name and name ~= UNKNOWNOBJECT and name ~= UKNOWNBEING and not UnitIsCharmed(unitid) then
|
||||
-- clear stuff
|
||||
unknownUnits[unitid] = nil
|
||||
-- return if a pet attempts to replace a player name
|
||||
-- this doesnt fix the problem with 2 pets overwriting each other FIXME
|
||||
if string.find(unitid,"pet") then
|
||||
if roster[name] and roster[name].class ~= "pet" then
|
||||
return name
|
||||
end
|
||||
end
|
||||
-- save old data if existing
|
||||
if roster[name] then
|
||||
old = Compost and Compost:Acquire() or {}
|
||||
old.name = roster[name].name
|
||||
old.unitid = roster[name].unitid
|
||||
old.class = roster[name].class
|
||||
old.rank = roster[name].rank
|
||||
old.subgroup = roster[name].subgroup
|
||||
old.online = roster[name].online
|
||||
end
|
||||
-- object
|
||||
if not roster[name] then
|
||||
roster[name] = Compost and Compost:Acquire() or {}
|
||||
end
|
||||
-- name
|
||||
roster[name].name = name
|
||||
-- unitid
|
||||
roster[name].unitid = unitid
|
||||
-- class
|
||||
if string.find(unitid,"pet") then
|
||||
roster[name].class = "PET"
|
||||
else
|
||||
_,roster[name].class = UnitClass(unitid)
|
||||
end
|
||||
-- subgroup and rank
|
||||
if GetNumRaidMembers() > 0 then
|
||||
local _,_,num = string.find(unitid, "(%d+)")
|
||||
_,roster[name].rank,roster[name].subgroup = GetRaidRosterInfo(num)
|
||||
else
|
||||
roster[name].subgroup = 1
|
||||
roster[name].rank = 0
|
||||
end
|
||||
-- online/offline status
|
||||
roster[name].online = UnitIsConnected(unitid)
|
||||
|
||||
-- compare data
|
||||
if not old
|
||||
or roster[name].name ~= old.name
|
||||
or roster[name].unitid ~= old.unitid
|
||||
or roster[name].class ~= old.class
|
||||
or roster[name].subgroup ~= old.subgroup
|
||||
or roster[name].rank ~= old.rank
|
||||
or roster[name].online ~= old.online
|
||||
then
|
||||
updatedUnits[name] = Compost and Compost:Acquire() or {}
|
||||
updatedUnits[name].oldname = (old and old.name) or nil
|
||||
updatedUnits[name].oldunitid = (old and old.unitid) or nil
|
||||
updatedUnits[name].oldclass = (old and old.class) or nil
|
||||
updatedUnits[name].oldsubgroup = (old and old.subgroup) or nil
|
||||
updatedUnits[name].oldrank = (old and old.rank) or nil
|
||||
updatedUnits[name].oldonline = (old and old.online) or nil
|
||||
updatedUnits[name].name = roster[name].name
|
||||
updatedUnits[name].unitid = roster[name].unitid
|
||||
updatedUnits[name].class = roster[name].class
|
||||
updatedUnits[name].subgroup = roster[name].subgroup
|
||||
updatedUnits[name].rank = roster[name].rank
|
||||
updatedUnits[name].online = roster[name].online
|
||||
end
|
||||
-- compost our table
|
||||
if old and Compost then
|
||||
Compost:Reclaim(old)
|
||||
end
|
||||
return name
|
||||
else
|
||||
unknownUnits[unitid] = true
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function RosterLib:RemoveUnit(name)
|
||||
updatedUnits[name] = Compost and Compost:Acquire() or {}
|
||||
updatedUnits[name].oldname = roster[name].name
|
||||
updatedUnits[name].oldunitid = roster[name].unitid
|
||||
updatedUnits[name].oldclass = roster[name].class
|
||||
updatedUnits[name].oldsubgroup = roster[name].subgroup
|
||||
updatedUnits[name].oldrank = roster[name].rank
|
||||
if Compost then Compost:Reclaim(roster[name]) end
|
||||
roster[name] = nil
|
||||
end
|
||||
|
||||
|
||||
------------------------------------------------
|
||||
-- API
|
||||
------------------------------------------------
|
||||
|
||||
function RosterLib:GetUnitIDFromName(name)
|
||||
if roster[name] then
|
||||
return roster[name].unitid
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function RosterLib:GetUnitIDFromUnit(unit)
|
||||
local name = UnitName(unit)
|
||||
if name and roster[name] then
|
||||
return roster[name].unitid
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function RosterLib:GetUnitObjectFromName(name)
|
||||
if roster[name] then
|
||||
return roster[name]
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function RosterLib:GetUnitObjectFromUnit(unit)
|
||||
local name = UnitName(unit)
|
||||
if roster[name] then
|
||||
return roster[name]
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function RosterLib:IterateRoster(pets)
|
||||
local key
|
||||
return function()
|
||||
repeat
|
||||
key = next(roster, key)
|
||||
until (roster[key] == nil or pets or roster[key].class ~= "PET")
|
||||
|
||||
return roster[key]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
AceLibrary:Register(RosterLib, MAJOR_VERSION, MINOR_VERSION, activate, nil, external)
|
||||
Loading…
Reference in New Issue
Block a user