Quantcast

Redid directories

Adrian L Lange [08-06-09 - 04:06]
Redid directories
Filename
Broker_Equipment.lua
Broker_Equipment.toc
Broker_Equipment/Broker_Equipment.lua
Broker_Equipment/Broker_Equipment.toc
Broker_Equipment/libs/CallbackHandler-1.0.lua
Broker_Equipment/libs/LibDataBroker-1.1.lua
Broker_Equipment/libs/LibStub.lua
libs/CallbackHandler-1.0.lua
libs/LibDataBroker-1.1.lua
libs/LibStub.lua
diff --git a/Broker_Equipment.lua b/Broker_Equipment.lua
new file mode 100644
index 0000000..7e32405
--- /dev/null
+++ b/Broker_Equipment.lua
@@ -0,0 +1,220 @@
+--[[
+
+	Copyright (c) 2009 Adrian L Lange <adrianlund@gmail.com>
+	All rights reserved.
+
+	You're allowed to use this addon, free of monetary charge,
+	but you are not allowed to modify, alter, or redistribute
+	this addon without express, written permission of the author.
+
+--]]
+
+local L = {}
+if(GetLocale() == 'deDE') then -- Katharsis / copystring
+	L.NOSET = 'Kein set'
+	L.TOOLTIP = 'Klicke links um dein set zu ändern\nKlicke rechts um den GearManager zu öffnen'
+	L.HINTS = {' ', '|cff00ff00Shift-klicke um den set zu aktualisieren\nStrg-klicke um den set zu löschen|r'}
+elseif(GetLocale() == 'frFR') then -- Soeters / Gnaf
+	L.NOSET = 'Pas de set'
+	L.TOOLTIP = 'Clic gauche pour changer d\'équipement\nClic droit pour ouvrir le gestionnaire d\'équipement'
+	L.HINTS = {' ', '|cff00ff00Maj-clic pour mettre à jour le set\nCtrl-clic pour supprimer le set|r'}
+elseif(GetLocale() == 'zhCN') then -- yleaf
+	L.NOSET = '无套装'
+	L.TOOLTIP = '左键点击切换套装\n右键打开套装管理器'
+	L.HINTS = {' ', '|cff00ff00Shift点击覆盖套装\nCtrl点击删除套装|r'}
+elseif(GetLocale() == 'zhTW') then -- yleaf
+	L.NOSET = '無套裝'
+	L.TOOLTIP = '左鍵點擊切換套裝\n右鍵點擊打開套裝管理器'
+	L.HINTS = {' ', '|cff00ff00Shift點擊覆蓋套裝\nCtrl點擊刪除套裝|r'}
+elseif(GetLocale() == 'koKR') then -- mrgyver
+	L.NOSET = '세트 없음'
+	L.TOOLTIP = '좌-클릭 세트 변경\n우-클릭 장비 관리창 열기'
+	L.HINTS = {' ', '|cff00ff00Shift-클릭 하면 세트 업데이트\nCtrl-클릭 하면 세트 삭제|r'}
+else
+	L.NOSET = 'No set'
+	L.TOOLTIP = 'Left-click to change your set\nRight-click to open GearManager'
+	L.HINTS = {' ', '|cff00ff00Shift-click to update set\nCtrl-click to delete set|r'}
+end
+
+
+local menu = {}
+local pendingUpdate = true
+local pendingName = nil
+
+local addon = CreateFrame('Frame', 'Broker_EquipmentMenu', UIParent, 'UIDropDownMenuTemplate')
+local broker = LibStub('LibDataBroker-1.1'):NewDataObject('Broker_Equipment', {
+	type = 'data source',
+	text = L.NOSET,
+	icon = [=[Interface\PaperDollInfoFrame\UI-EquipmentManager-Toggle]=],
+	iconCoords = {0.065, 0.935, 0.065, 0.935}
+})
+
+-- Borrowed from tekkub's EquipSetUpdater
+local function GetTextureIndex(tex)
+	RefreshEquipmentSetIconInfo()
+	tex = tex:lower()
+	local numicons = GetNumMacroIcons()
+	for i=INVSLOT_FIRST_EQUIPPED,INVSLOT_LAST_EQUIPPED do if GetInventoryItemTexture("player", i) then numicons = numicons + 1 end end
+	for i=1,numicons do
+		local texture, index = GetEquipmentSetIconInfo(i)
+		if texture:lower() == tex then return index end
+	end
+end
+
+local function matchEquipped(name)
+	for k, v in next, GetEquipmentSetItemIDs(name) do
+		local link = GetInventoryItemLink('player', k)
+		if(link) then
+			local id = tonumber(string.match(link, 'item:(%d+)'))
+			if(id ~= v) then
+				return
+			end
+		else
+			if(v ~= 0) then
+				return
+			end
+		end
+	end
+
+	return true
+end
+
+local function handleClick(name, icon)
+	if(IsShiftKeyDown()) then
+		local dialog = StaticPopup_Show('CUSTOM_OVERWRITE_EQUIPMENT_SET', name) -- Custom popup to update the info
+		dialog.name = name
+		dialog.icon = icon
+	elseif(IsControlKeyDown()) then
+		local dialog = StaticPopup_Show('CONFIRM_DELETE_EQUIPMENT_SET', name)
+		dialog.data = name
+	else
+		EquipmentManager_EquipSet(name)
+
+		if(InCombatLockdown()) then
+			pendingName = name
+			addon:RegisterEvent('PLAYER_REGEN_ENABLED')
+		end
+	end
+end
+
+local function updateInfo(name, icon)
+	broker.text = InCombatLockdown() and '|cffff0000'..name or name
+	broker.icon = icon
+
+	Broker_EquipmentDB.text = name
+	Broker_EquipmentDB.icon = icon
+end
+
+local function updateMenu()
+	pendingUpdate = nil
+	menu = wipe(menu)
+
+	local temp = {text = '|cff0090ffBroker Equipment|r\n', isTitle = true}
+	table.insert(menu, temp)
+
+	for index = 1, GetNumEquipmentSets() do
+		local name, icon = GetEquipmentSetInfo(index)
+		temp = {
+			notCheckable = true,
+			text = name,
+			icon = icon,
+			func = function() handleClick(name, icon) end
+		}
+		table.insert(menu, temp)
+	end
+
+	for index = 1, 2 do
+		temp = {
+			text = L.HINTS[index],
+			notCheckable = true,
+			disabled = true
+		}
+		table.insert(menu, temp)
+	end
+end
+
+-- Fuck blizzard!
+StaticPopupDialogs.CUSTOM_OVERWRITE_EQUIPMENT_SET = {
+	text = CONFIRM_OVERWRITE_EQUIPMENT_SET,
+	button1 = YES,
+	button2 = NO,
+	OnAccept = function(self) SaveEquipmentSet(self.name, GetTextureIndex(self.icon)); GearManagerDialogPopup:Hide() updateInfo(self.name, self.icon) end,
+	OnCancel = function() end,
+	OnHide = function(self) self.name, self.icon = nil, nil end,
+	hideOnEscape = 1,
+	timeout = 0,
+	exclusive = 1,
+}
+
+function broker:OnClick(button)
+	if(button == 'RightButton') then
+		if(GearManagerDialog:IsVisible()) then
+			if(PaperDollFrame:IsVisible()) then
+				ToggleCharacter('PaperDollFrame')
+			end
+			GearManagerDialog:Hide()
+		else
+			if(not PaperDollFrame:IsVisible()) then
+				ToggleCharacter('PaperDollFrame')
+			end
+			GearManagerDialog:Show()
+		end
+	elseif(GetNumEquipmentSets() > 0) then
+		if(pendingUpdate) then updateMenu() end
+		EasyMenu(menu, addon, self, 0, 0, 'MENU')
+
+		if(GameTooltip:GetOwner() == self) then GameTooltip:Hide() end
+	end
+end
+
+function broker:OnTooltipShow()
+	self:AddLine('|cff0090ffBroker Equipment|r')
+	self:AddLine(L.TOOLTIP)
+end
+
+function addon:PLAYER_REGEN_ENABLED(event)
+	EquipmentManager_EquipSet(pendingName)
+	pendingName = nil
+	self:UnregisterEvent(event)
+end
+
+function addon:ADDON_LOADED(event, addon)
+	if(addon ~= 'Broker_Equipment') then return end
+
+	Broker_EquipmentDB = Broker_EquipmentDB or {text = L.NOSET, icon = broker.icon}
+	broker.text = Broker_EquipmentDB.text
+	broker.icon = Broker_EquipmentDB.icon
+
+	self:RegisterEvent('EQUIPMENT_SETS_CHANGED')
+	self:RegisterEvent('UNIT_INVENTORY_CHANGED')
+	self:RegisterEvent('VARIABLES_LOADED')
+	self:UnregisterEvent(event)
+end
+
+function addon:EQUIPMENT_SETS_CHANGED()
+	pendingUpdate = true
+end
+
+function addon:UNIT_INVENTORY_CHANGED(event, unit)
+	if(unit ~= 'player') then return end
+
+	for index = 1, GetNumEquipmentSets() do
+		local name, icon = GetEquipmentSetInfo(index)
+		if(matchEquipped(name)) then
+			updateInfo(name, icon)
+			break
+		else
+			updateInfo(UNKNOWN, [=[Interface\Icons\INV_Misc_QuestionMark]=])
+		end
+	end
+end
+
+function addon:VARIABLES_LOADED(event)
+	SetCVar('equipmentManager', 1)
+	GearManagerToggleButton:Show()
+
+	self:UnregisterEvent(event)
+end
+
+addon:RegisterEvent('ADDON_LOADED')
+addon:SetScript('OnEvent', function(self, event, ...) self[event](self, event, ...) end)
\ No newline at end of file
diff --git a/Broker_Equipment.toc b/Broker_Equipment.toc
new file mode 100644
index 0000000..00ed6e4
--- /dev/null
+++ b/Broker_Equipment.toc
@@ -0,0 +1,12 @@
+## Interface: 30100
+## Author: p3lim
+## Version: 30100.wowi:revision
+## Title: Broker Equipment
+## Notes: LDB Equipment Manager plug-in
+## SavedVariablesPerCharacter: Broker_EquipmentDB
+
+libs\LibStub.lua
+libs\CallbackHandler-1.0.lua
+libs\LibDataBroker-1.1.lua
+
+Broker_Equipment.lua
\ No newline at end of file
diff --git a/Broker_Equipment/Broker_Equipment.lua b/Broker_Equipment/Broker_Equipment.lua
deleted file mode 100644
index 7e32405..0000000
--- a/Broker_Equipment/Broker_Equipment.lua
+++ /dev/null
@@ -1,220 +0,0 @@
---[[
-
-	Copyright (c) 2009 Adrian L Lange <adrianlund@gmail.com>
-	All rights reserved.
-
-	You're allowed to use this addon, free of monetary charge,
-	but you are not allowed to modify, alter, or redistribute
-	this addon without express, written permission of the author.
-
---]]
-
-local L = {}
-if(GetLocale() == 'deDE') then -- Katharsis / copystring
-	L.NOSET = 'Kein set'
-	L.TOOLTIP = 'Klicke links um dein set zu ändern\nKlicke rechts um den GearManager zu öffnen'
-	L.HINTS = {' ', '|cff00ff00Shift-klicke um den set zu aktualisieren\nStrg-klicke um den set zu löschen|r'}
-elseif(GetLocale() == 'frFR') then -- Soeters / Gnaf
-	L.NOSET = 'Pas de set'
-	L.TOOLTIP = 'Clic gauche pour changer d\'équipement\nClic droit pour ouvrir le gestionnaire d\'équipement'
-	L.HINTS = {' ', '|cff00ff00Maj-clic pour mettre à jour le set\nCtrl-clic pour supprimer le set|r'}
-elseif(GetLocale() == 'zhCN') then -- yleaf
-	L.NOSET = '无套装'
-	L.TOOLTIP = '左键点击切换套装\n右键打开套装管理器'
-	L.HINTS = {' ', '|cff00ff00Shift点击覆盖套装\nCtrl点击删除套装|r'}
-elseif(GetLocale() == 'zhTW') then -- yleaf
-	L.NOSET = '無套裝'
-	L.TOOLTIP = '左鍵點擊切換套裝\n右鍵點擊打開套裝管理器'
-	L.HINTS = {' ', '|cff00ff00Shift點擊覆蓋套裝\nCtrl點擊刪除套裝|r'}
-elseif(GetLocale() == 'koKR') then -- mrgyver
-	L.NOSET = '세트 없음'
-	L.TOOLTIP = '좌-클릭 세트 변경\n우-클릭 장비 관리창 열기'
-	L.HINTS = {' ', '|cff00ff00Shift-클릭 하면 세트 업데이트\nCtrl-클릭 하면 세트 삭제|r'}
-else
-	L.NOSET = 'No set'
-	L.TOOLTIP = 'Left-click to change your set\nRight-click to open GearManager'
-	L.HINTS = {' ', '|cff00ff00Shift-click to update set\nCtrl-click to delete set|r'}
-end
-
-
-local menu = {}
-local pendingUpdate = true
-local pendingName = nil
-
-local addon = CreateFrame('Frame', 'Broker_EquipmentMenu', UIParent, 'UIDropDownMenuTemplate')
-local broker = LibStub('LibDataBroker-1.1'):NewDataObject('Broker_Equipment', {
-	type = 'data source',
-	text = L.NOSET,
-	icon = [=[Interface\PaperDollInfoFrame\UI-EquipmentManager-Toggle]=],
-	iconCoords = {0.065, 0.935, 0.065, 0.935}
-})
-
--- Borrowed from tekkub's EquipSetUpdater
-local function GetTextureIndex(tex)
-	RefreshEquipmentSetIconInfo()
-	tex = tex:lower()
-	local numicons = GetNumMacroIcons()
-	for i=INVSLOT_FIRST_EQUIPPED,INVSLOT_LAST_EQUIPPED do if GetInventoryItemTexture("player", i) then numicons = numicons + 1 end end
-	for i=1,numicons do
-		local texture, index = GetEquipmentSetIconInfo(i)
-		if texture:lower() == tex then return index end
-	end
-end
-
-local function matchEquipped(name)
-	for k, v in next, GetEquipmentSetItemIDs(name) do
-		local link = GetInventoryItemLink('player', k)
-		if(link) then
-			local id = tonumber(string.match(link, 'item:(%d+)'))
-			if(id ~= v) then
-				return
-			end
-		else
-			if(v ~= 0) then
-				return
-			end
-		end
-	end
-
-	return true
-end
-
-local function handleClick(name, icon)
-	if(IsShiftKeyDown()) then
-		local dialog = StaticPopup_Show('CUSTOM_OVERWRITE_EQUIPMENT_SET', name) -- Custom popup to update the info
-		dialog.name = name
-		dialog.icon = icon
-	elseif(IsControlKeyDown()) then
-		local dialog = StaticPopup_Show('CONFIRM_DELETE_EQUIPMENT_SET', name)
-		dialog.data = name
-	else
-		EquipmentManager_EquipSet(name)
-
-		if(InCombatLockdown()) then
-			pendingName = name
-			addon:RegisterEvent('PLAYER_REGEN_ENABLED')
-		end
-	end
-end
-
-local function updateInfo(name, icon)
-	broker.text = InCombatLockdown() and '|cffff0000'..name or name
-	broker.icon = icon
-
-	Broker_EquipmentDB.text = name
-	Broker_EquipmentDB.icon = icon
-end
-
-local function updateMenu()
-	pendingUpdate = nil
-	menu = wipe(menu)
-
-	local temp = {text = '|cff0090ffBroker Equipment|r\n', isTitle = true}
-	table.insert(menu, temp)
-
-	for index = 1, GetNumEquipmentSets() do
-		local name, icon = GetEquipmentSetInfo(index)
-		temp = {
-			notCheckable = true,
-			text = name,
-			icon = icon,
-			func = function() handleClick(name, icon) end
-		}
-		table.insert(menu, temp)
-	end
-
-	for index = 1, 2 do
-		temp = {
-			text = L.HINTS[index],
-			notCheckable = true,
-			disabled = true
-		}
-		table.insert(menu, temp)
-	end
-end
-
--- Fuck blizzard!
-StaticPopupDialogs.CUSTOM_OVERWRITE_EQUIPMENT_SET = {
-	text = CONFIRM_OVERWRITE_EQUIPMENT_SET,
-	button1 = YES,
-	button2 = NO,
-	OnAccept = function(self) SaveEquipmentSet(self.name, GetTextureIndex(self.icon)); GearManagerDialogPopup:Hide() updateInfo(self.name, self.icon) end,
-	OnCancel = function() end,
-	OnHide = function(self) self.name, self.icon = nil, nil end,
-	hideOnEscape = 1,
-	timeout = 0,
-	exclusive = 1,
-}
-
-function broker:OnClick(button)
-	if(button == 'RightButton') then
-		if(GearManagerDialog:IsVisible()) then
-			if(PaperDollFrame:IsVisible()) then
-				ToggleCharacter('PaperDollFrame')
-			end
-			GearManagerDialog:Hide()
-		else
-			if(not PaperDollFrame:IsVisible()) then
-				ToggleCharacter('PaperDollFrame')
-			end
-			GearManagerDialog:Show()
-		end
-	elseif(GetNumEquipmentSets() > 0) then
-		if(pendingUpdate) then updateMenu() end
-		EasyMenu(menu, addon, self, 0, 0, 'MENU')
-
-		if(GameTooltip:GetOwner() == self) then GameTooltip:Hide() end
-	end
-end
-
-function broker:OnTooltipShow()
-	self:AddLine('|cff0090ffBroker Equipment|r')
-	self:AddLine(L.TOOLTIP)
-end
-
-function addon:PLAYER_REGEN_ENABLED(event)
-	EquipmentManager_EquipSet(pendingName)
-	pendingName = nil
-	self:UnregisterEvent(event)
-end
-
-function addon:ADDON_LOADED(event, addon)
-	if(addon ~= 'Broker_Equipment') then return end
-
-	Broker_EquipmentDB = Broker_EquipmentDB or {text = L.NOSET, icon = broker.icon}
-	broker.text = Broker_EquipmentDB.text
-	broker.icon = Broker_EquipmentDB.icon
-
-	self:RegisterEvent('EQUIPMENT_SETS_CHANGED')
-	self:RegisterEvent('UNIT_INVENTORY_CHANGED')
-	self:RegisterEvent('VARIABLES_LOADED')
-	self:UnregisterEvent(event)
-end
-
-function addon:EQUIPMENT_SETS_CHANGED()
-	pendingUpdate = true
-end
-
-function addon:UNIT_INVENTORY_CHANGED(event, unit)
-	if(unit ~= 'player') then return end
-
-	for index = 1, GetNumEquipmentSets() do
-		local name, icon = GetEquipmentSetInfo(index)
-		if(matchEquipped(name)) then
-			updateInfo(name, icon)
-			break
-		else
-			updateInfo(UNKNOWN, [=[Interface\Icons\INV_Misc_QuestionMark]=])
-		end
-	end
-end
-
-function addon:VARIABLES_LOADED(event)
-	SetCVar('equipmentManager', 1)
-	GearManagerToggleButton:Show()
-
-	self:UnregisterEvent(event)
-end
-
-addon:RegisterEvent('ADDON_LOADED')
-addon:SetScript('OnEvent', function(self, event, ...) self[event](self, event, ...) end)
\ No newline at end of file
diff --git a/Broker_Equipment/Broker_Equipment.toc b/Broker_Equipment/Broker_Equipment.toc
deleted file mode 100644
index 00ed6e4..0000000
--- a/Broker_Equipment/Broker_Equipment.toc
+++ /dev/null
@@ -1,12 +0,0 @@
-## Interface: 30100
-## Author: p3lim
-## Version: 30100.wowi:revision
-## Title: Broker Equipment
-## Notes: LDB Equipment Manager plug-in
-## SavedVariablesPerCharacter: Broker_EquipmentDB
-
-libs\LibStub.lua
-libs\CallbackHandler-1.0.lua
-libs\LibDataBroker-1.1.lua
-
-Broker_Equipment.lua
\ No newline at end of file
diff --git a/Broker_Equipment/libs/CallbackHandler-1.0.lua b/Broker_Equipment/libs/CallbackHandler-1.0.lua
deleted file mode 100644
index 5a495f6..0000000
--- a/Broker_Equipment/libs/CallbackHandler-1.0.lua
+++ /dev/null
@@ -1,239 +0,0 @@
---[[ $Id: CallbackHandler-1.0.lua 3 2008-09-29 16:54:20Z nevcairiel $ ]]
-local MAJOR, MINOR = "CallbackHandler-1.0", 3
-local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR)
-
-if not CallbackHandler then return end -- No upgrade needed
-
-local meta = {__index = function(tbl, key) tbl[key] = {} return tbl[key] end}
-
-local type = type
-local pcall = pcall
-local pairs = pairs
-local assert = assert
-local concat = table.concat
-local loadstring = loadstring
-local next = next
-local select = select
-local type = type
-local xpcall = xpcall
-
-local function errorhandler(err)
-	return geterrorhandler()(err)
-end
-
-local function CreateDispatcher(argCount)
-	local code = [[
-	local next, xpcall, eh = ...
-
-	local method, ARGS
-	local function call() method(ARGS) end
-
-	local function dispatch(handlers, ...)
-		local index
-		index, method = next(handlers)
-		if not method then return end
-		local OLD_ARGS = ARGS
-		ARGS = ...
-		repeat
-			xpcall(call, eh)
-			index, method = next(handlers, index)
-		until not method
-		ARGS = OLD_ARGS
-	end
-
-	return dispatch
-	]]
-
-	local ARGS, OLD_ARGS = {}, {}
-	for i = 1, argCount do ARGS[i], OLD_ARGS[i] = "arg"..i, "old_arg"..i end
-	code = code:gsub("OLD_ARGS", concat(OLD_ARGS, ", ")):gsub("ARGS", concat(ARGS, ", "))
-	return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(next, xpcall, errorhandler)
-end
-
-local Dispatchers = setmetatable({}, {__index=function(self, argCount)
-	local dispatcher = CreateDispatcher(argCount)
-	rawset(self, argCount, dispatcher)
-	return dispatcher
-end})
-
---------------------------------------------------------------------------
--- CallbackHandler:New
---
---   target            - target object to embed public APIs in
---   RegisterName      - name of the callback registration API, default "RegisterCallback"
---   UnregisterName    - name of the callback unregistration API, default "UnregisterCallback"
---   UnregisterAllName - name of the API to unregister all callbacks, default "UnregisterAllCallbacks". false == don't publish this API.
-
-function CallbackHandler:New(target, RegisterName, UnregisterName, UnregisterAllName, OnUsed, OnUnused)
-	-- TODO: Remove this after beta has gone out
-	assert(not OnUsed and not OnUnused, "ACE-80: OnUsed/OnUnused are deprecated. Callbacks are now done to registry.OnUsed and registry.OnUnused")
-
-	RegisterName = RegisterName or "RegisterCallback"
-	UnregisterName = UnregisterName or "UnregisterCallback"
-	if UnregisterAllName==nil then	-- false is used to indicate "don't want this method"
-		UnregisterAllName = "UnregisterAllCallbacks"
-	end
-
-	-- we declare all objects and exported APIs inside this closure to quickly gain access
-	-- to e.g. function names, the "target" parameter, etc
-
-
-	-- Create the registry object
-	local events = setmetatable({}, meta)
-	local registry = { recurse=0, events=events }
-
-	-- registry:Fire() - fires the given event/message into the registry
-	function registry:Fire(eventname, ...)
-		if not rawget(events, eventname) or not next(events[eventname]) then return end
-		local oldrecurse = registry.recurse
-		registry.recurse = oldrecurse + 1
-
-		Dispatchers[select('#', ...) + 1](events[eventname], eventname, ...)
-
-		registry.recurse = oldrecurse
-
-		if registry.insertQueue and oldrecurse==0 then
-			-- Something in one of our callbacks wanted to register more callbacks; they got queued
-			for eventname,callbacks in pairs(registry.insertQueue) do
-				local first = not rawget(events, eventname) or not next(events[eventname])	-- test for empty before. not test for one member after. that one member may have been overwritten.
-				for self,func in pairs(callbacks) do
-					events[eventname][self] = func
-					-- fire OnUsed callback?
-					if first and registry.OnUsed then
-						registry.OnUsed(registry, target, eventname)
-						first = nil
-					end
-				end
-			end
-			registry.insertQueue = nil
-		end
-	end
-
-	-- Registration of a callback, handles:
-	--   self["method"], leads to self["method"](self, ...)
-	--   self with function ref, leads to functionref(...)
-	--   "addonId" (instead of self) with function ref, leads to functionref(...)
-	-- all with an optional arg, which, if present, gets passed as first argument (after self if present)
-	target[RegisterName] = function(self, eventname, method, ... --[[actually just a single arg]])
-		if type(eventname) ~= "string" then
-			error("Usage: "..RegisterName.."(eventname, method[, arg]): 'eventname' - string expected.", 2)
-		end
-
-		method = method or eventname
-
-		local first = not rawget(events, eventname) or not next(events[eventname])	-- test for empty before. not test for one member after. that one member may have been overwritten.
-
-		if type(method) ~= "string" and type(method) ~= "function" then
-			error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - string or function expected.", 2)
-		end
-
-		local regfunc
-
-		if type(method) == "string" then
-			-- self["method"] calling style
-			if type(self) ~= "table" then
-				error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): self was not a table?", 2)
-			elseif self==target then
-				error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): do not use Library:"..RegisterName.."(), use your own 'self'", 2)
-			elseif type(self[method]) ~= "function" then
-				error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - method '"..tostring(method).."' not found on self.", 2)
-			end
-
-			if select("#",...)>=1 then	-- this is not the same as testing for arg==nil!
-				local arg=select(1,...)
-				regfunc = function(...) self[method](self,arg,...) end
-			else
-				regfunc = function(...) self[method](self,...) end
-			end
-		else
-			-- function ref with self=object or self="addonId"
-			if type(self)~="table" and type(self)~="string" then
-				error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string expected.", 2)
-			end
-
-			if select("#",...)>=1 then	-- this is not the same as testing for arg==nil!
-				local arg=select(1,...)
-				regfunc = function(...) method(arg,...) end
-			else
-				regfunc = method
-			end
-		end
-
-
-		if events[eventname][self] or registry.recurse<1 then
-		-- if registry.recurse<1 then
-			-- we're overwriting an existing entry, or not currently recursing. just set it.
-			events[eventname][self] = regfunc
-			-- fire OnUsed callback?
-			if registry.OnUsed and first then
-				registry.OnUsed(registry, target, eventname)
-			end
-		else
-			-- we're currently processing a callback in this registry, so delay the registration of this new entry!
-			-- yes, we're a bit wasteful on garbage, but this is a fringe case, so we're picking low implementation overhead over garbage efficiency
-			registry.insertQueue = registry.insertQueue or setmetatable({},meta)
-			registry.insertQueue[eventname][self] = regfunc
-		end
-	end
-
-	-- Unregister a callback
-	target[UnregisterName] = function(self, eventname)
-		if not self or self==target then
-			error("Usage: "..UnregisterName.."(eventname): bad 'self'", 2)
-		end
-		if type(eventname) ~= "string" then
-			error("Usage: "..UnregisterName.."(eventname): 'eventname' - string expected.", 2)
-		end
-		if rawget(events, eventname) and events[eventname][self] then
-			events[eventname][self] = nil
-			-- Fire OnUnused callback?
-			if registry.OnUnused and not next(events[eventname]) then
-				registry.OnUnused(registry, target, eventname)
-			end
-		end
-		if registry.insertQueue and rawget(registry.insertQueue, eventname) and registry.insertQueue[eventname][self] then
-			registry.insertQueue[eventname][self] = nil
-		end
-	end
-
-	-- OPTIONAL: Unregister all callbacks for given selfs/addonIds
-	if UnregisterAllName then
-		target[UnregisterAllName] = function(...)
-			if select("#",...)<1 then
-				error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2)
-			end
-			if select("#",...)==1 and ...==target then
-				error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2)
-			end
-
-
-			for i=1,select("#",...) do
-				local self = select(i,...)
-				if registry.insertQueue then
-					for eventname, callbacks in pairs(registry.insertQueue) do
-						if callbacks[self] then
-							callbacks[self] = nil
-						end
-					end
-				end
-				for eventname, callbacks in pairs(events) do
-					if callbacks[self] then
-						callbacks[self] = nil
-						-- Fire OnUnused callback?
-						if registry.OnUnused and not next(callbacks) then
-							registry.OnUnused(registry, target, eventname)
-						end
-					end
-				end
-			end
-		end
-	end
-
-	return registry
-end
-
-
--- CallbackHandler purposefully does NOT do explicit embedding. Nor does it
--- try to upgrade old implicit embeds since the system is selfcontained and
--- relies on closures to work.
-
diff --git a/Broker_Equipment/libs/LibDataBroker-1.1.lua b/Broker_Equipment/libs/LibDataBroker-1.1.lua
deleted file mode 100644
index f47c0cd..0000000
--- a/Broker_Equipment/libs/LibDataBroker-1.1.lua
+++ /dev/null
@@ -1,90 +0,0 @@
-
-assert(LibStub, "LibDataBroker-1.1 requires LibStub")
-assert(LibStub:GetLibrary("CallbackHandler-1.0", true), "LibDataBroker-1.1 requires CallbackHandler-1.0")
-
-local lib, oldminor = LibStub:NewLibrary("LibDataBroker-1.1", 4)
-if not lib then return end
-oldminor = oldminor or 0
-
-
-lib.callbacks = lib.callbacks or LibStub:GetLibrary("CallbackHandler-1.0"):New(lib)
-lib.attributestorage, lib.namestorage, lib.proxystorage = lib.attributestorage or {}, lib.namestorage or {}, lib.proxystorage or {}
-local attributestorage, namestorage, callbacks = lib.attributestorage, lib.namestorage, lib.callbacks
-
-if oldminor < 2 then
-	lib.domt = {
-		__metatable = "access denied",
-		__index = function(self, key) return attributestorage[self] and attributestorage[self][key] end,
-	}
-end
-
-if oldminor < 3 then
-	lib.domt.__newindex = function(self, key, value)
-		if not attributestorage[self] then attributestorage[self] = {} end
-		if attributestorage[self][key] == value then return end
-		attributestorage[self][key] = value
-		local name = namestorage[self]
-		if not name then return end
-		callbacks:Fire("LibDataBroker_AttributeChanged", name, key, value, self)
-		callbacks:Fire("LibDataBroker_AttributeChanged_"..name, name, key, value, self)
-		callbacks:Fire("LibDataBroker_AttributeChanged_"..name.."_"..key, name, key, value, self)
-		callbacks:Fire("LibDataBroker_AttributeChanged__"..key, name, key, value, self)
-	end
-end
-
-if oldminor < 2 then
-	function lib:NewDataObject(name, dataobj)
-		if self.proxystorage[name] then return end
-
-		if dataobj then
-			assert(type(dataobj) == "table", "Invalid dataobj, must be nil or a table")
-			self.attributestorage[dataobj] = {}
-			for i,v in pairs(dataobj) do
-				self.attributestorage[dataobj][i] = v
-				dataobj[i] = nil
-			end
-		end
-		dataobj = setmetatable(dataobj or {}, self.domt)
-		self.proxystorage[name], self.namestorage[dataobj] = dataobj, name
-		self.callbacks:Fire("LibDataBroker_DataObjectCreated", name, dataobj)
-		return dataobj
-	end
-end
-
-if oldminor < 1 then
-	function lib:DataObjectIterator()
-		return pairs(self.proxystorage)
-	end
-
-	function lib:GetDataObjectByName(dataobjectname)
-		return self.proxystorage[dataobjectname]
-	end
-
-	function lib:GetNameByDataObject(dataobject)
-		return self.namestorage[dataobject]
-	end
-end
-
-if oldminor < 4 then
-	local next = pairs(attributestorage)
-	function lib:pairs(dataobject_or_name)
-		local t = type(dataobject_or_name)
-		assert(t == "string" or t == "table", "Usage: ldb:pairs('dataobjectname') or ldb:pairs(dataobject)")
-
-		local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name
-		assert(attributestorage[dataobj], "Data object not found")
-
-		return next, attributestorage[dataobj], nil
-	end
-
-	local ipairs_iter = ipairs(attributestorage)
-	function lib:ipairs(dataobject_or_name)
-		local t = type(dataobject_or_name)
-		assert(t == "string" or t == "table", "Usage: ldb:ipairs('dataobjectname') or ldb:ipairs(dataobject)")
-
-		local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name
-		assert(attributestorage[dataobj], "Data object not found")
-
-		return ipairs_iter, attributestorage[dataobj], 0
-	end
-end
diff --git a/Broker_Equipment/libs/LibStub.lua b/Broker_Equipment/libs/LibStub.lua
deleted file mode 100644
index cfc97de..0000000
--- a/Broker_Equipment/libs/LibStub.lua
+++ /dev/null
@@ -1,30 +0,0 @@
--- LibStub is a simple versioning stub meant for use in Libraries.  http://www.wowace.com/wiki/LibStub for more info
--- LibStub is hereby placed in the Public Domain Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
-local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2  -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
-local LibStub = _G[LIBSTUB_MAJOR]
-
-if not LibStub or LibStub.minor < LIBSTUB_MINOR then
-	LibStub = LibStub or {libs = {}, minors = {} }
-	_G[LIBSTUB_MAJOR] = LibStub
-	LibStub.minor = LIBSTUB_MINOR
-
-	function LibStub:NewLibrary(major, minor)
-		assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
-		minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
-
-		local oldminor = self.minors[major]
-		if oldminor and oldminor >= minor then return nil end
-		self.minors[major], self.libs[major] = minor, self.libs[major] or {}
-		return self.libs[major], oldminor
-	end
-
-	function LibStub:GetLibrary(major, silent)
-		if not self.libs[major] and not silent then
-			error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
-		end
-		return self.libs[major], self.minors[major]
-	end
-
-	function LibStub:IterateLibraries() return pairs(self.libs) end
-	setmetatable(LibStub, { __call = LibStub.GetLibrary })
-end
diff --git a/libs/CallbackHandler-1.0.lua b/libs/CallbackHandler-1.0.lua
new file mode 100644
index 0000000..5a495f6
--- /dev/null
+++ b/libs/CallbackHandler-1.0.lua
@@ -0,0 +1,239 @@
+--[[ $Id: CallbackHandler-1.0.lua 3 2008-09-29 16:54:20Z nevcairiel $ ]]
+local MAJOR, MINOR = "CallbackHandler-1.0", 3
+local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR)
+
+if not CallbackHandler then return end -- No upgrade needed
+
+local meta = {__index = function(tbl, key) tbl[key] = {} return tbl[key] end}
+
+local type = type
+local pcall = pcall
+local pairs = pairs
+local assert = assert
+local concat = table.concat
+local loadstring = loadstring
+local next = next
+local select = select
+local type = type
+local xpcall = xpcall
+
+local function errorhandler(err)
+	return geterrorhandler()(err)
+end
+
+local function CreateDispatcher(argCount)
+	local code = [[
+	local next, xpcall, eh = ...
+
+	local method, ARGS
+	local function call() method(ARGS) end
+
+	local function dispatch(handlers, ...)
+		local index
+		index, method = next(handlers)
+		if not method then return end
+		local OLD_ARGS = ARGS
+		ARGS = ...
+		repeat
+			xpcall(call, eh)
+			index, method = next(handlers, index)
+		until not method
+		ARGS = OLD_ARGS
+	end
+
+	return dispatch
+	]]
+
+	local ARGS, OLD_ARGS = {}, {}
+	for i = 1, argCount do ARGS[i], OLD_ARGS[i] = "arg"..i, "old_arg"..i end
+	code = code:gsub("OLD_ARGS", concat(OLD_ARGS, ", ")):gsub("ARGS", concat(ARGS, ", "))
+	return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(next, xpcall, errorhandler)
+end
+
+local Dispatchers = setmetatable({}, {__index=function(self, argCount)
+	local dispatcher = CreateDispatcher(argCount)
+	rawset(self, argCount, dispatcher)
+	return dispatcher
+end})
+
+--------------------------------------------------------------------------
+-- CallbackHandler:New
+--
+--   target            - target object to embed public APIs in
+--   RegisterName      - name of the callback registration API, default "RegisterCallback"
+--   UnregisterName    - name of the callback unregistration API, default "UnregisterCallback"
+--   UnregisterAllName - name of the API to unregister all callbacks, default "UnregisterAllCallbacks". false == don't publish this API.
+
+function CallbackHandler:New(target, RegisterName, UnregisterName, UnregisterAllName, OnUsed, OnUnused)
+	-- TODO: Remove this after beta has gone out
+	assert(not OnUsed and not OnUnused, "ACE-80: OnUsed/OnUnused are deprecated. Callbacks are now done to registry.OnUsed and registry.OnUnused")
+
+	RegisterName = RegisterName or "RegisterCallback"
+	UnregisterName = UnregisterName or "UnregisterCallback"
+	if UnregisterAllName==nil then	-- false is used to indicate "don't want this method"
+		UnregisterAllName = "UnregisterAllCallbacks"
+	end
+
+	-- we declare all objects and exported APIs inside this closure to quickly gain access
+	-- to e.g. function names, the "target" parameter, etc
+
+
+	-- Create the registry object
+	local events = setmetatable({}, meta)
+	local registry = { recurse=0, events=events }
+
+	-- registry:Fire() - fires the given event/message into the registry
+	function registry:Fire(eventname, ...)
+		if not rawget(events, eventname) or not next(events[eventname]) then return end
+		local oldrecurse = registry.recurse
+		registry.recurse = oldrecurse + 1
+
+		Dispatchers[select('#', ...) + 1](events[eventname], eventname, ...)
+
+		registry.recurse = oldrecurse
+
+		if registry.insertQueue and oldrecurse==0 then
+			-- Something in one of our callbacks wanted to register more callbacks; they got queued
+			for eventname,callbacks in pairs(registry.insertQueue) do
+				local first = not rawget(events, eventname) or not next(events[eventname])	-- test for empty before. not test for one member after. that one member may have been overwritten.
+				for self,func in pairs(callbacks) do
+					events[eventname][self] = func
+					-- fire OnUsed callback?
+					if first and registry.OnUsed then
+						registry.OnUsed(registry, target, eventname)
+						first = nil
+					end
+				end
+			end
+			registry.insertQueue = nil
+		end
+	end
+
+	-- Registration of a callback, handles:
+	--   self["method"], leads to self["method"](self, ...)
+	--   self with function ref, leads to functionref(...)
+	--   "addonId" (instead of self) with function ref, leads to functionref(...)
+	-- all with an optional arg, which, if present, gets passed as first argument (after self if present)
+	target[RegisterName] = function(self, eventname, method, ... --[[actually just a single arg]])
+		if type(eventname) ~= "string" then
+			error("Usage: "..RegisterName.."(eventname, method[, arg]): 'eventname' - string expected.", 2)
+		end
+
+		method = method or eventname
+
+		local first = not rawget(events, eventname) or not next(events[eventname])	-- test for empty before. not test for one member after. that one member may have been overwritten.
+
+		if type(method) ~= "string" and type(method) ~= "function" then
+			error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - string or function expected.", 2)
+		end
+
+		local regfunc
+
+		if type(method) == "string" then
+			-- self["method"] calling style
+			if type(self) ~= "table" then
+				error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): self was not a table?", 2)
+			elseif self==target then
+				error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): do not use Library:"..RegisterName.."(), use your own 'self'", 2)
+			elseif type(self[method]) ~= "function" then
+				error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - method '"..tostring(method).."' not found on self.", 2)
+			end
+
+			if select("#",...)>=1 then	-- this is not the same as testing for arg==nil!
+				local arg=select(1,...)
+				regfunc = function(...) self[method](self,arg,...) end
+			else
+				regfunc = function(...) self[method](self,...) end
+			end
+		else
+			-- function ref with self=object or self="addonId"
+			if type(self)~="table" and type(self)~="string" then
+				error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string expected.", 2)
+			end
+
+			if select("#",...)>=1 then	-- this is not the same as testing for arg==nil!
+				local arg=select(1,...)
+				regfunc = function(...) method(arg,...) end
+			else
+				regfunc = method
+			end
+		end
+
+
+		if events[eventname][self] or registry.recurse<1 then
+		-- if registry.recurse<1 then
+			-- we're overwriting an existing entry, or not currently recursing. just set it.
+			events[eventname][self] = regfunc
+			-- fire OnUsed callback?
+			if registry.OnUsed and first then
+				registry.OnUsed(registry, target, eventname)
+			end
+		else
+			-- we're currently processing a callback in this registry, so delay the registration of this new entry!
+			-- yes, we're a bit wasteful on garbage, but this is a fringe case, so we're picking low implementation overhead over garbage efficiency
+			registry.insertQueue = registry.insertQueue or setmetatable({},meta)
+			registry.insertQueue[eventname][self] = regfunc
+		end
+	end
+
+	-- Unregister a callback
+	target[UnregisterName] = function(self, eventname)
+		if not self or self==target then
+			error("Usage: "..UnregisterName.."(eventname): bad 'self'", 2)
+		end
+		if type(eventname) ~= "string" then
+			error("Usage: "..UnregisterName.."(eventname): 'eventname' - string expected.", 2)
+		end
+		if rawget(events, eventname) and events[eventname][self] then
+			events[eventname][self] = nil
+			-- Fire OnUnused callback?
+			if registry.OnUnused and not next(events[eventname]) then
+				registry.OnUnused(registry, target, eventname)
+			end
+		end
+		if registry.insertQueue and rawget(registry.insertQueue, eventname) and registry.insertQueue[eventname][self] then
+			registry.insertQueue[eventname][self] = nil
+		end
+	end
+
+	-- OPTIONAL: Unregister all callbacks for given selfs/addonIds
+	if UnregisterAllName then
+		target[UnregisterAllName] = function(...)
+			if select("#",...)<1 then
+				error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2)
+			end
+			if select("#",...)==1 and ...==target then
+				error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2)
+			end
+
+
+			for i=1,select("#",...) do
+				local self = select(i,...)
+				if registry.insertQueue then
+					for eventname, callbacks in pairs(registry.insertQueue) do
+						if callbacks[self] then
+							callbacks[self] = nil
+						end
+					end
+				end
+				for eventname, callbacks in pairs(events) do
+					if callbacks[self] then
+						callbacks[self] = nil
+						-- Fire OnUnused callback?
+						if registry.OnUnused and not next(callbacks) then
+							registry.OnUnused(registry, target, eventname)
+						end
+					end
+				end
+			end
+		end
+	end
+
+	return registry
+end
+
+
+-- CallbackHandler purposefully does NOT do explicit embedding. Nor does it
+-- try to upgrade old implicit embeds since the system is selfcontained and
+-- relies on closures to work.
+
diff --git a/libs/LibDataBroker-1.1.lua b/libs/LibDataBroker-1.1.lua
new file mode 100644
index 0000000..f47c0cd
--- /dev/null
+++ b/libs/LibDataBroker-1.1.lua
@@ -0,0 +1,90 @@
+
+assert(LibStub, "LibDataBroker-1.1 requires LibStub")
+assert(LibStub:GetLibrary("CallbackHandler-1.0", true), "LibDataBroker-1.1 requires CallbackHandler-1.0")
+
+local lib, oldminor = LibStub:NewLibrary("LibDataBroker-1.1", 4)
+if not lib then return end
+oldminor = oldminor or 0
+
+
+lib.callbacks = lib.callbacks or LibStub:GetLibrary("CallbackHandler-1.0"):New(lib)
+lib.attributestorage, lib.namestorage, lib.proxystorage = lib.attributestorage or {}, lib.namestorage or {}, lib.proxystorage or {}
+local attributestorage, namestorage, callbacks = lib.attributestorage, lib.namestorage, lib.callbacks
+
+if oldminor < 2 then
+	lib.domt = {
+		__metatable = "access denied",
+		__index = function(self, key) return attributestorage[self] and attributestorage[self][key] end,
+	}
+end
+
+if oldminor < 3 then
+	lib.domt.__newindex = function(self, key, value)
+		if not attributestorage[self] then attributestorage[self] = {} end
+		if attributestorage[self][key] == value then return end
+		attributestorage[self][key] = value
+		local name = namestorage[self]
+		if not name then return end
+		callbacks:Fire("LibDataBroker_AttributeChanged", name, key, value, self)
+		callbacks:Fire("LibDataBroker_AttributeChanged_"..name, name, key, value, self)
+		callbacks:Fire("LibDataBroker_AttributeChanged_"..name.."_"..key, name, key, value, self)
+		callbacks:Fire("LibDataBroker_AttributeChanged__"..key, name, key, value, self)
+	end
+end
+
+if oldminor < 2 then
+	function lib:NewDataObject(name, dataobj)
+		if self.proxystorage[name] then return end
+
+		if dataobj then
+			assert(type(dataobj) == "table", "Invalid dataobj, must be nil or a table")
+			self.attributestorage[dataobj] = {}
+			for i,v in pairs(dataobj) do
+				self.attributestorage[dataobj][i] = v
+				dataobj[i] = nil
+			end
+		end
+		dataobj = setmetatable(dataobj or {}, self.domt)
+		self.proxystorage[name], self.namestorage[dataobj] = dataobj, name
+		self.callbacks:Fire("LibDataBroker_DataObjectCreated", name, dataobj)
+		return dataobj
+	end
+end
+
+if oldminor < 1 then
+	function lib:DataObjectIterator()
+		return pairs(self.proxystorage)
+	end
+
+	function lib:GetDataObjectByName(dataobjectname)
+		return self.proxystorage[dataobjectname]
+	end
+
+	function lib:GetNameByDataObject(dataobject)
+		return self.namestorage[dataobject]
+	end
+end
+
+if oldminor < 4 then
+	local next = pairs(attributestorage)
+	function lib:pairs(dataobject_or_name)
+		local t = type(dataobject_or_name)
+		assert(t == "string" or t == "table", "Usage: ldb:pairs('dataobjectname') or ldb:pairs(dataobject)")
+
+		local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name
+		assert(attributestorage[dataobj], "Data object not found")
+
+		return next, attributestorage[dataobj], nil
+	end
+
+	local ipairs_iter = ipairs(attributestorage)
+	function lib:ipairs(dataobject_or_name)
+		local t = type(dataobject_or_name)
+		assert(t == "string" or t == "table", "Usage: ldb:ipairs('dataobjectname') or ldb:ipairs(dataobject)")
+
+		local dataobj = self.proxystorage[dataobject_or_name] or dataobject_or_name
+		assert(attributestorage[dataobj], "Data object not found")
+
+		return ipairs_iter, attributestorage[dataobj], 0
+	end
+end
diff --git a/libs/LibStub.lua b/libs/LibStub.lua
new file mode 100644
index 0000000..cfc97de
--- /dev/null
+++ b/libs/LibStub.lua
@@ -0,0 +1,30 @@
+-- LibStub is a simple versioning stub meant for use in Libraries.  http://www.wowace.com/wiki/LibStub for more info
+-- LibStub is hereby placed in the Public Domain Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke
+local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2  -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS!
+local LibStub = _G[LIBSTUB_MAJOR]
+
+if not LibStub or LibStub.minor < LIBSTUB_MINOR then
+	LibStub = LibStub or {libs = {}, minors = {} }
+	_G[LIBSTUB_MAJOR] = LibStub
+	LibStub.minor = LIBSTUB_MINOR
+
+	function LibStub:NewLibrary(major, minor)
+		assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
+		minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
+
+		local oldminor = self.minors[major]
+		if oldminor and oldminor >= minor then return nil end
+		self.minors[major], self.libs[major] = minor, self.libs[major] or {}
+		return self.libs[major], oldminor
+	end
+
+	function LibStub:GetLibrary(major, silent)
+		if not self.libs[major] and not silent then
+			error(("Cannot find a library instance of %q."):format(tostring(major)), 2)
+		end
+		return self.libs[major], self.minors[major]
+	end
+
+	function LibStub:IterateLibraries() return pairs(self.libs) end
+	setmetatable(LibStub, { __call = LibStub.GetLibrary })
+end