annotate modules/FuBar_ReActionFu/lib/LibRock-1.0/LibRock-1.0.lua @ 30:0d95ce7a9ec2

- added Ace3 externs - converted ReAction_ConfigUI to use blizzard interface addons panel via AceConfigDialog-3.0 - partially converted FuBar module to LibRock, deprecated it (going to remove it entirely later) - cleaned up a couple other tidbits
author Flick <flickerstreak@gmail.com>
date Wed, 02 Apr 2008 23:31:13 +0000
parents
children
rev   line source
flickerstreak@30 1 --[[
flickerstreak@30 2 Name: LibRock-1.0
flickerstreak@30 3 Revision: $Rev: 63317 $
flickerstreak@30 4 Developed by: ckknight (ckknight@gmail.com)
flickerstreak@30 5 Website: http://www.wowace.com/
flickerstreak@30 6 Description: Library to allow for library and addon creation and easy table recycling functions.
flickerstreak@30 7 License: LGPL v2.1
flickerstreak@30 8 ]]
flickerstreak@30 9
flickerstreak@30 10 local MAJOR_VERSION = "LibRock-1.0"
flickerstreak@30 11 local MINOR_VERSION = tonumber(("$Revision: 63317 $"):match("(%d+)")) - 60000
flickerstreak@30 12
flickerstreak@30 13 local _G = _G
flickerstreak@30 14 local GetLocale = _G.GetLocale
flickerstreak@30 15 local CATEGORIES
flickerstreak@30 16 if GetLocale() == "deDE" then
flickerstreak@30 17 CATEGORIES = {
flickerstreak@30 18 ["Action Bars"] = "Aktionsleisten",
flickerstreak@30 19 ["Auction"] = "Auktion",
flickerstreak@30 20 ["Audio"] = "Audio",
flickerstreak@30 21 ["Battlegrounds/PvP"] = "Schlachtfeld/PvP",
flickerstreak@30 22 ["Buffs"] = "Stärkungszauber",
flickerstreak@30 23 ["Chat/Communication"] = "Chat/Kommunikation",
flickerstreak@30 24 ["Druid"] = "Druide",
flickerstreak@30 25 ["Hunter"] = "Jäger",
flickerstreak@30 26 ["Mage"] = "Magier",
flickerstreak@30 27 ["Paladin"] = "Paladin",
flickerstreak@30 28 ["Priest"] = "Priester",
flickerstreak@30 29 ["Rogue"] = "Schurke",
flickerstreak@30 30 ["Shaman"] = "Schamane",
flickerstreak@30 31 ["Warlock"] = "Hexenmeister",
flickerstreak@30 32 ["Warrior"] = "Krieger",
flickerstreak@30 33 ["Healer"] = "Heiler",
flickerstreak@30 34 ["Tank"] = "Tank",
flickerstreak@30 35 ["Caster"] = "Zauberer",
flickerstreak@30 36 ["Combat"] = "Kampf",
flickerstreak@30 37 ["Compilations"] = "Zusammenstellungen",
flickerstreak@30 38 ["Data Export"] = "Datenexport",
flickerstreak@30 39 ["Development Tools"] = "Entwicklungstools",
flickerstreak@30 40 ["Guild"] = "Gilde",
flickerstreak@30 41 ["Frame Modification"] = "Frameveränderungen",
flickerstreak@30 42 ["Interface Enhancements"] = "Interfaceverbesserungen",
flickerstreak@30 43 ["Inventory"] = "Inventar",
flickerstreak@30 44 ["Library"] = "Bibliotheken",
flickerstreak@30 45 ["Map"] = "Karte",
flickerstreak@30 46 ["Mail"] = "Post",
flickerstreak@30 47 ["Miscellaneous"] = "Diverses",
flickerstreak@30 48 ["Quest"] = "Quest",
flickerstreak@30 49 ["Raid"] = "Schlachtzug",
flickerstreak@30 50 ["Tradeskill"] = "Beruf",
flickerstreak@30 51 ["UnitFrame"] = "Einheiten-Fenster",
flickerstreak@30 52 }
flickerstreak@30 53 elseif GetLocale() == "frFR" then
flickerstreak@30 54 CATEGORIES = {
flickerstreak@30 55 ["Action Bars"] = "Barres d'action",
flickerstreak@30 56 ["Auction"] = "Hôtel des ventes",
flickerstreak@30 57 ["Audio"] = "Audio",
flickerstreak@30 58 ["Battlegrounds/PvP"] = "Champs de bataille/JcJ",
flickerstreak@30 59 ["Buffs"] = "Buffs",
flickerstreak@30 60 ["Chat/Communication"] = "Chat/Communication",
flickerstreak@30 61 ["Druid"] = "Druide",
flickerstreak@30 62 ["Hunter"] = "Chasseur",
flickerstreak@30 63 ["Mage"] = "Mage",
flickerstreak@30 64 ["Paladin"] = "Paladin",
flickerstreak@30 65 ["Priest"] = "Prêtre",
flickerstreak@30 66 ["Rogue"] = "Voleur",
flickerstreak@30 67 ["Shaman"] = "Chaman",
flickerstreak@30 68 ["Warlock"] = "Démoniste",
flickerstreak@30 69 ["Warrior"] = "Guerrier",
flickerstreak@30 70 ["Healer"] = "Soigneur",
flickerstreak@30 71 ["Tank"] = "Tank",
flickerstreak@30 72 ["Caster"] = "Casteur",
flickerstreak@30 73 ["Combat"] = "Combat",
flickerstreak@30 74 ["Compilations"] = "Compilations",
flickerstreak@30 75 ["Data Export"] = "Exportation de données",
flickerstreak@30 76 ["Development Tools"] = "Outils de développement",
flickerstreak@30 77 ["Guild"] = "Guilde",
flickerstreak@30 78 ["Frame Modification"] = "Modification des fenêtres",
flickerstreak@30 79 ["Interface Enhancements"] = "Améliorations de l'interface",
flickerstreak@30 80 ["Inventory"] = "Inventaire",
flickerstreak@30 81 ["Library"] = "Bibliothèques",
flickerstreak@30 82 ["Map"] = "Carte",
flickerstreak@30 83 ["Mail"] = "Courrier",
flickerstreak@30 84 ["Miscellaneous"] = "Divers",
flickerstreak@30 85 ["Quest"] = "Quêtes",
flickerstreak@30 86 ["Raid"] = "Raid",
flickerstreak@30 87 ["Tradeskill"] = "Métiers",
flickerstreak@30 88 ["UnitFrame"] = "Fenêtres d'unité",
flickerstreak@30 89 }
flickerstreak@30 90 elseif GetLocale() == "koKR" then
flickerstreak@30 91 CATEGORIES = {
flickerstreak@30 92 ["Action Bars"] = "액션바",
flickerstreak@30 93 ["Auction"] = "경매",
flickerstreak@30 94 ["Audio"] = "음향",
flickerstreak@30 95 ["Battlegrounds/PvP"] = "전장/PvP",
flickerstreak@30 96 ["Buffs"] = "버프",
flickerstreak@30 97 ["Chat/Communication"] = "대화/의사소통",
flickerstreak@30 98 ["Druid"] = "드루이드",
flickerstreak@30 99 ["Hunter"] = "사냥꾼",
flickerstreak@30 100 ["Mage"] = "마법사",
flickerstreak@30 101 ["Paladin"] = "성기사",
flickerstreak@30 102 ["Priest"] = "사제",
flickerstreak@30 103 ["Rogue"] = "도적",
flickerstreak@30 104 ["Shaman"] = "주술사",
flickerstreak@30 105 ["Warlock"] = "흑마법사",
flickerstreak@30 106 ["Warrior"] = "전사",
flickerstreak@30 107 ["Healer"] = "힐러",
flickerstreak@30 108 ["Tank"] = "탱커",
flickerstreak@30 109 ["Caster"] = "캐스터",
flickerstreak@30 110 ["Combat"] = "전투",
flickerstreak@30 111 ["Compilations"] = "복합",
flickerstreak@30 112 ["Data Export"] = "자료 출력",
flickerstreak@30 113 ["Development Tools"] = "개발 도구",
flickerstreak@30 114 ["Guild"] = "길드",
flickerstreak@30 115 ["Frame Modification"] = "구조 변경",
flickerstreak@30 116 ["Interface Enhancements"] = "인터페이스 강화",
flickerstreak@30 117 ["Inventory"] = "인벤토리",
flickerstreak@30 118 ["Library"] = "라이브러리",
flickerstreak@30 119 ["Map"] = "지도",
flickerstreak@30 120 ["Mail"] = "우편",
flickerstreak@30 121 ["Miscellaneous"] = "기타",
flickerstreak@30 122 ["Quest"] = "퀘스트",
flickerstreak@30 123 ["Raid"] = "공격대",
flickerstreak@30 124 ["Tradeskill"] = "전문기술",
flickerstreak@30 125 ["UnitFrame"] = "유닛 프레임",
flickerstreak@30 126 }
flickerstreak@30 127 elseif GetLocale() == "zhTW" then
flickerstreak@30 128 CATEGORIES = {
flickerstreak@30 129 ["Action Bars"] = "動作列",
flickerstreak@30 130 ["Auction"] = "拍賣",
flickerstreak@30 131 ["Audio"] = "音效",
flickerstreak@30 132 ["Battlegrounds/PvP"] = "戰場/PvP",
flickerstreak@30 133 ["Buffs"] = "增益",
flickerstreak@30 134 ["Chat/Communication"] = "聊天/通訊",
flickerstreak@30 135 ["Druid"] = "德魯伊",
flickerstreak@30 136 ["Hunter"] = "獵人",
flickerstreak@30 137 ["Mage"] = "法師",
flickerstreak@30 138 ["Paladin"] = "聖騎士",
flickerstreak@30 139 ["Priest"] = "牧師",
flickerstreak@30 140 ["Rogue"] = "盜賊",
flickerstreak@30 141 ["Shaman"] = "薩滿",
flickerstreak@30 142 ["Warlock"] = "術士",
flickerstreak@30 143 ["Warrior"] = "戰士",
flickerstreak@30 144 ["Healer"] = "治療者",
flickerstreak@30 145 ["Tank"] = "坦克",
flickerstreak@30 146 ["Caster"] = "施法者",
flickerstreak@30 147 ["Combat"] = "戰鬥",
flickerstreak@30 148 ["Compilations"] = "整合",
flickerstreak@30 149 ["Data Export"] = "資料匯出",
flickerstreak@30 150 ["Development Tools"] = "開發工具",
flickerstreak@30 151 ["Guild"] = "公會",
flickerstreak@30 152 ["Frame Modification"] = "框架修改",
flickerstreak@30 153 ["Interface Enhancements"] = "介面增強",
flickerstreak@30 154 ["Inventory"] = "庫存",
flickerstreak@30 155 ["Library"] = "程式庫",
flickerstreak@30 156 ["Map"] = "地圖",
flickerstreak@30 157 ["Mail"] = "郵件",
flickerstreak@30 158 ["Miscellaneous"] = "雜項",
flickerstreak@30 159 ["Quest"] = "任務",
flickerstreak@30 160 ["Raid"] = "團隊",
flickerstreak@30 161 ["Tradeskill"] = "交易技能",
flickerstreak@30 162 ["UnitFrame"] = "頭像框架",
flickerstreak@30 163 }
flickerstreak@30 164 elseif GetLocale() == "zhCN" then
flickerstreak@30 165 CATEGORIES = {
flickerstreak@30 166 ["Action Bars"] = "动作条",
flickerstreak@30 167 ["Auction"] = "拍卖",
flickerstreak@30 168 ["Audio"] = "音频",
flickerstreak@30 169 ["Battlegrounds/PvP"] = "战场/PvP",
flickerstreak@30 170 ["Buffs"] = "增益魔法",
flickerstreak@30 171 ["Chat/Communication"] = "聊天/交流",
flickerstreak@30 172 ["Druid"] = "德鲁伊",
flickerstreak@30 173 ["Hunter"] = "猎人",
flickerstreak@30 174 ["Mage"] = "法师",
flickerstreak@30 175 ["Paladin"] = "圣骑士",
flickerstreak@30 176 ["Priest"] = "牧师",
flickerstreak@30 177 ["Rogue"] = "潜行者",
flickerstreak@30 178 ["Shaman"] = "萨满祭司",
flickerstreak@30 179 ["Warlock"] = "术士",
flickerstreak@30 180 ["Warrior"] = "战士",
flickerstreak@30 181 ["Healer"] = "治疗",
flickerstreak@30 182 ["Tank"] = "坦克",
flickerstreak@30 183 ["Caster"] = "远程输出",
flickerstreak@30 184 ["Combat"] = "战斗",
flickerstreak@30 185 ["Compilations"] = "编译",
flickerstreak@30 186 ["Data Export"] = "数据导出",
flickerstreak@30 187 ["Development Tools"] = "开发工具",
flickerstreak@30 188 ["Guild"] = "公会",
flickerstreak@30 189 ["Frame Modification"] = "框架修改",
flickerstreak@30 190 ["Interface Enhancements"] = "界面增强",
flickerstreak@30 191 ["Inventory"] = "背包",
flickerstreak@30 192 ["Library"] = "库",
flickerstreak@30 193 ["Map"] = "地图",
flickerstreak@30 194 ["Mail"] = "邮件",
flickerstreak@30 195 ["Miscellaneous"] = "杂项",
flickerstreak@30 196 ["Quest"] = "任务",
flickerstreak@30 197 ["Raid"] = "团队",
flickerstreak@30 198 ["Tradeskill"] = "商业技能",
flickerstreak@30 199 ["UnitFrame"] = "头像框架",
flickerstreak@30 200 }
flickerstreak@30 201 elseif GetLocale() == "esES" then
flickerstreak@30 202 CATEGORIES = {
flickerstreak@30 203 ["Action Bars"] = "Barras de Acción",
flickerstreak@30 204 ["Auction"] = "Subasta",
flickerstreak@30 205 ["Audio"] = "Audio",
flickerstreak@30 206 ["Battlegrounds/PvP"] = "Campos de Batalla/JcJ",
flickerstreak@30 207 ["Buffs"] = "Buffs",
flickerstreak@30 208 ["Chat/Communication"] = "Chat/Comunicación",
flickerstreak@30 209 ["Druid"] = "Druida",
flickerstreak@30 210 ["Hunter"] = "Cazador",
flickerstreak@30 211 ["Mage"] = "Mago",
flickerstreak@30 212 ["Paladin"] = "Paladín",
flickerstreak@30 213 ["Priest"] = "Sacerdote",
flickerstreak@30 214 ["Rogue"] = "Pícaro",
flickerstreak@30 215 ["Shaman"] = "Chamán",
flickerstreak@30 216 ["Warlock"] = "Brujo",
flickerstreak@30 217 ["Warrior"] = "Guerrero",
flickerstreak@30 218 ["Healer"] = "Sanador",
flickerstreak@30 219 ["Tank"] = "Tanque",
flickerstreak@30 220 ["Caster"] = "Conjurador",
flickerstreak@30 221 ["Combat"] = "Combate",
flickerstreak@30 222 ["Compilations"] = "Compilaciones",
flickerstreak@30 223 ["Data Export"] = "Exportar Datos",
flickerstreak@30 224 ["Development Tools"] = "Herramientas de Desarrollo",
flickerstreak@30 225 ["Guild"] = "Hermandad",
flickerstreak@30 226 ["Frame Modification"] = "Modificación de Marcos",
flickerstreak@30 227 ["Interface Enhancements"] = "Mejoras de la Interfaz",
flickerstreak@30 228 ["Inventory"] = "Inventario",
flickerstreak@30 229 ["Library"] = "Biblioteca",
flickerstreak@30 230 ["Map"] = "Mapa",
flickerstreak@30 231 ["Mail"] = "Correo",
flickerstreak@30 232 ["Miscellaneous"] = "Misceláneo",
flickerstreak@30 233 ["Quest"] = "Misión",
flickerstreak@30 234 ["Raid"] = "Banda",
flickerstreak@30 235 ["Tradeskill"] = "Habilidad de Comercio",
flickerstreak@30 236 ["UnitFrame"] = "Marco de Unidades",
flickerstreak@30 237 }
flickerstreak@30 238 else -- enUS
flickerstreak@30 239 CATEGORIES = {
flickerstreak@30 240 ["Action Bars"] = "Action Bars",
flickerstreak@30 241 ["Auction"] = "Auction",
flickerstreak@30 242 ["Audio"] = "Audio",
flickerstreak@30 243 ["Battlegrounds/PvP"] = "Battlegrounds/PvP",
flickerstreak@30 244 ["Buffs"] = "Buffs",
flickerstreak@30 245 ["Chat/Communication"] = "Chat/Communication",
flickerstreak@30 246 ["Druid"] = "Druid",
flickerstreak@30 247 ["Hunter"] = "Hunter",
flickerstreak@30 248 ["Mage"] = "Mage",
flickerstreak@30 249 ["Paladin"] = "Paladin",
flickerstreak@30 250 ["Priest"] = "Priest",
flickerstreak@30 251 ["Rogue"] = "Rogue",
flickerstreak@30 252 ["Shaman"] = "Shaman",
flickerstreak@30 253 ["Warlock"] = "Warlock",
flickerstreak@30 254 ["Warrior"] = "Warrior",
flickerstreak@30 255 ["Healer"] = "Healer",
flickerstreak@30 256 ["Tank"] = "Tank",
flickerstreak@30 257 ["Caster"] = "Caster",
flickerstreak@30 258 ["Combat"] = "Combat",
flickerstreak@30 259 ["Compilations"] = "Compilations",
flickerstreak@30 260 ["Data Export"] = "Data Export",
flickerstreak@30 261 ["Development Tools"] = "Development Tools",
flickerstreak@30 262 ["Guild"] = "Guild",
flickerstreak@30 263 ["Frame Modification"] = "Frame Modification",
flickerstreak@30 264 ["Interface Enhancements"] = "Interface Enhancements",
flickerstreak@30 265 ["Inventory"] = "Inventory",
flickerstreak@30 266 ["Library"] = "Library",
flickerstreak@30 267 ["Map"] = "Map",
flickerstreak@30 268 ["Mail"] = "Mail",
flickerstreak@30 269 ["Miscellaneous"] = "Miscellaneous",
flickerstreak@30 270 ["Quest"] = "Quest",
flickerstreak@30 271 ["Raid"] = "Raid",
flickerstreak@30 272 ["Tradeskill"] = "Tradeskill",
flickerstreak@30 273 ["UnitFrame"] = "UnitFrame",
flickerstreak@30 274 }
flickerstreak@30 275 end
flickerstreak@30 276
flickerstreak@30 277 local select = _G.select
flickerstreak@30 278 local tostring = _G.tostring
flickerstreak@30 279 local pairs = _G.pairs
flickerstreak@30 280 local ipairs = _G.ipairs
flickerstreak@30 281 local error = _G.error
flickerstreak@30 282 local setmetatable = _G.setmetatable
flickerstreak@30 283 local getmetatable = _G.getmetatable
flickerstreak@30 284 local type = _G.type
flickerstreak@30 285 local pcall = _G.pcall
flickerstreak@30 286 local next = _G.next
flickerstreak@30 287 local tonumber = _G.tonumber
flickerstreak@30 288 local strmatch = _G.strmatch
flickerstreak@30 289 local table_remove = _G.table.remove
flickerstreak@30 290 local debugstack = _G.debugstack
flickerstreak@30 291 local LoadAddOn = _G.LoadAddOn
flickerstreak@30 292 local GetAddOnInfo = _G.GetAddOnInfo
flickerstreak@30 293 local GetAddOnMetadata = _G.GetAddOnMetadata
flickerstreak@30 294 local GetNumAddOns = _G.GetNumAddOns
flickerstreak@30 295 local DisableAddOn = _G.DisableAddOn
flickerstreak@30 296 local EnableAddOn = _G.EnableAddOn
flickerstreak@30 297 local IsAddOnLoadOnDemand = _G.IsAddOnLoadOnDemand
flickerstreak@30 298 local IsLoggedIn = _G.IsLoggedIn
flickerstreak@30 299 local geterrorhandler = _G.geterrorhandler
flickerstreak@30 300 local assert = _G.assert
flickerstreak@30 301 local collectgarbage = _G.collectgarbage
flickerstreak@30 302 local table_sort = _G.table.sort
flickerstreak@30 303 local table_concat = _G.table.concat
flickerstreak@30 304
flickerstreak@30 305 -- #AUTODOC_NAMESPACE Rock
flickerstreak@30 306
flickerstreak@30 307
flickerstreak@30 308 local LibStub = _G.LibStub
flickerstreak@30 309
flickerstreak@30 310 local Rock = LibStub:GetLibrary(MAJOR_VERSION, true) or _G.Rock
flickerstreak@30 311 local oldRock
flickerstreak@30 312 if not Rock then
flickerstreak@30 313 Rock = LibStub:NewLibrary(MAJOR_VERSION, MINOR_VERSION)
flickerstreak@30 314 if not Rock then
flickerstreak@30 315 return
flickerstreak@30 316 end
flickerstreak@30 317 Rock.name = MAJOR_VERSION
flickerstreak@30 318 else
flickerstreak@30 319 Rock, oldRock = Rock:NewLibrary(MAJOR_VERSION, MINOR_VERSION)
flickerstreak@30 320 if not Rock then
flickerstreak@30 321 return
flickerstreak@30 322 end
flickerstreak@30 323 end
flickerstreak@30 324 _G.Rock = Rock
flickerstreak@30 325
flickerstreak@30 326 local L = setmetatable({}, {__index=function(self,key) self[key] = key; return key end})
flickerstreak@30 327 if GetLocale() == "zhCN" then
flickerstreak@30 328 L["Advanced options"] = "高级选项"
flickerstreak@30 329 L["Advanced options for developers and power users."] = "开发者与高级用户的高级选项"
flickerstreak@30 330 L["Unit tests"] = "框体测试"
flickerstreak@30 331 L["Enable unit tests to be run. This is for developers only.\n\nYou must ReloadUI for changes to take effect."] = "开启框体测试,仅供开发者使用。\n\n需要重载用户界面。"
flickerstreak@30 332 L["Contracts"] = "侦错协定"
flickerstreak@30 333 L["Enable contracts to be run. This is for developers and anyone wanting to file a bug. Do not file a bug unless contracts are enabled. This will slightly slow down your addons if enabled."] = "启用侦错协定,这是给插件作者用来通报错误所使用。"
flickerstreak@30 334 L["Reload UI"] = "重载UI"
flickerstreak@30 335 L["Reload the User Interface for some changes to take effect."] = "部分功能更改需要重载用户界面才会生效。"
flickerstreak@30 336 L["Reload"] = "重载"
flickerstreak@30 337 L["Give donation"] = "捐赠"
flickerstreak@30 338 L["Donate"] = "捐赠"
flickerstreak@30 339 L["Give a much-needed donation to the author of this addon."] = "给插件作者捐赠支持插件开发。"
flickerstreak@30 340 L["File issue"] = "通报错误"
flickerstreak@30 341 L["Report"] = "报告"
flickerstreak@30 342 L["File a bug or request a new feature or an improvement to this addon."] = "发送错误报告或请求新功能及要改进的部分。"
flickerstreak@30 343 L["Press Ctrl-C to copy, then Alt-Tab out of the game, open your favorite web browser, and paste the link into the address bar."] = "Ctrl-C复制网址,Alt-Tab切换到桌面,打开浏览器,在地址栏贴上网址。"
flickerstreak@30 344 L["Press Cmd-C to copy, then Cmd-Tab out of the game, open your favorite web browser, and paste the link into the address bar."] = "Cmd-C复制网址,Cmd-Tab切换到电脑桌面,打开浏览器,在地址栏贴上网址。"
flickerstreak@30 345 L["Enabled"] = "开启"
flickerstreak@30 346 L["Enable or disable this addon."] = "启用这个插件。"
flickerstreak@30 347
flickerstreak@30 348 elseif GetLocale() == "zhTW" then
flickerstreak@30 349 L["Advanced options"] = "進階選項"
flickerstreak@30 350 L["Advanced options for developers and power users."] = "插件作者、進階用戶選項"
flickerstreak@30 351 L["Unit tests"] = "單元測試"
flickerstreak@30 352 L["Enable unit tests to be run. This is for developers only.\n\nYou must ReloadUI for changes to take effect."] = "啟用單元測試,這是給插件作者使用的功能。\n\n需要重載介面才能使用。"
flickerstreak@30 353 L["Contracts"] = "偵錯協定"
flickerstreak@30 354 L["Enable contracts to be run. This is for developers and anyone wanting to file a bug. Do not file a bug unless contracts are enabled. This will slightly slow down your addons if enabled."] = "啟用偵錯協定,這是給插件作者用來通報錯誤所使用。"
flickerstreak@30 355 L["Reload UI"] = "重載介面"
flickerstreak@30 356 L["Reload the User Interface for some changes to take effect."] = "重新載入使用者介面,部分功能才會生效。"
flickerstreak@30 357 L["Reload"] = "重載"
flickerstreak@30 358 L["Give donation"] = "捐贈"
flickerstreak@30 359 L["Donate"] = "捐贈"
flickerstreak@30 360 L["Give a much-needed donation to the author of this addon."] = "捐贈金錢給插件作者。"
flickerstreak@30 361 L["File issue"] = "通報錯誤"
flickerstreak@30 362 L["Report"] = "報告"
flickerstreak@30 363 L["File a bug or request a new feature or an improvement to this addon."] = "發出錯誤報告或請求新功能及要改進的部分。"
flickerstreak@30 364 L["Press Ctrl-C to copy, then Alt-Tab out of the game, open your favorite web browser, and paste the link into the address bar."] = "Ctrl-C複製網址,Alt-Tab切換到電腦桌面,打開瀏覽器,在網址列貼上網址。"
flickerstreak@30 365 L["Press Cmd-C to copy, then Cmd-Tab out of the game, open your favorite web browser, and paste the link into the address bar."] = "Cmd-C複製網址,Cmd-Tab切換到電腦桌面,打開瀏覽器,在網址列貼上網址。"
flickerstreak@30 366 L["Enabled"] = "啟用"
flickerstreak@30 367 L["Enable or disable this addon."] = "啟用這個插件。"
flickerstreak@30 368 elseif GetLocale() == "koKR" then
flickerstreak@30 369 L["Advanced options"] = "상세 옵션"
flickerstreak@30 370 L["Advanced options for developers and power users."] = "개발자와 파워 사용자를 위한 상세 옵션입니다."
flickerstreak@30 371 L["Unit tests"] = "유닛 테스트"
flickerstreak@30 372 L["Enable unit tests to be run. This is for developers only.\n\nYou must ReloadUI for changes to take effect."] = "유닛 테스트를 사용합니다. 이것은 개발자만을 위한 옵션입니다.\n\n변경된 결과를 적용하기 위해 당신의 UI를 재실행 합니다."
flickerstreak@30 373 L["Contracts"] = "계약"
flickerstreak@30 374 L["Enable contracts to be run. This is for developers and anyone wanting to file a bug. Do not file a bug unless contracts are enabled. This will slightly slow down your addons if enabled."] = "계약을 사용합니다. 이것은 개발자와 버그 파일을 알릴 분이면 누구나 사용 가능합니다. 계약이 가능하지 않으면 버그 파일을 보내지 마십시오. 이것은 당신의 애드온 속도를 약간 떨어뜨립니다."
flickerstreak@30 375 L["Reload UI"] = "UI 재실행"
flickerstreak@30 376 L["Reload the User Interface for some changes to take effect."] = "변경된 결과를 적용하기 위해 사용자 인터페이스를 재실행합니다."
flickerstreak@30 377 L["Reload"] = "재실행"
flickerstreak@30 378 L["Give donation"] = "기부"
flickerstreak@30 379 L["Donate"] = "기부"
flickerstreak@30 380 L["Give a much-needed donation to the author of this addon."] = "이 애드온의 제작자에게 필요한 기부를 합니다."
flickerstreak@30 381 L["File issue"] = "파일 이슈"
flickerstreak@30 382 L["Report"] = "보고"
flickerstreak@30 383 L["File a bug or request a new feature or an improvement to this addon."] = "버그 파일을 알리거나 새로운 기능 또는 이 애드온에 대한 개선을 부탁합니다."
flickerstreak@30 384 L["Press Ctrl-C to copy, then Alt-Tab out of the game, open your favorite web browser, and paste the link into the address bar."] = "Ctrl-C로 복사합니다. Alt-Tab 눌려 게임으로 부터 나간후 웹 브라우저를 엽니다. 복사된 링크를 주소 창에 붙여넣기 합니다."
flickerstreak@30 385 L["Press Cmd-C to copy, then Cmd-Tab out of the game, open your favorite web browser, and paste the link into the address bar."] = "Cmd-C로 복사합니다. Cmd-Tab 눌려 게임으로 부터 나간후 웹 브라우저를 엽니다. 복사된 링크를 주소 창에 붙여넣기 합니다."
flickerstreak@30 386 L["Enabled"] = "사용"
flickerstreak@30 387 L["Enable or disable this addon."] = "이 애드온을 사용하거나 사용하지 않습니다."
flickerstreak@30 388 elseif GetLocale() == "frFR" then
flickerstreak@30 389 L["Advanced options"] = "Options avancées"
flickerstreak@30 390 L["Advanced options for developers and power users."] = "Options avancées à l'attention des développeurs et des utilisateurs expérimentés."
flickerstreak@30 391 L["Reload UI"] = "Recharger IU"
flickerstreak@30 392 L["Reload the User Interface for some changes to take effect."] = "Recharge l'interface utilisateur afin que certains changements prennent effet."
flickerstreak@30 393 L["Reload"] = "Recharger"
flickerstreak@30 394 L["Give donation"] = "Faire un don"
flickerstreak@30 395 L["Donate"] = "Don"
flickerstreak@30 396 L["Give a much-needed donation to the author of this addon."] = "Permet de faire un don bien mérité à l'auteur de cet addon."
flickerstreak@30 397 L["File issue"] = "Problème"
flickerstreak@30 398 L["Report"] = "Signaler"
flickerstreak@30 399 L["File a bug or request a new feature or an improvement to this addon."] = "Permet de signaler un bogue ou de demander une amélioration à cet addon."
flickerstreak@30 400 L["Press Ctrl-C to copy, then Alt-Tab out of the game, open your favorite web browser, and paste the link into the address bar."] = "Ctrl-C pour copier, puis Alt-Tab pour sortir du jeu. Ouvrez votre navigateur internet et collez le lien dans la barre d'adresse."
flickerstreak@30 401 L["Press Cmd-C to copy, then Cmd-Tab out of the game, open your favorite web browser, and paste the link into the address bar."] = "Cmd-C pour copier, puis Alt-Tab pour sortir du jeu. Ouvrez votre navigateur internet et collez le lien dans la barre d'adresse."
flickerstreak@30 402 L["Enabled"] = "Activé"
flickerstreak@30 403 L["Enable or disable this addon."] = "Active ou désactive cet addon."
flickerstreak@30 404 end
flickerstreak@30 405
flickerstreak@30 406 local isStandalone = debugstack():match("[Oo%.][Nn%.][Ss%.]\\([^\\]+)\\") == MAJOR_VERSION or nil
flickerstreak@30 407 local unitTestDB, enableContracts
flickerstreak@30 408
flickerstreak@30 409 local weakKey = { __mode = 'k' }
flickerstreak@30 410
flickerstreak@30 411 -- frame to manage events from
flickerstreak@30 412 Rock.frame = oldRock and oldRock.frame or _G.CreateFrame("Frame")
flickerstreak@30 413 local frame = Rock.frame
flickerstreak@30 414 -- dict of libraries in { ["major"] = object } form
flickerstreak@30 415 Rock.libraries = oldRock and oldRock.libraries or { [MAJOR_VERSION] = Rock }
flickerstreak@30 416 local libraries = Rock.libraries
flickerstreak@30 417 -- set of libraries which have gone through the finalization process in { [object] = true } form
flickerstreak@30 418 Rock.finalizedLibraries = setmetatable(oldRock and oldRock.finalizedLibraries or { }, weakKey)
flickerstreak@30 419 local finalizedLibraries = Rock.finalizedLibraries
flickerstreak@30 420 -- set of libraries which have been tried to be loaded.
flickerstreak@30 421 Rock.scannedLibraries = oldRock and oldRock.scannedLibraries or {}
flickerstreak@30 422 local scannedLibraries = Rock.scannedLibraries
flickerstreak@30 423 -- exportedMethods[library] = { "method1", "method2" }
flickerstreak@30 424 Rock.exportedMethods = setmetatable(oldRock and oldRock.exportedMethods or {}, weakKey)
flickerstreak@30 425 local exportedMethods = Rock.exportedMethods
flickerstreak@30 426 -- mixinToObject[mixin][object] = true
flickerstreak@30 427 Rock.mixinToObject = setmetatable(oldRock and oldRock.mixinToObject or {}, weakKey)
flickerstreak@30 428 local mixinToObject = Rock.mixinToObject
flickerstreak@30 429 -- dict of addons in { ["name"] = object } form
flickerstreak@30 430 Rock.addons = oldRock and oldRock.addons or {}
flickerstreak@30 431 local addons = Rock.addons
flickerstreak@30 432 -- set of libraries that should be finalized before ADDON_LOADED.
flickerstreak@30 433 Rock.pendingLibraries = setmetatable(oldRock and oldRock.pendingLibraries or { }, weakKey)
flickerstreak@30 434 local pendingLibraries = Rock.pendingLibraries
flickerstreak@30 435 -- list of addons in order of created that need to be initialized by ADDON_LOADED.
flickerstreak@30 436 Rock.pendingAddons = oldRock and oldRock.pendingAddons or {}
flickerstreak@30 437 local pendingAddons = Rock.pendingAddons
flickerstreak@30 438 -- dictionary of addons to their folder names
flickerstreak@30 439 Rock.addonToFolder = oldRock and oldRock.addonToFolder or {}
flickerstreak@30 440 local addonToFolder = Rock.addonToFolder
flickerstreak@30 441 -- set of folders which have been loaded
flickerstreak@30 442 Rock.foldersLoaded = oldRock and oldRock.foldersLoaded or {}
flickerstreak@30 443 local foldersLoaded = Rock.foldersLoaded
flickerstreak@30 444 -- list of addons in order of created that need to be enabled by PLAYER_LOGIN.
flickerstreak@30 445 Rock.pendingAddonsEnable = oldRock and oldRock.pendingAddonsEnable or {}
flickerstreak@30 446 local pendingAddonsEnable = Rock.pendingAddonsEnable
flickerstreak@30 447 -- set of addons which have been enabled at least once.
flickerstreak@30 448 Rock.addonsAlreadyEnabled = oldRock and oldRock.addonsAlreadyEnabled or {}
flickerstreak@30 449 local addonsAlreadyEnabled = Rock.addonsAlreadyEnabled
flickerstreak@30 450 -- set of addons which have no database and are set to be inactive.
flickerstreak@30 451 Rock.inactiveAddons = oldRock and oldRock.inactiveAddons or {}
flickerstreak@30 452 local inactiveAddons = Rock.inactiveAddons
flickerstreak@30 453 -- set of addons which are currently enabled (not necessarily should be)
flickerstreak@30 454 Rock.currentlyEnabledAddons = oldRock and oldRock.currentlyEnabledAddons or {}
flickerstreak@30 455 local currentlyEnabledAddons = Rock.currentlyEnabledAddons
flickerstreak@30 456 -- dictionary of namespace to list of functions which will be run.
flickerstreak@30 457 Rock.unitTests = oldRock and oldRock.unitTests or {}
flickerstreak@30 458 local unitTests = Rock.unitTests
flickerstreak@30 459 -- metatable for addons
flickerstreak@30 460 Rock.addon_mt = oldRock and oldRock.addon_mt or {}
flickerstreak@30 461 local addon_mt = Rock.addon_mt
flickerstreak@30 462 for k in pairs(addon_mt) do
flickerstreak@30 463 addon_mt[k] = nil
flickerstreak@30 464 end
flickerstreak@30 465 function addon_mt:__tostring()
flickerstreak@30 466 return tostring(self.name)
flickerstreak@30 467 end
flickerstreak@30 468
flickerstreak@30 469 local function better_tostring(self)
flickerstreak@30 470 if type(self) == "table" and self.name then
flickerstreak@30 471 return tostring(self.name)
flickerstreak@30 472 end
flickerstreak@30 473 return tostring(self)
flickerstreak@30 474 end
flickerstreak@30 475
flickerstreak@30 476 local function figureCurrentAddon(pos)
flickerstreak@30 477 local stack = debugstack(pos+1, 1, 0)
flickerstreak@30 478 local folder = stack:match("[Oo%.][Nn%.][Ss%.]\\([^\\]+)\\")
flickerstreak@30 479 if folder then
flickerstreak@30 480 return folder
flickerstreak@30 481 end
flickerstreak@30 482
flickerstreak@30 483 local partFolder = stack:match("...([^\\]+)\\")
flickerstreak@30 484 if partFolder then
flickerstreak@30 485 local partFolder_len = #partFolder
flickerstreak@30 486 for i = 1, GetNumAddOns() do
flickerstreak@30 487 local name = GetAddOnInfo(i)
flickerstreak@30 488 if #name >= partFolder_len then
flickerstreak@30 489 local partName = name:sub(-partFolder_len)
flickerstreak@30 490 if partName == partFolder then
flickerstreak@30 491 return name
flickerstreak@30 492 end
flickerstreak@30 493 end
flickerstreak@30 494 end
flickerstreak@30 495 end
flickerstreak@30 496 return nil
flickerstreak@30 497 end
flickerstreak@30 498
flickerstreak@30 499 --[[---------------------------------------------------------------------------
flickerstreak@30 500 Returns:
flickerstreak@30 501 string - the localized name of the given category.
flickerstreak@30 502 Arguments:
flickerstreak@30 503 string - the English name of the category.
flickerstreak@30 504 Example:
flickerstreak@30 505 local uf = Rock:GetLocalizedCategory("UnitFrame")
flickerstreak@30 506 -----------------------------------------------------------------------------]]
flickerstreak@30 507 function Rock:GetLocalizedCategory(name)
flickerstreak@30 508 if type(name) ~= "string" then
flickerstreak@30 509 error(("Bad argument #2 to `GetLocalizedCategory'. Expected %q, got %q."):format("string", type(name)), 2)
flickerstreak@30 510 end
flickerstreak@30 511 local cat = CATEGORIES[name]
flickerstreak@30 512 if cat then
flickerstreak@30 513 return cat
flickerstreak@30 514 end
flickerstreak@30 515 local name_lower = name:lower()
flickerstreak@30 516 for k in pairs(CATEGORIES) do
flickerstreak@30 517 if k:lower() == name_lower then
flickerstreak@30 518 return k
flickerstreak@30 519 end
flickerstreak@30 520 end
flickerstreak@30 521 return _G.UNKNOWN or "Unknown"
flickerstreak@30 522 end
flickerstreak@30 523
flickerstreak@30 524 local weak = {__mode = 'kv'}
flickerstreak@30 525
flickerstreak@30 526 Rock.recycleData = oldRock and oldRock.recycleData or {}
flickerstreak@30 527 local recycleData = Rock.recycleData
flickerstreak@30 528 if recycleData.pools then
flickerstreak@30 529 setmetatable(recycleData.pools, weak)
flickerstreak@30 530 end
flickerstreak@30 531 if recycleData.debugPools then
flickerstreak@30 532 setmetatable(recycleData.debugPools, weak)
flickerstreak@30 533 end
flickerstreak@30 534 if recycleData.newList then
flickerstreak@30 535 setmetatable(recycleData.newList, weak)
flickerstreak@30 536 end
flickerstreak@30 537 if recycleData.newDict then
flickerstreak@30 538 setmetatable(recycleData.newDict, weak)
flickerstreak@30 539 end
flickerstreak@30 540 if recycleData.newSet then
flickerstreak@30 541 setmetatable(recycleData.newSet, weak)
flickerstreak@30 542 end
flickerstreak@30 543 if recycleData.del then
flickerstreak@30 544 setmetatable(recycleData.del, weak)
flickerstreak@30 545 end
flickerstreak@30 546
flickerstreak@30 547 local tmp = {}
flickerstreak@30 548 local function myUnpack(t, start)
flickerstreak@30 549 if not start then
flickerstreak@30 550 start = 1
flickerstreak@30 551 end
flickerstreak@30 552 local value = t[start]
flickerstreak@30 553 if value == nil then
flickerstreak@30 554 return
flickerstreak@30 555 end
flickerstreak@30 556 t[start] = nil
flickerstreak@30 557 return value, myUnpack(t, start+1)
flickerstreak@30 558 end
flickerstreak@30 559
flickerstreak@30 560 --[[---------------------------------------------------------------------------
flickerstreak@30 561 Notes:
flickerstreak@30 562 * Returns functions for the specified namespace based on what is provided.
flickerstreak@30 563 * function types:
flickerstreak@30 564 ; "newList" : to create a list
flickerstreak@30 565 ; "newDict" : to create a dictionary
flickerstreak@30 566 ; "newSet" : to create a set
flickerstreak@30 567 ; "del" : to delete a table
flickerstreak@30 568 ; "unpackListAndDel" : deletes a table and returns what its contents were as a list, in order.
flickerstreak@30 569 ; "unpackSetAndDel" : deletes a table and returns what its contents were as a set, in no particular order.
flickerstreak@30 570 ; "unpackDictAndDel" : deletes a table and returns what its contents were as a dictionary, in no particular order.
flickerstreak@30 571 * If you provide "Debug" as the last argument, then the namespace can be debugged with ''':DebugRecycle'''
flickerstreak@30 572 * It is '''not recommended''' to use table recycling with tables that have more than 128 keys, as it is typically faster to let lua's garbage collector handle it.
flickerstreak@30 573 Arguments:
flickerstreak@30 574 string - the namespace. ''Note: this doesn't necessarily have to be a string.''
flickerstreak@30 575 Example:
flickerstreak@30 576 local newList, newDict, newSet, del, unpackListAndDel, unpackSetAndDel, unpackDictAndDel = Rock:GetRecyclingFunctions("MyNamespace", "newList", "newDict", "newSet", "del", "unpackListAndDel", "unpackSetAndDel", "unpackDictAndDel")
flickerstreak@30 577
flickerstreak@30 578 local t = newList('alpha', 'bravo') -- same as t = {'alpha', 'bravo'}
flickerstreak@30 579 local u = newDict('alpha', 'bravo') -- same as t = {['alpha'] = 'bravo'}
flickerstreak@30 580 local v = newSet('alpha', 'bravo') -- same as t = {['alpha'] = true, ['bravo'] = true}
flickerstreak@30 581 t = del(t) -- you want to clear your reference as well as deleting.
flickerstreak@30 582 u = del(u)
flickerstreak@30 583 v = del(v)
flickerstreak@30 584
flickerstreak@30 585 -- for debugging
flickerstreak@30 586 local newList = Rock:GetRecyclingFunctions("MyNamespace", "newList", "Debug")
flickerstreak@30 587 local t = newList()
flickerstreak@30 588 Rock:DebugRecycle("MyNamespace")
flickerstreak@30 589 t = del(t)
flickerstreak@30 590
flickerstreak@30 591 -- unpacking functions
flickerstreak@30 592 unpackListAndDel(newList(...)) => ...
flickerstreak@30 593 unpackSetAndDel(newSet(...)) => ...
flickerstreak@30 594 unpackDictAndDel(newDict(...)) => ...
flickerstreak@30 595 newList(unpackListAndDel(t)) => t
flickerstreak@30 596 newSet(unpackSetAndDel(t)) => t
flickerstreak@30 597 newDict(unpackDictAndDel(t)) => t
flickerstreak@30 598 -- as you can see, they are inverses of each other.
flickerstreak@30 599 -----------------------------------------------------------------------------]]
flickerstreak@30 600 function Rock:GetRecyclingFunctions(namespace, ...)
flickerstreak@30 601 local pools = recycleData.pools
flickerstreak@30 602 if not pools then
flickerstreak@30 603 pools = setmetatable({}, weak)
flickerstreak@30 604 recycleData.pools = pools
flickerstreak@30 605 end
flickerstreak@30 606 if namespace == "newList" or namespace == "newSet" or namespace == "newDict" or namespace == "del" or namespace == "unpackListAndDel" or namespace == "unpackSetAndDel" or namespace == "unpackDictAndDel" then
flickerstreak@30 607 error(("Bad argument #2 to `GetRecyclingFunctions'. Cannot be %q"):format(namespace), 2)
flickerstreak@30 608 end
flickerstreak@30 609 local pool = pools[namespace]
flickerstreak@30 610 if not pool then
flickerstreak@30 611 pool = setmetatable({}, weak)
flickerstreak@30 612 pools[namespace] = pool
flickerstreak@30 613 end
flickerstreak@30 614 local n = select('#', ...)
flickerstreak@30 615 local debug = select(n, ...) == "Debug"
flickerstreak@30 616 if debug then
flickerstreak@30 617 n = n - 1
flickerstreak@30 618 local debugPools = recycleData.debugPools
flickerstreak@30 619 if not debugPools then
flickerstreak@30 620 debugPools = setmetatable({}, weak)
flickerstreak@30 621 recycleData.debugPools = debugPools
flickerstreak@30 622 end
flickerstreak@30 623 debug = debugPools[namespace]
flickerstreak@30 624 if not debug then
flickerstreak@30 625 debug = { num = 0 }
flickerstreak@30 626 debugPools[namespace] = debug
flickerstreak@30 627 end
flickerstreak@30 628 elseif recycleData.debugPools and recycleData.debugPools[namespace] then
flickerstreak@30 629 debug = recycleData.debugPools[namespace]
flickerstreak@30 630 end
flickerstreak@30 631 for i = 1, n do
flickerstreak@30 632 local func = select(i, ...)
flickerstreak@30 633 local recycleData_func = recycleData[func]
flickerstreak@30 634 if not recycleData_func then
flickerstreak@30 635 recycleData_func = setmetatable({}, weak)
flickerstreak@30 636 recycleData[func] = recycleData_func
flickerstreak@30 637 end
flickerstreak@30 638 if func == "newList" then
flickerstreak@30 639 local newList = recycleData_func[namespace]
flickerstreak@30 640 if not newList then
flickerstreak@30 641 function newList(...)
flickerstreak@30 642 local t = next(pool)
flickerstreak@30 643 local n = select('#', ...)
flickerstreak@30 644 if t then
flickerstreak@30 645 pool[t] = nil
flickerstreak@30 646 for i = 1, n do
flickerstreak@30 647 t[i] = select(i, ...)
flickerstreak@30 648 end
flickerstreak@30 649 else
flickerstreak@30 650 t = { ... }
flickerstreak@30 651 end
flickerstreak@30 652
flickerstreak@30 653 if debug then
flickerstreak@30 654 debug[t] = debugstack(2)
flickerstreak@30 655 debug.num = debug.num + 1
flickerstreak@30 656 end
flickerstreak@30 657
flickerstreak@30 658 return t, n
flickerstreak@30 659 end
flickerstreak@30 660 recycleData_func[namespace] = newList
flickerstreak@30 661 end
flickerstreak@30 662 tmp[i] = newList
flickerstreak@30 663 elseif func == "newDict" then
flickerstreak@30 664 local newDict = recycleData_func[namespace]
flickerstreak@30 665 if not newDict then
flickerstreak@30 666 function newDict(...)
flickerstreak@30 667 local t = next(pool)
flickerstreak@30 668 if t then
flickerstreak@30 669 pool[t] = nil
flickerstreak@30 670 else
flickerstreak@30 671 t = {}
flickerstreak@30 672 end
flickerstreak@30 673
flickerstreak@30 674 for i = 1, select('#', ...), 2 do
flickerstreak@30 675 t[select(i, ...)] = select(i+1, ...)
flickerstreak@30 676 end
flickerstreak@30 677
flickerstreak@30 678 if debug then
flickerstreak@30 679 debug[t] = debugstack(2)
flickerstreak@30 680 debug.num = debug.num + 1
flickerstreak@30 681 end
flickerstreak@30 682
flickerstreak@30 683 return t
flickerstreak@30 684 end
flickerstreak@30 685 recycleData_func[namespace] = newDict
flickerstreak@30 686 end
flickerstreak@30 687 tmp[i] = newDict
flickerstreak@30 688 elseif func == "newSet" then
flickerstreak@30 689 local newSet = recycleData_func[namespace]
flickerstreak@30 690 if not newSet then
flickerstreak@30 691 function newSet(...)
flickerstreak@30 692 local t = next(pool)
flickerstreak@30 693 if t then
flickerstreak@30 694 pool[t] = nil
flickerstreak@30 695 else
flickerstreak@30 696 t = {}
flickerstreak@30 697 end
flickerstreak@30 698
flickerstreak@30 699 for i = 1, select('#', ...) do
flickerstreak@30 700 t[select(i, ...)] = true
flickerstreak@30 701 end
flickerstreak@30 702
flickerstreak@30 703 if debug then
flickerstreak@30 704 debug[t] = debugstack(2)
flickerstreak@30 705 debug.num = debug.num + 1
flickerstreak@30 706 end
flickerstreak@30 707
flickerstreak@30 708 return t
flickerstreak@30 709 end
flickerstreak@30 710 recycleData_func[namespace] = newSet
flickerstreak@30 711 end
flickerstreak@30 712 tmp[i] = newSet
flickerstreak@30 713 elseif func == "del" then
flickerstreak@30 714 local del = recycleData_func[namespace]
flickerstreak@30 715 if not del then
flickerstreak@30 716 function del(t)
flickerstreak@30 717 if not t then
flickerstreak@30 718 error(("Bad argument #1 to `del'. Expected %q, got %q."):format("table", type(t)), 2)
flickerstreak@30 719 end
flickerstreak@30 720 if pool[t] then
flickerstreak@30 721 local _, ret = pcall(error, "Error, double-free syndrome.", 3)
flickerstreak@30 722 geterrorhandler()(ret)
flickerstreak@30 723 end
flickerstreak@30 724 setmetatable(t, nil)
flickerstreak@30 725 for k in pairs(t) do
flickerstreak@30 726 t[k] = nil
flickerstreak@30 727 end
flickerstreak@30 728 t[true] = true
flickerstreak@30 729 t[true] = nil
flickerstreak@30 730 pool[t] = true
flickerstreak@30 731
flickerstreak@30 732 if debug then
flickerstreak@30 733 debug[t] = nil
flickerstreak@30 734 debug.num = debug.num - 1
flickerstreak@30 735 end
flickerstreak@30 736 return nil
flickerstreak@30 737 end
flickerstreak@30 738 recycleData_func[namespace] = del
flickerstreak@30 739 end
flickerstreak@30 740 tmp[i] = del
flickerstreak@30 741 elseif func == "unpackListAndDel" then
flickerstreak@30 742 local unpackListAndDel = recycleData_func[namespace]
flickerstreak@30 743 if not unpackListAndDel then
flickerstreak@30 744 local function f(t, start, finish)
flickerstreak@30 745 if start > finish then
flickerstreak@30 746 for k in pairs(t) do
flickerstreak@30 747 t[k] = nil
flickerstreak@30 748 end
flickerstreak@30 749 t[true] = true
flickerstreak@30 750 t[true] = nil
flickerstreak@30 751 pool[t] = true
flickerstreak@30 752 return
flickerstreak@30 753 end
flickerstreak@30 754 return t[start], f(t, start+1, finish)
flickerstreak@30 755 end
flickerstreak@30 756 function unpackListAndDel(t, start, finish)
flickerstreak@30 757 if not t then
flickerstreak@30 758 error(("Bad argument #1 to `unpackListAndDel'. Expected %q, got %q."):format("table", type(t)), 2)
flickerstreak@30 759 end
flickerstreak@30 760 if not start then
flickerstreak@30 761 start = 1
flickerstreak@30 762 end
flickerstreak@30 763 if not finish then
flickerstreak@30 764 finish = #t
flickerstreak@30 765 end
flickerstreak@30 766 setmetatable(t, nil)
flickerstreak@30 767 if debug then
flickerstreak@30 768 debug[t] = nil
flickerstreak@30 769 debug.num = debug.num - 1
flickerstreak@30 770 end
flickerstreak@30 771 return f(t, start, finish)
flickerstreak@30 772 end
flickerstreak@30 773 end
flickerstreak@30 774 tmp[i] = unpackListAndDel
flickerstreak@30 775 elseif func == "unpackSetAndDel" then
flickerstreak@30 776 local unpackSetAndDel = recycleData_func[namespace]
flickerstreak@30 777 if not unpackSetAndDel then
flickerstreak@30 778 local function f(t, current)
flickerstreak@30 779 current = next(t, current)
flickerstreak@30 780 if current == nil then
flickerstreak@30 781 for k in pairs(t) do
flickerstreak@30 782 t[k] = nil
flickerstreak@30 783 end
flickerstreak@30 784 t[true] = true
flickerstreak@30 785 t[true] = nil
flickerstreak@30 786 pool[t] = true
flickerstreak@30 787 return
flickerstreak@30 788 end
flickerstreak@30 789 return current, f(t, current)
flickerstreak@30 790 end
flickerstreak@30 791 function unpackSetAndDel(t)
flickerstreak@30 792 if not t then
flickerstreak@30 793 error(("Bad argument #1 to `unpackListAndDel'. Expected %q, got %q."):format("table", type(t)), 2)
flickerstreak@30 794 end
flickerstreak@30 795 setmetatable(t, nil)
flickerstreak@30 796 if debug then
flickerstreak@30 797 debug[t] = nil
flickerstreak@30 798 debug.num = debug.num - 1
flickerstreak@30 799 end
flickerstreak@30 800 return f(t, nil)
flickerstreak@30 801 end
flickerstreak@30 802 end
flickerstreak@30 803 tmp[i] = unpackSetAndDel
flickerstreak@30 804 elseif func == "unpackDictAndDel" then
flickerstreak@30 805 local unpackDictAndDel = recycleData_func[namespace]
flickerstreak@30 806 if not unpackDictAndDel then
flickerstreak@30 807 local function f(t, current)
flickerstreak@30 808 local value
flickerstreak@30 809 current, value = next(t, current)
flickerstreak@30 810 if current == nil then
flickerstreak@30 811 for k in pairs(t) do
flickerstreak@30 812 t[k] = nil
flickerstreak@30 813 end
flickerstreak@30 814 t[true] = true
flickerstreak@30 815 t[true] = nil
flickerstreak@30 816 pool[t] = true
flickerstreak@30 817 return
flickerstreak@30 818 end
flickerstreak@30 819 return current, value, f(t, current)
flickerstreak@30 820 end
flickerstreak@30 821 function unpackDictAndDel(t)
flickerstreak@30 822 if not t then
flickerstreak@30 823 error(("Bad argument #1 to `unpackListAndDel'. Expected %q, got %q."):format("table", type(t)), 2)
flickerstreak@30 824 end
flickerstreak@30 825 setmetatable(t, nil)
flickerstreak@30 826 if debug then
flickerstreak@30 827 debug[t] = nil
flickerstreak@30 828 debug.num = debug.num - 1
flickerstreak@30 829 end
flickerstreak@30 830 return f(t, nil)
flickerstreak@30 831 end
flickerstreak@30 832 end
flickerstreak@30 833 tmp[i] = unpackDictAndDel
flickerstreak@30 834 else
flickerstreak@30 835 error(("Bad argument #%d to `GetRecyclingFunctions': %q, %q, %q, %q, %q, %q, or %q expected, got %s"):format(i+2, "newList", "newDict", "newSet", "del", "unpackListAndDel", "unpackSetAndDel", "unpackDictAndDel", type(func) == "string" and ("%q"):format(func) or tostring(func)), 2)
flickerstreak@30 836 end
flickerstreak@30 837 end
flickerstreak@30 838 return myUnpack(tmp)
flickerstreak@30 839 end
flickerstreak@30 840
flickerstreak@30 841 --[[---------------------------------------------------------------------------
flickerstreak@30 842 Notes:
flickerstreak@30 843 * Prints information about the specified recycling namespace, including what tables are still in play and where they come from and how many there are.
flickerstreak@30 844 * This goes in tandem with ''':GetRecyclingFunctions'''
flickerstreak@30 845 Arguments:
flickerstreak@30 846 string - the namespace. ''Note: this doesn't necessarily have to be a string.''
flickerstreak@30 847 Example:
flickerstreak@30 848 local newList = Rock:GetRecyclingFunctions("MyNamespace", "newList", "Debug")
flickerstreak@30 849 local t = newList()
flickerstreak@30 850 Rock:DebugRecycle("MyNamespace")
flickerstreak@30 851 t = del(t)
flickerstreak@30 852 -----------------------------------------------------------------------------]]
flickerstreak@30 853 function Rock:DebugRecycle(namespace)
flickerstreak@30 854 local debug = recycleData.debugPools and recycleData.debugPools[namespace]
flickerstreak@30 855 if not debug then
flickerstreak@30 856 return
flickerstreak@30 857 end
flickerstreak@30 858 for k, v in pairs(debug) do
flickerstreak@30 859 if k ~= "num" then
flickerstreak@30 860 _G.DEFAULT_CHAT_FRAME:AddMessage(v)
flickerstreak@30 861 _G.DEFAULT_CHAT_FRAME:AddMessage("------")
flickerstreak@30 862 end
flickerstreak@30 863 end
flickerstreak@30 864 _G.DEFAULT_CHAT_FRAME:AddMessage(("%s: %d tables in action."):format(tostring(namespace), debug.num))
flickerstreak@30 865 end
flickerstreak@30 866
flickerstreak@30 867 local newList, del, unpackListAndDel, unpackDictAndDel = Rock:GetRecyclingFunctions(MAJOR_VERSION, "newList", "del", "unpackListAndDel", "unpackDictAndDel")
flickerstreak@30 868
flickerstreak@30 869 --[[---------------------------------------------------------------------------
flickerstreak@30 870 Notes:
flickerstreak@30 871 * Adds a unit test for the specified namespace
flickerstreak@30 872 * The function provided is called, and it should be where tests are performed, if a problem occurs, an error should fire. If no problems occur, it should return silently.
flickerstreak@30 873 * You can have as many tests per namespace as you want.
flickerstreak@30 874 Arguments:
flickerstreak@30 875 string - the namespace.
flickerstreak@30 876 function - the function to call.
flickerstreak@30 877 Example:
flickerstreak@30 878 Rock:AddUnitTest("LibMonkey-1.0", function()
flickerstreak@30 879 local LibMonkey = Rock("LibMonkey-1.0")
flickerstreak@30 880 assert(LibMonkey:Fling() == "Poo")
flickerstreak@30 881 end)
flickerstreak@30 882 -----------------------------------------------------------------------------]]
flickerstreak@30 883 function Rock:AddUnitTest(namespace, func)
flickerstreak@30 884 if not isStandalone then
flickerstreak@30 885 return
flickerstreak@30 886 end
flickerstreak@30 887 if type(namespace) ~= "string" then
flickerstreak@30 888 error(("Bad argument #2 to `AddUnitTest'. Expected %q, got %q."):format("string", type(namespace)), 2)
flickerstreak@30 889 end
flickerstreak@30 890 if namespace:find("^Lib[A-Z]") then
flickerstreak@30 891 local addon = figureCurrentAddon(2)
flickerstreak@30 892 if addon ~= namespace then
flickerstreak@30 893 return
flickerstreak@30 894 end
flickerstreak@30 895 end
flickerstreak@30 896 if type(func) ~= "function" then
flickerstreak@30 897 error(("Bad argument #3 to `AddUnitTest'. Expected %q, got %q."):format("function", type(func)), 2)
flickerstreak@30 898 end
flickerstreak@30 899 local addon = figureCurrentAddon(2)
flickerstreak@30 900 if libraries[namespace] and addon ~= namespace then
flickerstreak@30 901 -- only work on standalone libraries.
flickerstreak@30 902 return
flickerstreak@30 903 end
flickerstreak@30 904 local unitTests_namespace = unitTests[namespace]
flickerstreak@30 905 if not unitTests_namespace then
flickerstreak@30 906 unitTests_namespace = newList()
flickerstreak@30 907 unitTests[namespace] = unitTests_namespace
flickerstreak@30 908 end
flickerstreak@30 909 if not unitTests_namespace.addon then
flickerstreak@30 910 unitTests_namespace.addon = addon
flickerstreak@30 911 end
flickerstreak@30 912 if unitTestDB and not unitTestDB[namespace] then
flickerstreak@30 913 return
flickerstreak@30 914 end
flickerstreak@30 915 unitTests_namespace[#unitTests_namespace+1] = func
flickerstreak@30 916 end
flickerstreak@30 917
flickerstreak@30 918 local LibRockEvent
flickerstreak@30 919 local LibRockModuleCore
flickerstreak@30 920 local OpenDonationFrame, OpenIssueFrame
flickerstreak@30 921 function Rock:OnLibraryLoad(major, library)
flickerstreak@30 922 if major == "LibRockEvent-1.0" then
flickerstreak@30 923 LibRockEvent = library
flickerstreak@30 924 LibRockEvent:Embed(Rock)
flickerstreak@30 925 elseif major == "LibRockModuleCore-1.0" then
flickerstreak@30 926 LibRockModuleCore = library
flickerstreak@30 927 elseif major == "LibRockConfig-1.0" then
flickerstreak@30 928 if isStandalone then
flickerstreak@30 929 library.rockOptions.args.advanced = {
flickerstreak@30 930 type = 'group',
flickerstreak@30 931 groupType = 'inline',
flickerstreak@30 932 name = L["Advanced options"],
flickerstreak@30 933 desc = L["Advanced options for developers and power users."],
flickerstreak@30 934 order = -1,
flickerstreak@30 935 args = {
flickerstreak@30 936 unitTests = {
flickerstreak@30 937 type = 'multichoice',
flickerstreak@30 938 name = L["Unit tests"],
flickerstreak@30 939 desc = L["Enable unit tests to be run. This is for developers only.\n\nYou must ReloadUI for changes to take effect."],
flickerstreak@30 940 get = function(key)
flickerstreak@30 941 return unitTestDB[key]
flickerstreak@30 942 end,
flickerstreak@30 943 set = function(key, value)
flickerstreak@30 944 unitTestDB[key] = value or nil
flickerstreak@30 945 end,
flickerstreak@30 946 choices = function()
flickerstreak@30 947 local t = newList()
flickerstreak@30 948 for k in pairs(unitTests) do
flickerstreak@30 949 t[k] = k
flickerstreak@30 950 end
flickerstreak@30 951 return "@dict", unpackDictAndDel(t)
flickerstreak@30 952 end
flickerstreak@30 953 },
flickerstreak@30 954 contracts = {
flickerstreak@30 955 type = 'boolean',
flickerstreak@30 956 name = L["Contracts"],
flickerstreak@30 957 desc = L["Enable contracts to be run. This is for developers and anyone wanting to file a bug. Do not file a bug unless contracts are enabled. This will slightly slow down your addons if enabled."],
flickerstreak@30 958 get = function()
flickerstreak@30 959 return enableContracts
flickerstreak@30 960 end,
flickerstreak@30 961 set = function(value)
flickerstreak@30 962 _G.LibRock_1_0DB.contracts = value or nil
flickerstreak@30 963 enableContracts = value
flickerstreak@30 964 end,
flickerstreak@30 965 }
flickerstreak@30 966 }
flickerstreak@30 967 }
flickerstreak@30 968 end
flickerstreak@30 969 library.rockOptions.args.reloadui = {
flickerstreak@30 970 type = 'execute',
flickerstreak@30 971 name = L["Reload UI"],
flickerstreak@30 972 desc = L["Reload the User Interface for some changes to take effect."],
flickerstreak@30 973 buttonText = L["Reload"],
flickerstreak@30 974 func = function()
flickerstreak@30 975 _G.ReloadUI()
flickerstreak@30 976 end,
flickerstreak@30 977 order = -2,
flickerstreak@30 978 }
flickerstreak@30 979 Rock.donate = "Paypal:ckknight AT gmail DOT com"
flickerstreak@30 980 library.rockOptions.args.donate = {
flickerstreak@30 981 type = 'execute',
flickerstreak@30 982 name = L["Give donation"],
flickerstreak@30 983 buttonText = L["Donate"],
flickerstreak@30 984 desc = L["Give a much-needed donation to the author of this addon."],
flickerstreak@30 985 func = OpenDonationFrame,
flickerstreak@30 986 passValue = Rock,
flickerstreak@30 987 order = -3,
flickerstreak@30 988 }
flickerstreak@30 989 Rock.issueTracker = "Wowace:10027"
flickerstreak@30 990 library.rockOptions.args.issue = {
flickerstreak@30 991 type = 'execute',
flickerstreak@30 992 name = L["File issue"],
flickerstreak@30 993 buttonText = L["Report"],
flickerstreak@30 994 desc = L["File a bug or request a new feature or an improvement to this addon."],
flickerstreak@30 995 func = OpenIssueFrame,
flickerstreak@30 996 passValue = Rock,
flickerstreak@30 997 order = -4,
flickerstreak@30 998 }
flickerstreak@30 999 end
flickerstreak@30 1000 end
flickerstreak@30 1001
flickerstreak@30 1002 addon_mt.__index = {}
flickerstreak@30 1003 local addon_mt___index = addon_mt.__index
flickerstreak@30 1004 --[[---------------------------------------------------------------------------
flickerstreak@30 1005 #FORCE_DOC
flickerstreak@30 1006 Notes:
flickerstreak@30 1007 * This is exported to all addons.
flickerstreak@30 1008 * This information is retrieved from LibRockModuleCore-1.0 if it is a module, otherwise from LibRockDB-1.0 if it uses that as a mixin, otherwise it keeps a variable locally.
flickerstreak@30 1009 Returns:
flickerstreak@30 1010 boolean - whether the addon is in an active state or not.
flickerstreak@30 1011 Example:
flickerstreak@30 1012 local active = MyAddon:IsActive()
flickerstreak@30 1013 -----------------------------------------------------------------------------]]
flickerstreak@30 1014 function addon_mt___index:IsActive()
flickerstreak@30 1015 if LibRockModuleCore then
flickerstreak@30 1016 local core = LibRockModuleCore:HasModule(self)
flickerstreak@30 1017 if core then
flickerstreak@30 1018 return core:IsModuleActive(self)
flickerstreak@30 1019 end
flickerstreak@30 1020 end
flickerstreak@30 1021
flickerstreak@30 1022 local self_db = self.db
flickerstreak@30 1023 if self_db then
flickerstreak@30 1024 local disabled
flickerstreak@30 1025 local self_db_raw = self_db.raw
flickerstreak@30 1026 if self_db_raw then
flickerstreak@30 1027 local self_db_raw_disabled = self_db_raw.disabled
flickerstreak@30 1028 if self_db_raw_disabled then
flickerstreak@30 1029 local profile = type(self.GetProfile) == "function" and select(2, self:GetProfile()) or false
flickerstreak@30 1030 disabled = self_db_raw_disabled[profile]
flickerstreak@30 1031 end
flickerstreak@30 1032 else
flickerstreak@30 1033 return false
flickerstreak@30 1034 end
flickerstreak@30 1035 return not disabled
flickerstreak@30 1036 end
flickerstreak@30 1037
flickerstreak@30 1038 return not inactiveAddons[self]
flickerstreak@30 1039 end
flickerstreak@30 1040 --[[---------------------------------------------------------------------------
flickerstreak@30 1041 #FORCE_DOC
flickerstreak@30 1042 Notes:
flickerstreak@30 1043 * This is exported to all addons.
flickerstreak@30 1044 * If it enables the addon, it will call :OnEnable(first) on the addon and :OnEmbedEnable(addon, first) on all its mixins.
flickerstreak@30 1045 * If it disables the addon, it will call :OnDisable(first) on the addon and :OnEmbedDisable(addon, first) on all its mixins.
flickerstreak@30 1046 * This information is stored by LibRockModuleCore-1.0 if it is a module, otherwise from LibRockDB-1.0 if it uses that as a mixin, otherwise it keeps a variable locally.
flickerstreak@30 1047 Arguments:
flickerstreak@30 1048 [optional] boolean - whether the addon should be in an active state or not. Default: not :IsActive()
flickerstreak@30 1049 Returns:
flickerstreak@30 1050 boolean - whether the addon is in an active state or not.
flickerstreak@30 1051 Example:
flickerstreak@30 1052 MyAddon:ToggleActive() -- switch
flickerstreak@30 1053 MyAddon:ToggleActive(true) -- force on
flickerstreak@30 1054 MyAddon:ToggleActive(false) -- force off
flickerstreak@30 1055 -----------------------------------------------------------------------------]]
flickerstreak@30 1056 function addon_mt___index:ToggleActive(state)
flickerstreak@30 1057 if state and state ~= true then
flickerstreak@30 1058 error(("Bad argument #2 to `ToggleActive'. Expected %q or %q, got %q."):format("boolean", "nil", type(state)), 2)
flickerstreak@30 1059 end
flickerstreak@30 1060 if LibRockModuleCore then
flickerstreak@30 1061 local core = LibRockModuleCore:HasModule(self)
flickerstreak@30 1062 if core then
flickerstreak@30 1063 return core:ToggleModuleActive(self, state)
flickerstreak@30 1064 end
flickerstreak@30 1065 end
flickerstreak@30 1066
flickerstreak@30 1067 local self_db = self.db
flickerstreak@30 1068 if self_db then
flickerstreak@30 1069 local self_db_raw = self_db.raw
flickerstreak@30 1070 if not self_db_raw then
flickerstreak@30 1071 error("Error saving to database with `ToggleActive'. db.raw not available.", 2)
flickerstreak@30 1072 end
flickerstreak@30 1073 local self_db_raw_disabled = self_db_raw.disabled
flickerstreak@30 1074 if not self_db_raw_disabled then
flickerstreak@30 1075 self_db_raw_disabled = newList()
flickerstreak@30 1076 self_db_raw.disabled = self_db_raw_disabled
flickerstreak@30 1077 end
flickerstreak@30 1078 local profile = type(self.GetProfile) == "function" and select(2, self:GetProfile()) or false
flickerstreak@30 1079 if state == nil then
flickerstreak@30 1080 state = not not self_db_raw_disabled[profile]
flickerstreak@30 1081 elseif (not self_db_raw_disabled[profile]) == state then
flickerstreak@30 1082 return
flickerstreak@30 1083 end
flickerstreak@30 1084 self_db_raw_disabled[profile] = not state or nil
flickerstreak@30 1085 if next(self_db_raw_disabled) == nil then
flickerstreak@30 1086 self_db_raw.disabled = del(self_db_raw_disabled)
flickerstreak@30 1087 end
flickerstreak@30 1088 else
flickerstreak@30 1089 if state == nil then
flickerstreak@30 1090 state = not not inactiveAddons[self]
flickerstreak@30 1091 elseif (not inactiveAddons[self]) == state then
flickerstreak@30 1092 return
flickerstreak@30 1093 end
flickerstreak@30 1094 inactiveAddons[self] = not state or nil
flickerstreak@30 1095 end
flickerstreak@30 1096
flickerstreak@30 1097 Rock:RecheckEnabledStates()
flickerstreak@30 1098
flickerstreak@30 1099 return state
flickerstreak@30 1100 end
flickerstreak@30 1101
flickerstreak@30 1102 local function noop() end
flickerstreak@30 1103
flickerstreak@30 1104 do
flickerstreak@30 1105 local preconditions = setmetatable({}, weakKey)
flickerstreak@30 1106 local postconditions = setmetatable({}, weakKey)
flickerstreak@30 1107 local postconditionsOld = setmetatable({}, weakKey)
flickerstreak@30 1108
flickerstreak@30 1109 local currentMethod = nil
flickerstreak@30 1110
flickerstreak@30 1111 local function hook(object, method)
flickerstreak@30 1112 local object_method = object[method]
flickerstreak@30 1113 object[method] = function(...)
flickerstreak@30 1114 local pre = preconditions[object_method]
flickerstreak@30 1115 local post = postconditions[object_method]
flickerstreak@30 1116 if pre then
flickerstreak@30 1117 local old_currentMethod = currentMethod
flickerstreak@30 1118 currentMethod = method
flickerstreak@30 1119 pre(...)
flickerstreak@30 1120 currentMethod = old_currentMethod
flickerstreak@30 1121 end
flickerstreak@30 1122 if not post then
flickerstreak@30 1123 return object_method(...)
flickerstreak@30 1124 end
flickerstreak@30 1125 local oldFunc = postconditionsOld[object_method]
flickerstreak@30 1126 local old
flickerstreak@30 1127 if oldFunc then
flickerstreak@30 1128 old = newList()
flickerstreak@30 1129 oldFunc(old, ...)
flickerstreak@30 1130 end
flickerstreak@30 1131
flickerstreak@30 1132 local old_currentMethod = currentMethod
flickerstreak@30 1133 currentMethod = nil
flickerstreak@30 1134 local ret, n = newList(object_method(...))
flickerstreak@30 1135
flickerstreak@30 1136 currentMethod = method
flickerstreak@30 1137 if old then
flickerstreak@30 1138 post(old, ret, ...)
flickerstreak@30 1139 old = del(old)
flickerstreak@30 1140 else
flickerstreak@30 1141 post(ret, ...)
flickerstreak@30 1142 end
flickerstreak@30 1143 currentMethod = old_currentMethod
flickerstreak@30 1144 return unpackListAndDel(ret, 1, n)
flickerstreak@30 1145 end
flickerstreak@30 1146 end
flickerstreak@30 1147
flickerstreak@30 1148 local function precondition(object, method, func)
flickerstreak@30 1149 if type(object) ~= "table" then
flickerstreak@30 1150 error(("Bad argument #1 to `precondition'. Expected %q, got %q."):format("table", type(object)), 2)
flickerstreak@30 1151 end
flickerstreak@30 1152 if type(object[method]) ~= "function" then
flickerstreak@30 1153 error(("Method %q not found on object %s. Expected %q, got %q."):format(tostring(method), tostring(object), "function", type(object[method])), 2)
flickerstreak@30 1154 end
flickerstreak@30 1155 if type(func) ~= "function" then
flickerstreak@30 1156 error(("Bad argument #3 to `precondition'. Expected %q, got %q."):format("function", type(func)), 2)
flickerstreak@30 1157 end
flickerstreak@30 1158
flickerstreak@30 1159 local object_method = object[method]
flickerstreak@30 1160 if preconditions[object_method] then
flickerstreak@30 1161 error("Cannot call `preconditon' on the same method twice.", 2)
flickerstreak@30 1162 end
flickerstreak@30 1163 preconditions[object_method] = func
flickerstreak@30 1164
flickerstreak@30 1165 if not postconditions[object_method] then
flickerstreak@30 1166 hook(object, method)
flickerstreak@30 1167 end
flickerstreak@30 1168 end
flickerstreak@30 1169
flickerstreak@30 1170 local function postcondition(object, method, func, fillOld)
flickerstreak@30 1171 if type(object) ~= "table" then
flickerstreak@30 1172 error(("Bad argument #1 to `postcondition'. Expected %q, got %q."):format("table", type(object)), 2)
flickerstreak@30 1173 end
flickerstreak@30 1174 if type(object[method]) ~= "function" then
flickerstreak@30 1175 error(("Method %q not found on object %s. Expected %q, got %q."):format(tostring(method), tostring(object), "function", type(object[method])), 2)
flickerstreak@30 1176 end
flickerstreak@30 1177 if type(func) ~= "function" then
flickerstreak@30 1178 error(("Bad argument #3 to `postcondition'. Expected %q, got %q."):format("function", type(func)), 2)
flickerstreak@30 1179 end
flickerstreak@30 1180 if fillOld and type(fillOld) ~= "function" then
flickerstreak@30 1181 error(("Bad argument #4 to `postcondition'. Expected %q or %q, got %q."):format("function", "nil", type(func)), 2)
flickerstreak@30 1182 end
flickerstreak@30 1183
flickerstreak@30 1184 local object_method = object[method]
flickerstreak@30 1185 if postconditions[object_method] then
flickerstreak@30 1186 error("Cannot call `postcondition' on the same method twice.", 2)
flickerstreak@30 1187 end
flickerstreak@30 1188 postconditions[object_method] = func
flickerstreak@30 1189 postconditionsOld[object_method] = fillOld
flickerstreak@30 1190
flickerstreak@30 1191 if not preconditions[object_method] then
flickerstreak@30 1192 hook(object, method)
flickerstreak@30 1193 end
flickerstreak@30 1194 end
flickerstreak@30 1195
flickerstreak@30 1196 local function argCheck(value, position, ...)
flickerstreak@30 1197 if not currentMethod then
flickerstreak@30 1198 error("Cannot call `argCheck' outside of a pre/post-condition.", 2)
flickerstreak@30 1199 end
flickerstreak@30 1200 if type(position) ~= "number" then
flickerstreak@30 1201 error(("Bad argument #2 to `argCheck'. Expected %q, got %q"):format("number", type(position)), 2)
flickerstreak@30 1202 end
flickerstreak@30 1203 local type_value = type(value)
flickerstreak@30 1204 for i = 1, select('#', ...) do
flickerstreak@30 1205 local v = select(i, ...)
flickerstreak@30 1206 if type(v) ~= "string" then
flickerstreak@30 1207 error(("Bad argument #%d to `argCheck'. Expected %q, got %q"):format(i+1, "string", type(v)), 2)
flickerstreak@30 1208 end
flickerstreak@30 1209 if v == type_value then
flickerstreak@30 1210 return
flickerstreak@30 1211 end
flickerstreak@30 1212 end
flickerstreak@30 1213 local t = newList(...)
flickerstreak@30 1214 t[#t] = nil
flickerstreak@30 1215 for i,v in ipairs(t) do
flickerstreak@30 1216 t[i] = ("%q"):format(v)
flickerstreak@30 1217 end
flickerstreak@30 1218 local s
flickerstreak@30 1219 if #t == 0 then
flickerstreak@30 1220 s = ("%q"):format((...))
flickerstreak@30 1221 elseif #t == 1 then
flickerstreak@30 1222 s = ("%q or %q"):format(...)
flickerstreak@30 1223 else
flickerstreak@30 1224 s = table_concat(t, ", ") .. ", or " .. ("%q"):format(select(#t+1, ...))
flickerstreak@30 1225 end
flickerstreak@30 1226 t = del(t)
flickerstreak@30 1227
flickerstreak@30 1228 error(("Bad argument #%d to `%s'. Expected %s, got %q."):format(position, tostring(currentMethod), s, type_value), 4)
flickerstreak@30 1229 end
flickerstreak@30 1230
flickerstreak@30 1231 --[[---------------------------------------------------------------------------
flickerstreak@30 1232 Notes:
flickerstreak@30 1233 * Returns functions for the specified namespace based on what is provided.
flickerstreak@30 1234 * function types:
flickerstreak@30 1235 ; "precondition" : to set the pre-condition for a method.
flickerstreak@30 1236 ; "postcondition" : to set the post-condition for a method.
flickerstreak@30 1237 ; "argCheck" : to check the type of an argument, to be executed within a pre-condition.
flickerstreak@30 1238 * preconditon is in the form of <tt>precondition(object, "methodName", func(self, ...))</tt>
flickerstreak@30 1239 * postcondition is in the form of either <tt>postcondition(object, "methodName", func(returnValues, self, ...))</tt> or <tt>postcondition(object, "methodName", func(oldValues, returnValues, self, ...), populateOld(oldValues, self, ...))</tt>
flickerstreak@30 1240 ** returnValues is the list of return values, empty if no return values were sent.
flickerstreak@30 1241 ** if the populateOld function is provided, then the empty oldValues table is provided and expected to be filled, and then given to the func.
flickerstreak@30 1242 * argCheck is in the form of <tt>argCheck(value, n, "type1" [, "type2", ...])</tt>
flickerstreak@30 1243 ** value is the value provided to the function you're checking.
flickerstreak@30 1244 ** n is the argument position. ''Note: 1 is the position of `self'. 2 would be the first "real" position.''
flickerstreak@30 1245 ** the tuple of types can be any string, but specifically "nil", "boolean", "string", "number", "function", "userdata", "table", etc.
flickerstreak@30 1246 Arguments:
flickerstreak@30 1247 string - the namespace. ''Note: this doesn't necessarily have to be a string.''
flickerstreak@30 1248 Example:
flickerstreak@30 1249 local precondition, postcondition, argCheck = Rock:GetRecyclingFunctions("Stack", "precondition", "postcondition", "argCheck")
flickerstreak@30 1250
flickerstreak@30 1251 local stack = {}
flickerstreak@30 1252 stack.IsEmpty = function(self)
flickerstreak@30 1253 return self[1] == nil
flickerstreak@30 1254 end
flickerstreak@30 1255 stack.GetLength = function(self)
flickerstreak@30 1256 return #self
flickerstreak@30 1257 end
flickerstreak@30 1258 stack.Push = function(self, value)
flickerstreak@30 1259 self[#self+1] = value
flickerstreak@30 1260 end
flickerstreak@30 1261 precondition(stack, "Push", function(self, value)
flickerstreak@30 1262 argCheck(value, 2, "string") -- only accept strings, no other values
flickerstreak@30 1263 end)
flickerstreak@30 1264 postcondition(stack, "Push", function(old, ret, self, value)
flickerstreak@30 1265 assert(self:GetLength() == old.length+1)
flickerstreak@30 1266 assert(not self:IsEmpty())
flickerstreak@30 1267 end, function(old, self)
flickerstreak@30 1268 old.length = self:GetLength()
flickerstreak@30 1269 end)
flickerstreak@30 1270 stack.Pop = function(self)
flickerstreak@30 1271 local value = self[#self]
flickerstreak@30 1272 self[#self] = nil
flickerstreak@30 1273 return value
flickerstreak@30 1274 end
flickerstreak@30 1275 precondition(stack, "Pop", function(self)
flickerstreak@30 1276 assert(self:GetLength() >= 1)
flickerstreak@30 1277 end)
flickerstreak@30 1278 postcondition(stack, "Pop", function(old, ret, self)
flickerstreak@30 1279 assert(self:GetLength() == old.length-1)
flickerstreak@30 1280 end, function(old, self)
flickerstreak@30 1281 old.length = self:GetLength()
flickerstreak@30 1282 end)
flickerstreak@30 1283 stack.Peek = function(self)
flickerstreak@30 1284 return self[#self]
flickerstreak@30 1285 end
flickerstreak@30 1286 precondition(stack, "Peek", function(self)
flickerstreak@30 1287 assert(self:GetLength() >= 1)
flickerstreak@30 1288 end)
flickerstreak@30 1289 postcondition(stack, "Peek", function(old, ret, self)
flickerstreak@30 1290 assert(self:GetLength() == old.length)
flickerstreak@30 1291 end, function(old, self)
flickerstreak@30 1292 old.length = self:GetLength()
flickerstreak@30 1293 end)
flickerstreak@30 1294
flickerstreak@30 1295 local t = setmetatable({}, {__index=stack})
flickerstreak@30 1296 t:Push("Alpha")
flickerstreak@30 1297 t:Push("Bravo")
flickerstreak@30 1298 t:Push(5) -- error, only strings
flickerstreak@30 1299 assert(t:Pop() == "Bravo")
flickerstreak@30 1300 assert(t:Pop() == "Alpha")
flickerstreak@30 1301 t:Pop() -- error, out of values
flickerstreak@30 1302 -----------------------------------------------------------------------------]]
flickerstreak@30 1303 function Rock:GetContractFunctions(namespace, ...)
flickerstreak@30 1304 if namespace == "precondition" or namespace == "postcondition" or namespace == "argCheck" then
flickerstreak@30 1305 error(("Bad argument #2 to `GetContractFunctions'. Cannot be %q."):format(namespace), 2)
flickerstreak@30 1306 end
flickerstreak@30 1307 local t = newList()
flickerstreak@30 1308 if enableContracts then
flickerstreak@30 1309 for i = 1, select('#', ...) do
flickerstreak@30 1310 local v = select(i, ...)
flickerstreak@30 1311 if v == "precondition" then
flickerstreak@30 1312 t[i] = precondition
flickerstreak@30 1313 elseif v == "postcondition" then
flickerstreak@30 1314 t[i] = postcondition
flickerstreak@30 1315 elseif v == "argCheck" then
flickerstreak@30 1316 t[i] = argCheck
flickerstreak@30 1317 else
flickerstreak@30 1318 error(("Bad argument #%d to `GetContractFunctions'. Expected %q, %q, or %q, got %q."):format(i+2, "precondition", "postcondition", "argCheck", tostring(v)))
flickerstreak@30 1319 end
flickerstreak@30 1320 end
flickerstreak@30 1321 else
flickerstreak@30 1322 for i = 1, select('#', ...) do
flickerstreak@30 1323 t[i] = noop
flickerstreak@30 1324 end
flickerstreak@30 1325 end
flickerstreak@30 1326 return unpackListAndDel(t)
flickerstreak@30 1327 end
flickerstreak@30 1328 end
flickerstreak@30 1329
flickerstreak@30 1330 --[[---------------------------------------------------------------------------
flickerstreak@30 1331 Notes:
flickerstreak@30 1332 * convert a revision string to a number
flickerstreak@30 1333 Arguments:
flickerstreak@30 1334 string - revision string
flickerstreak@30 1335 Returns:
flickerstreak@30 1336 string or number - the string given or the number retrieved from it.
flickerstreak@30 1337 -----------------------------------------------------------------------------]]
flickerstreak@30 1338 local function coerceRevisionToNumber(version)
flickerstreak@30 1339 if type(version) == "string" then
flickerstreak@30 1340 return tonumber(version:match("(%-?%d+)")) or version
flickerstreak@30 1341 else
flickerstreak@30 1342 return version
flickerstreak@30 1343 end
flickerstreak@30 1344 end
flickerstreak@30 1345
flickerstreak@30 1346 --[[---------------------------------------------------------------------------
flickerstreak@30 1347 Notes:
flickerstreak@30 1348 * try to enable the standalone library specified
flickerstreak@30 1349 Arguments:
flickerstreak@30 1350 string - name of the library.
flickerstreak@30 1351 Returns:
flickerstreak@30 1352 boolean - whether the library is properly enabled and loadable.
flickerstreak@30 1353 -----------------------------------------------------------------------------]]
flickerstreak@30 1354 local function TryToEnable(addon)
flickerstreak@30 1355 local islod = IsAddOnLoadOnDemand(addon)
flickerstreak@30 1356 if islod then
flickerstreak@30 1357 local _, _, _, enabled = GetAddOnInfo(addon)
flickerstreak@30 1358 EnableAddOn(addon)
flickerstreak@30 1359 local _, _, _, _, loadable = GetAddOnInfo(addon)
flickerstreak@30 1360 if not loadable and not enabled then
flickerstreak@30 1361 DisableAddOn(addon)
flickerstreak@30 1362 end
flickerstreak@30 1363
flickerstreak@30 1364 return loadable
flickerstreak@30 1365 end
flickerstreak@30 1366 end
flickerstreak@30 1367
flickerstreak@30 1368 --[[---------------------------------------------------------------------------
flickerstreak@30 1369 Notes:
flickerstreak@30 1370 * try to load the standalone library specified
flickerstreak@30 1371 Arguments:
flickerstreak@30 1372 string - name of the library.
flickerstreak@30 1373 Returns:
flickerstreak@30 1374 boolean - whether the library is loaded.
flickerstreak@30 1375 -----------------------------------------------------------------------------]]
flickerstreak@30 1376 local function TryToLoadStandalone(major)
flickerstreak@30 1377 major = major:lower()
flickerstreak@30 1378 if scannedLibraries[major] then
flickerstreak@30 1379 return
flickerstreak@30 1380 end
flickerstreak@30 1381 scannedLibraries[major] = true
flickerstreak@30 1382 local name, _, _, enabled, loadable, state = GetAddOnInfo(major)
flickerstreak@30 1383 if state == "MISSING" or not IsAddOnLoadOnDemand(major) then
flickerstreak@30 1384 -- backwards compatibility for X-AceLibrary
flickerstreak@30 1385 local field = "X-AceLibrary-" .. major
flickerstreak@30 1386 local loaded
flickerstreak@30 1387 for i = 1, GetNumAddOns() do
flickerstreak@30 1388 if GetAddOnMetadata(i, field) then
flickerstreak@30 1389 name, _, _, enabled, loadable = GetAddOnInfo(i)
flickerstreak@30 1390
flickerstreak@30 1391 loadable = (enabled and loadable) or TryToEnable(name)
flickerstreak@30 1392 if loadable then
flickerstreak@30 1393 loaded = true
flickerstreak@30 1394 LoadAddOn(name)
flickerstreak@30 1395 end
flickerstreak@30 1396 end
flickerstreak@30 1397 end
flickerstreak@30 1398
flickerstreak@30 1399 return loaded
flickerstreak@30 1400 elseif (enabled and loadable) or TryToEnable(major) then
flickerstreak@30 1401 LoadAddOn(major)
flickerstreak@30 1402 return true
flickerstreak@30 1403 else
flickerstreak@30 1404 return false
flickerstreak@30 1405 end
flickerstreak@30 1406 end
flickerstreak@30 1407
flickerstreak@30 1408 --[[---------------------------------------------------------------------------
flickerstreak@30 1409 Notes:
flickerstreak@30 1410 * Return the LibStub library, casing is unimportant.
flickerstreak@30 1411 Arguments:
flickerstreak@30 1412 string - name of the library.
flickerstreak@30 1413 Returns:
flickerstreak@30 1414 table or nil - library
flickerstreak@30 1415 number - minor version
flickerstreak@30 1416 -----------------------------------------------------------------------------]]
flickerstreak@30 1417 local function GetLibStubLibrary(major)
flickerstreak@30 1418 local lib, minor = LibStub:GetLibrary(major, true)
flickerstreak@30 1419 if lib then
flickerstreak@30 1420 return lib, minor
flickerstreak@30 1421 end
flickerstreak@30 1422 major = major:lower()
flickerstreak@30 1423 for m, lib in LibStub:IterateLibraries() do
flickerstreak@30 1424 if m:lower() == major then
flickerstreak@30 1425 return LibStub:GetLibrary(m)
flickerstreak@30 1426 end
flickerstreak@30 1427 end
flickerstreak@30 1428 return nil, nil
flickerstreak@30 1429 end
flickerstreak@30 1430
flickerstreak@30 1431 local finishLibraryRegistration
flickerstreak@30 1432 --[[---------------------------------------------------------------------------
flickerstreak@30 1433 Notes:
flickerstreak@30 1434 * create a new library if the version provided is not out of date.
flickerstreak@30 1435 Arguments:
flickerstreak@30 1436 string - name of the library.
flickerstreak@30 1437 number - version of the library.
flickerstreak@30 1438 Returns:
flickerstreak@30 1439 library, oldLibrary
flickerstreak@30 1440 * table or nil - the library with which to manipulate
flickerstreak@30 1441 * table or nil - the old version of the library to upgrade from
flickerstreak@30 1442 Example:
flickerstreak@30 1443 local LibMonkey, oldLib = Rock:NewLibrary("LibMonkey-1.0", 50)
flickerstreak@30 1444 if not LibMonkey then
flickerstreak@30 1445 -- opt out now, out of date
flickerstreak@30 1446 return
flickerstreak@30 1447 end
flickerstreak@30 1448 -----------------------------------------------------------------------------]]
flickerstreak@30 1449 function Rock:NewLibrary(major, version)
flickerstreak@30 1450 if type(major) ~= "string" then
flickerstreak@30 1451 error(("Bad argument #2 to `NewLibrary'. Expected %q, got %q."):format("string", type(major)), 2)
flickerstreak@30 1452 end
flickerstreak@30 1453 if not major:match("^Lib[A-Z][A-Za-z%d%-]*%-%d+%.%d+$") then
flickerstreak@30 1454 error(("Bad argument #2 to `NewLibrary'. Must match %q, got %q."):format("^Lib[A-Z][A-Za-z%d%-]*%-%d+%.%d+$", major), 2)
flickerstreak@30 1455 end
flickerstreak@30 1456 TryToLoadStandalone(major)
flickerstreak@30 1457 version = coerceRevisionToNumber(version)
flickerstreak@30 1458 if type(version) ~= "number" then
flickerstreak@30 1459 error(("Bad argument #3 to `NewLibrary'. Expected %q, got %q."):format("number", type(version)), 2)
flickerstreak@30 1460 end
flickerstreak@30 1461 local library, oldMinor = LibStub:GetLibrary(major, true)
flickerstreak@30 1462 if oldMinor and oldMinor >= version then
flickerstreak@30 1463 -- in case LibStub is acting funny
flickerstreak@30 1464 return nil, nil
flickerstreak@30 1465 end
flickerstreak@30 1466 local library, oldMinor = LibStub:NewLibrary(major, version)
flickerstreak@30 1467 if not library then
flickerstreak@30 1468 return nil, nil
flickerstreak@30 1469 end
flickerstreak@30 1470 local unitTests_major = unitTests[major]
flickerstreak@30 1471 if unitTests_major then
flickerstreak@30 1472 for k,v in pairs(unitTests_major) do
flickerstreak@30 1473 unitTests_major[k] = nil
flickerstreak@30 1474 end
flickerstreak@30 1475 end
flickerstreak@30 1476 for k, v in pairs(recycleData) do
flickerstreak@30 1477 v[major] = nil
flickerstreak@30 1478 end
flickerstreak@30 1479 local mixinToObject_library = mixinToObject[library]
flickerstreak@30 1480
flickerstreak@30 1481 local oldLib
flickerstreak@30 1482 if oldMinor then
flickerstreak@30 1483 -- previous version exists
flickerstreak@30 1484 local mixins = newList()
flickerstreak@30 1485 for mixin, objectSet in pairs(mixinToObject) do
flickerstreak@30 1486 if objectSet[library] then
flickerstreak@30 1487 mixins[mixin] = true
flickerstreak@30 1488 end
flickerstreak@30 1489 end
flickerstreak@30 1490 for mixin in pairs(mixins) do
flickerstreak@30 1491 mixin:Unembed(library)
flickerstreak@30 1492 end
flickerstreak@30 1493 mixins = del(mixins)
flickerstreak@30 1494 oldLib = newList()
flickerstreak@30 1495 for k, v in pairs(library) do
flickerstreak@30 1496 oldLib[k] = v
flickerstreak@30 1497 library[k] = nil
flickerstreak@30 1498 end
flickerstreak@30 1499 setmetatable(oldLib, getmetatable(library))
flickerstreak@30 1500 setmetatable(library, nil)
flickerstreak@30 1501 end
flickerstreak@30 1502 finishLibraryRegistration(major, version, library, figureCurrentAddon(2))
flickerstreak@30 1503
flickerstreak@30 1504 return library, oldLib
flickerstreak@30 1505 end
flickerstreak@30 1506 function finishLibraryRegistration(major, version, library, folder)
flickerstreak@30 1507 library.name = major
flickerstreak@30 1508
flickerstreak@30 1509 libraries[major] = library
flickerstreak@30 1510 pendingLibraries[library] = folder
flickerstreak@30 1511 local exportedMethods_library = exportedMethods[library]
flickerstreak@30 1512 if exportedMethods_library then
flickerstreak@30 1513 local mixinToObject_library = mixinToObject[library]
flickerstreak@30 1514 if mixinToObject_library then
flickerstreak@30 1515 for object in pairs(mixinToObject_library) do
flickerstreak@30 1516 for _,v in ipairs(exportedMethods_library) do
flickerstreak@30 1517 object[v] = nil
flickerstreak@30 1518 end
flickerstreak@30 1519 end
flickerstreak@30 1520 end
flickerstreak@30 1521 exportedMethods[library] = del(exportedMethods_library)
flickerstreak@30 1522 end
flickerstreak@30 1523 if library ~= Rock then
flickerstreak@30 1524 Rock:Embed(library)
flickerstreak@30 1525 end
flickerstreak@30 1526
flickerstreak@30 1527 frame:Show()
flickerstreak@30 1528 end
flickerstreak@30 1529 if not oldRock then
flickerstreak@30 1530 finishLibraryRegistration(MAJOR_VERSION, MINOR_VERSION, Rock, figureCurrentAddon(1))
flickerstreak@30 1531 end
flickerstreak@30 1532
flickerstreak@30 1533 -- #NODOC
flickerstreak@30 1534 local function __removeLibrary(libName)
flickerstreak@30 1535 libraries[libName] = nil
flickerstreak@30 1536 if LibStub.libs then
flickerstreak@30 1537 LibStub.libs[libName] = nil
flickerstreak@30 1538 end
flickerstreak@30 1539 if LibStub.minors then
flickerstreak@30 1540 LibStub.minors[libName] = nil
flickerstreak@30 1541 end
flickerstreak@30 1542 local lastCount
flickerstreak@30 1543 repeat
flickerstreak@30 1544 lastCount = collectgarbage('count')
flickerstreak@30 1545 collectgarbage('collect')
flickerstreak@30 1546 until lastCount == collectgarbage('count')
flickerstreak@30 1547 end
flickerstreak@30 1548 local function run(_,a)
flickerstreak@30 1549 if a < 1/30 then
flickerstreak@30 1550 collectgarbage('step')
flickerstreak@30 1551 end
flickerstreak@30 1552 end
flickerstreak@30 1553
flickerstreak@30 1554 --[[---------------------------------------------------------------------------
flickerstreak@30 1555 Notes:
flickerstreak@30 1556 * properly finalizes the library, essentially stating that it has loaded properly.
flickerstreak@30 1557 * This will call :OnLibraryLoad("major", library) on every other library
flickerstreak@30 1558 * This will also call :OnLibraryLoad("major", library) on the library provided, using every other library as the arguments.
flickerstreak@30 1559 * An error will occur if this is not done before ADDON_LOADED.
flickerstreak@30 1560 Arguments:
flickerstreak@30 1561 string - name of the library.
flickerstreak@30 1562 Example:
flickerstreak@30 1563 local LibMonkey, oldLib = Rock:NewLibrary("LibMonkey-1.0", 50)
flickerstreak@30 1564 if not LibMonkey then
flickerstreak@30 1565 -- opt out now, out of date
flickerstreak@30 1566 return
flickerstreak@30 1567 end
flickerstreak@30 1568 Rock:FinalizeLibrary("LibMonkey-1.0")
flickerstreak@30 1569 -----------------------------------------------------------------------------]]
flickerstreak@30 1570 function Rock:FinalizeLibrary(major)
flickerstreak@30 1571 if type(major) ~= "string" then
flickerstreak@30 1572 error(("Bad argument #2 to `FinalizeLibrary'. Expected %q, got %q."):format("string", type(major)), 2)
flickerstreak@30 1573 end
flickerstreak@30 1574 local library = libraries[major]
flickerstreak@30 1575 if not library then
flickerstreak@30 1576 error(("Bad argument #2 to `FinalizeLibrary'. %q is not a library."):format("string", major), 2)
flickerstreak@30 1577 end
flickerstreak@30 1578 pendingLibraries[library] = nil
flickerstreak@30 1579 local library_OnLibraryLoad = library.OnLibraryLoad
flickerstreak@30 1580 if library_OnLibraryLoad then
flickerstreak@30 1581 for maj, lib in LibStub:IterateLibraries() do -- for all libraries
flickerstreak@30 1582 if maj ~= major then
flickerstreak@30 1583 local success, ret = pcall(library_OnLibraryLoad, library, maj, lib)
flickerstreak@30 1584 if not success then
flickerstreak@30 1585 geterrorhandler()(ret)
flickerstreak@30 1586 break
flickerstreak@30 1587 end
flickerstreak@30 1588 end
flickerstreak@30 1589 end
flickerstreak@30 1590 end
flickerstreak@30 1591 if finalizedLibraries[library] then
flickerstreak@30 1592 return
flickerstreak@30 1593 end
flickerstreak@30 1594 finalizedLibraries[library] = true
flickerstreak@30 1595 for maj, lib in pairs(libraries) do -- just Rock libraries
flickerstreak@30 1596 if maj ~= major then
flickerstreak@30 1597 local lib_OnLibraryLoad = lib.OnLibraryLoad
flickerstreak@30 1598 if lib_OnLibraryLoad then
flickerstreak@30 1599 local success, ret = pcall(lib_OnLibraryLoad, lib, major, library)
flickerstreak@30 1600 if not success then
flickerstreak@30 1601 geterrorhandler()(ret)
flickerstreak@30 1602 end
flickerstreak@30 1603 end
flickerstreak@30 1604 end
flickerstreak@30 1605 end
flickerstreak@30 1606 if LibRockEvent then
flickerstreak@30 1607 self:DispatchEvent("LibraryLoad", major, library)
flickerstreak@30 1608 end
flickerstreak@30 1609 end
flickerstreak@30 1610
flickerstreak@30 1611 local function manualFinalize(major, library)
flickerstreak@30 1612 if libraries[major] then -- non-Rock libraries only
flickerstreak@30 1613 return
flickerstreak@30 1614 end
flickerstreak@30 1615 if finalizedLibraries[library] then -- don't do it twice
flickerstreak@30 1616 return
flickerstreak@30 1617 end
flickerstreak@30 1618 finalizedLibraries[library] = true
flickerstreak@30 1619 for maj, lib in pairs(libraries) do -- just Rock libraries
flickerstreak@30 1620 if maj ~= major then
flickerstreak@30 1621 local lib_OnLibraryLoad = lib.OnLibraryLoad
flickerstreak@30 1622 if lib_OnLibraryLoad then
flickerstreak@30 1623 local success, ret = pcall(lib_OnLibraryLoad, lib, major, library)
flickerstreak@30 1624 if not success then
flickerstreak@30 1625 geterrorhandler()(ret)
flickerstreak@30 1626 end
flickerstreak@30 1627 end
flickerstreak@30 1628 end
flickerstreak@30 1629 end
flickerstreak@30 1630 if LibRockEvent then
flickerstreak@30 1631 Rock:DispatchEvent("LibraryLoad", major, library)
flickerstreak@30 1632 end
flickerstreak@30 1633 end
flickerstreak@30 1634
flickerstreak@30 1635 --[[---------------------------------------------------------------------------
flickerstreak@30 1636 Arguments:
flickerstreak@30 1637 string - name of the library.
flickerstreak@30 1638 [optional] boolean - whether to not load a library if it is not found. Default: false
flickerstreak@30 1639 [optional] boolean - whether to not error if a library is not found. Default: false
flickerstreak@30 1640 Returns:
flickerstreak@30 1641 library
flickerstreak@30 1642 * table or nil - the library requested
flickerstreak@30 1643 Example:
flickerstreak@30 1644 local LibMonkey = Rock:GetLibrary("LibMonkey-1.0")
flickerstreak@30 1645 -- or
flickerstreak@30 1646 local LibMonkey = Rock("LibMonkey-1.0")
flickerstreak@30 1647 -----------------------------------------------------------------------------]]
flickerstreak@30 1648 function Rock:GetLibrary(major, dontLoad, dontError)
flickerstreak@30 1649 if type(major) ~= "string" then
flickerstreak@30 1650 error(("Bad argument #2 to `GetLibrary'. Expected %q, got %q."):format("string", type(major)), 2)
flickerstreak@30 1651 end
flickerstreak@30 1652 if dontLoad and dontLoad ~= true then
flickerstreak@30 1653 error(("Bad argument #3 to `GetLibrary'. Expected %q or %q, got %q."):format("boolean", "nil", type(dontLoad)), 2)
flickerstreak@30 1654 end
flickerstreak@30 1655 if dontError and dontError ~= true then
flickerstreak@30 1656 error(("Bad argument #4 to `GetLibrary'. Expected %q or %q, got %q."):format("boolean", "nil", type(dontError)), 2)
flickerstreak@30 1657 end
flickerstreak@30 1658 if not dontLoad then
flickerstreak@30 1659 TryToLoadStandalone(major)
flickerstreak@30 1660 end
flickerstreak@30 1661
flickerstreak@30 1662 local library = GetLibStubLibrary(major)
flickerstreak@30 1663 if not library then
flickerstreak@30 1664 if dontError then
flickerstreak@30 1665 return nil
flickerstreak@30 1666 end
flickerstreak@30 1667 error(("Library %q not found."):format(major), 2)
flickerstreak@30 1668 end
flickerstreak@30 1669
flickerstreak@30 1670 return library
flickerstreak@30 1671 end
flickerstreak@30 1672
flickerstreak@30 1673 setmetatable(Rock, { __call = Rock.GetLibrary })
flickerstreak@30 1674
flickerstreak@30 1675 --[[---------------------------------------------------------------------------
flickerstreak@30 1676 Arguments:
flickerstreak@30 1677 string - name of the library.
flickerstreak@30 1678 Returns:
flickerstreak@30 1679 boolean - whether the library exists and is a proper mixin which can be embedded.
flickerstreak@30 1680 Example:
flickerstreak@30 1681 local isMixin = Rock:IsLibraryMixin("LibMonkey-1.0")
flickerstreak@30 1682 -----------------------------------------------------------------------------]]
flickerstreak@30 1683 function Rock:IsLibraryMixin(name)
flickerstreak@30 1684 local library = self:GetLibrary(name, false, true)
flickerstreak@30 1685 if not library then
flickerstreak@30 1686 return false
flickerstreak@30 1687 end
flickerstreak@30 1688 return not not exportedMethods[library]
flickerstreak@30 1689 end
flickerstreak@30 1690
flickerstreak@30 1691 --[[---------------------------------------------------------------------------
flickerstreak@30 1692 Arguments:
flickerstreak@30 1693 string - name of the library.
flickerstreak@30 1694 [optional] boolean - whether to not load a library if it is not found. Default: false
flickerstreak@30 1695 Returns:
flickerstreak@30 1696 library
flickerstreak@30 1697 * table or nil - the library requested
flickerstreak@30 1698 Example:
flickerstreak@30 1699 local hasLibMonkey = Rock:HasLibrary("LibMonkey-1.0")
flickerstreak@30 1700 -----------------------------------------------------------------------------]]
flickerstreak@30 1701 function Rock:HasLibrary(major, dontLoad)
flickerstreak@30 1702 if type(major) ~= "string" then
flickerstreak@30 1703 error(("Bad argument #2 to `HasLibrary'. Expected %q, got %q."):format("string", type(major)), 2)
flickerstreak@30 1704 end
flickerstreak@30 1705 if dontLoad and dontLoad ~= true then
flickerstreak@30 1706 error(("Bad argument #3 to `HasLibrary'. Expected %q or %q, got %q."):format("boolean", "nil", type(dontLoad)), 2)
flickerstreak@30 1707 end
flickerstreak@30 1708 if not dontLoad then
flickerstreak@30 1709 TryToLoadStandalone(major)
flickerstreak@30 1710 end
flickerstreak@30 1711 return not not GetLibStubLibrary(major)
flickerstreak@30 1712 end
flickerstreak@30 1713
flickerstreak@30 1714 --[[---------------------------------------------------------------------------
flickerstreak@30 1715 Notes:
flickerstreak@30 1716 * This is exported to all libraries
flickerstreak@30 1717 Returns:
flickerstreak@30 1718 major, minor
flickerstreak@30 1719 * string - name of the library
flickerstreak@30 1720 * number - version of the library
flickerstreak@30 1721 Example:
flickerstreak@30 1722 local major, minor = Rock:GetLibraryVersion() -- will be "LibRock-1.0", 12345
flickerstreak@30 1723 local major, minor = LibMonkey:GetLibraryVersion() -- will be "LibMonkey-1.0", 50
flickerstreak@30 1724 -----------------------------------------------------------------------------]]
flickerstreak@30 1725 function Rock:GetLibraryVersion()
flickerstreak@30 1726 if type(self) ~= "table" then
flickerstreak@30 1727 return nil, nil
flickerstreak@30 1728 end
flickerstreak@30 1729 local major
flickerstreak@30 1730 local name = self.name
flickerstreak@30 1731 if name and GetLibStubLibrary(name) == self then
flickerstreak@30 1732 major = name
flickerstreak@30 1733 else
flickerstreak@30 1734 for m, instance in LibStub:IterateLibraries() do
flickerstreak@30 1735 if instance == self then
flickerstreak@30 1736 major = m
flickerstreak@30 1737 break
flickerstreak@30 1738 end
flickerstreak@30 1739 end
flickerstreak@30 1740 if not major then
flickerstreak@30 1741 return nil, nil
flickerstreak@30 1742 end
flickerstreak@30 1743 end
flickerstreak@30 1744 local _, minor = GetLibStubLibrary(major)
flickerstreak@30 1745 return major, minor
flickerstreak@30 1746 end
flickerstreak@30 1747
flickerstreak@30 1748 --[[---------------------------------------------------------------------------
flickerstreak@30 1749 Returns:
flickerstreak@30 1750 an iterator to traverse all registered libraries.
flickerstreak@30 1751 Example:
flickerstreak@30 1752 for major, library in Rock:IterateLibraries() do
flickerstreak@30 1753 -- do something with major and library
flickerstreak@30 1754 end
flickerstreak@30 1755 -----------------------------------------------------------------------------]]
flickerstreak@30 1756 function Rock:IterateLibraries()
flickerstreak@30 1757 return LibStub:IterateLibraries()
flickerstreak@30 1758 end
flickerstreak@30 1759
flickerstreak@30 1760 --[[---------------------------------------------------------------------------
flickerstreak@30 1761 Notes:
flickerstreak@30 1762 * This is exported to all libraries
flickerstreak@30 1763 * Allows you to set precisely what methods for the library to export.
flickerstreak@30 1764 * This automatically turns a library into a mixin.
flickerstreak@30 1765 Arguments:
flickerstreak@30 1766 tuple - the list of method names to export.
flickerstreak@30 1767 Example:
flickerstreak@30 1768 local LibMonkey = Rock:NewLibrary("LibMonkey-1.0", 50)
flickerstreak@30 1769 LibMonkey.FlingPoo = function(self)
flickerstreak@30 1770 return "Splat!"
flickerstreak@30 1771 end
flickerstreak@30 1772 LibMonkey:SetExportedMethods("FlingPoo")
flickerstreak@30 1773 -- later
flickerstreak@30 1774 local Darwin = Rock:NewAddon("Darwin", "LibMonkey-1.0")
flickerstreak@30 1775 assert(Darwin:FlingPoo() == "Splat!")
flickerstreak@30 1776 -----------------------------------------------------------------------------]]
flickerstreak@30 1777 function Rock:SetExportedMethods(...)
flickerstreak@30 1778 if exportedMethods[self] then
flickerstreak@30 1779 error("Cannot call `SetExportedMethods' more than once.", 2)
flickerstreak@30 1780 end
flickerstreak@30 1781 local t = newList(...)
flickerstreak@30 1782 if #t == 0 then
flickerstreak@30 1783 error("Must supply at least 1 method to `SetExportedMethods'.", 2)
flickerstreak@30 1784 end
flickerstreak@30 1785 for i,v in ipairs(t) do
flickerstreak@30 1786 if type(self[v]) ~= "function" then
flickerstreak@30 1787 error(("Bad argument #%d to `SetExportedMethods'. Method %q does not exist."):format(i+1, tostring(v)), 2)
flickerstreak@30 1788 end
flickerstreak@30 1789 end
flickerstreak@30 1790 exportedMethods[self] = t
flickerstreak@30 1791
flickerstreak@30 1792 local mixinToObject_library = mixinToObject[self]
flickerstreak@30 1793 if mixinToObject_library then
flickerstreak@30 1794 for object in pairs(mixinToObject_library) do
flickerstreak@30 1795 for _,method in ipairs(t) do
flickerstreak@30 1796 object[method] = self[method]
flickerstreak@30 1797 end
flickerstreak@30 1798 end
flickerstreak@30 1799 end
flickerstreak@30 1800 end
flickerstreak@30 1801
flickerstreak@30 1802 --[[---------------------------------------------------------------------------
flickerstreak@30 1803 Notes:
flickerstreak@30 1804 * This is exported to all libraries
flickerstreak@30 1805 * Embeds all the methods previously set to export onto a table.
flickerstreak@30 1806 * This will call :OnEmbed(object) on the library if it is available.
flickerstreak@30 1807 Arguments:
flickerstreak@30 1808 table - the table with which to export methods onto.
flickerstreak@30 1809 Returns:
flickerstreak@30 1810 The table provided, after embedding.
flickerstreak@30 1811 Example:
flickerstreak@30 1812 local LibMonkey = Rock:NewLibrary("LibMonkey-1.0", 50)
flickerstreak@30 1813 LibMonkey.FlingPoo = function(self)
flickerstreak@30 1814 return "Splat!"
flickerstreak@30 1815 end
flickerstreak@30 1816 LibMonkey:SetExportedMethods("FlingPoo")
flickerstreak@30 1817 -- later
flickerstreak@30 1818 local Darwin = {}
flickerstreak@30 1819 Rock("LibMonkey-1.0"):Embed(Darwin)
flickerstreak@30 1820 assert(Darwin:FlingPoo() == "Splat!")
flickerstreak@30 1821 -----------------------------------------------------------------------------]]
flickerstreak@30 1822 function Rock:Embed(object)
flickerstreak@30 1823 if not exportedMethods[self] then
flickerstreak@30 1824 error(("Cannot call `Embed' for library %q if `SetExportedMethods' has not been called."):format(tostring(self.name)), 2)
flickerstreak@30 1825 end
flickerstreak@30 1826 if type(object) ~= "table" then
flickerstreak@30 1827 error(("Bad argument #2 to `Embed'. Expected %q, got %q."):format("table", type(object)), 2)
flickerstreak@30 1828 end
flickerstreak@30 1829
flickerstreak@30 1830 for i,v in ipairs(exportedMethods[self]) do
flickerstreak@30 1831 if type(self[v]) ~= "function" then
flickerstreak@30 1832 error(("Problem embedding method %q from library %q. Expected %q, got %q."):format(tostring(v), better_tostring(self), "function", type(self[v])))
flickerstreak@30 1833 end
flickerstreak@30 1834 object[v] = self[v]
flickerstreak@30 1835 end
flickerstreak@30 1836
flickerstreak@30 1837 if not mixinToObject[self] then
flickerstreak@30 1838 -- weak because objects come and go
flickerstreak@30 1839 mixinToObject[self] = setmetatable(newList(), weakKey)
flickerstreak@30 1840 end
flickerstreak@30 1841 if mixinToObject[self][object] then
flickerstreak@30 1842 error(("Cannot embed library %q into the same object %q more than once."):format(better_tostring(self), better_tostring(object)), 2)
flickerstreak@30 1843 end
flickerstreak@30 1844 mixinToObject[self][object] = true
flickerstreak@30 1845 if type(rawget(object, 'mixins')) == "table" then
flickerstreak@30 1846 object.mixins[self] = true
flickerstreak@30 1847 end
flickerstreak@30 1848
flickerstreak@30 1849 local self_OnEmbed = self.OnEmbed
flickerstreak@30 1850 if self_OnEmbed then
flickerstreak@30 1851 local success, ret = pcall(self_OnEmbed, self, object)
flickerstreak@30 1852 if not success then
flickerstreak@30 1853 geterrorhandler()(ret)
flickerstreak@30 1854 end
flickerstreak@30 1855 end
flickerstreak@30 1856
flickerstreak@30 1857 return object
flickerstreak@30 1858 end
flickerstreak@30 1859
flickerstreak@30 1860 --[[---------------------------------------------------------------------------
flickerstreak@30 1861 Notes:
flickerstreak@30 1862 * This is exported to all libraries
flickerstreak@30 1863 * Unembeds all the methods previously set to export onto a table.
flickerstreak@30 1864 * This will error if the library is not embedded on the object
flickerstreak@30 1865 * This will call :OnUnembed(object) on the library if it is available.
flickerstreak@30 1866 Arguments:
flickerstreak@30 1867 table - the table with which to export methods onto.
flickerstreak@30 1868 Returns:
flickerstreak@30 1869 The table provided, after embedding.
flickerstreak@30 1870 Example:
flickerstreak@30 1871 local LibMonkey = Rock:NewLibrary("LibMonkey-1.0", 50)
flickerstreak@30 1872 LibMonkey.FlingPoo = function(self)
flickerstreak@30 1873 return "Splat!"
flickerstreak@30 1874 end
flickerstreak@30 1875 LibMonkey:SetExportedMethods("FlingPoo")
flickerstreak@30 1876 -- later
flickerstreak@30 1877 local Darwin = {}
flickerstreak@30 1878 Rock("LibMonkey-1.0"):Embed(Darwin)
flickerstreak@30 1879 assert(Darwin:FlingPoo() == "Splat!")
flickerstreak@30 1880 Rock("LibMonkey-1.0"):Unembed(Darwin)
flickerstreak@30 1881 assert(Darwin.FlingPoo == nil)
flickerstreak@30 1882 -----------------------------------------------------------------------------]]
flickerstreak@30 1883 function Rock:Unembed(object)
flickerstreak@30 1884 if not exportedMethods[self] then
flickerstreak@30 1885 error(("Cannot call `Unembed' for library %q if `SetExportedMethods' has not been called."):format(better_tostring(self)), 2)
flickerstreak@30 1886 end
flickerstreak@30 1887
flickerstreak@30 1888 if not mixinToObject[self] or not mixinToObject[self][object] then
flickerstreak@30 1889 error(("Cannot unembed library %q from object %q, since it is not embedded originally."):format(better_tostring(self), better_tostring(object)), 2)
flickerstreak@30 1890 end
flickerstreak@30 1891 local mixinToObject_self = mixinToObject[self]
flickerstreak@30 1892 mixinToObject_self[object] = nil
flickerstreak@30 1893 if not next(mixinToObject_self) then
flickerstreak@30 1894 mixinToObject[self] = del(mixinToObject_self)
flickerstreak@30 1895 end
flickerstreak@30 1896
flickerstreak@30 1897 local mixin_OnUnembed = self.OnUnembed
flickerstreak@30 1898 if mixin_OnUnembed then
flickerstreak@30 1899 local success, ret = pcall(mixin_OnUnembed, self, object)
flickerstreak@30 1900 if not success then
flickerstreak@30 1901 geterrorhandler()(ret)
flickerstreak@30 1902 end
flickerstreak@30 1903 end
flickerstreak@30 1904
flickerstreak@30 1905 for i,v in ipairs(exportedMethods[self]) do
flickerstreak@30 1906 object[v] = nil
flickerstreak@30 1907 end
flickerstreak@30 1908 end
flickerstreak@30 1909
flickerstreak@30 1910 local function embedAce2Mixin(mixin, object)
flickerstreak@30 1911 if not mixinToObject[mixin] then
flickerstreak@30 1912 mixinToObject[mixin] = setmetatable(newList(), weakKey)
flickerstreak@30 1913 end
flickerstreak@30 1914 mixinToObject[mixin][object] = true
flickerstreak@30 1915 mixin:embed(object)
flickerstreak@30 1916 end
flickerstreak@30 1917
flickerstreak@30 1918 local function embedLibStubMixin(mixin, object)
flickerstreak@30 1919 if not mixinToObject[mixin] then
flickerstreak@30 1920 mixinToObject[mixin] = setmetatable(newList(), weakKey)
flickerstreak@30 1921 end
flickerstreak@30 1922 mixinToObject[mixin][object] = true
flickerstreak@30 1923 mixin:Embed(object)
flickerstreak@30 1924 end
flickerstreak@30 1925
flickerstreak@30 1926 --[[---------------------------------------------------------------------------
flickerstreak@30 1927 Notes:
flickerstreak@30 1928 * create a new addon with the specified name.
flickerstreak@30 1929 Arguments:
flickerstreak@30 1930 string - name of the addon.
flickerstreak@30 1931 tuple - list of mixins with which to embed into this addon.
flickerstreak@30 1932 Returns:
flickerstreak@30 1933 addon
flickerstreak@30 1934 * table - the addon with which to manipulate
flickerstreak@30 1935 Example:
flickerstreak@30 1936 local MyAddon = Rock:NewAddon("MyAddon", "Mixin-1.0", "OtherMixin-2.0")
flickerstreak@30 1937 -----------------------------------------------------------------------------]]
flickerstreak@30 1938 function Rock:NewAddon(name, ...)
flickerstreak@30 1939 if type(name) ~= "string" then
flickerstreak@30 1940 error(("Bad argument #2 to `NewAddon'. Expected %q, got %q"):format("string", type(name)), 2)
flickerstreak@30 1941 end
flickerstreak@30 1942 if name:match("^Lib[A-Z]") then
flickerstreak@30 1943 error(("Bad argument #2 to `NewAddon'. Cannot start with %q, got %q."):format("Lib", name), 2)
flickerstreak@30 1944 end
flickerstreak@30 1945 if self == Rock and name:match("_") then
flickerstreak@30 1946 error(("Bad argument #2 to `NewAddon'. Cannot contain underscores, got %q."):format(name), 2)
flickerstreak@30 1947 end
flickerstreak@30 1948
flickerstreak@30 1949 if addons[name] then
flickerstreak@30 1950 error(("Bad argument #2 to `NewAddon'. Addon %q already created."):format(name), 2)
flickerstreak@30 1951 end
flickerstreak@30 1952 local addon = setmetatable(newList(), addon_mt)
flickerstreak@30 1953 addon.name = name
flickerstreak@30 1954
flickerstreak@30 1955 local mixinSet = newList()
flickerstreak@30 1956
flickerstreak@30 1957 for i = 1, select('#', ...) do
flickerstreak@30 1958 local libName = select(i, ...)
flickerstreak@30 1959 if mixinSet[libName] then
flickerstreak@30 1960 error(("Bad argument #%d to `NewAddon'. %q already stated."):format(i+2, tostring(libName)), 2)
flickerstreak@30 1961 end
flickerstreak@30 1962 mixinSet[libName] = true
flickerstreak@30 1963 TryToLoadStandalone(libName)
flickerstreak@30 1964 local library = Rock:GetLibrary(libName, false, true)
flickerstreak@30 1965 if not library then
flickerstreak@30 1966 error(("Bad argument #%d to `NewAddon'. Library %q is not found."):format(i+2, tostring(libName)), 2)
flickerstreak@30 1967 end
flickerstreak@30 1968
flickerstreak@30 1969 local style = 'rock'
flickerstreak@30 1970
flickerstreak@30 1971 if not exportedMethods[library] then
flickerstreak@30 1972 local good = false
flickerstreak@30 1973 if AceLibrary then
flickerstreak@30 1974 local AceOO = AceLibrary:HasInstance("AceOO-2.0", false) and AceLibrary("AceOO-2.0")
flickerstreak@30 1975 if AceOO.inherits(library, AceOO.Mixin) then
flickerstreak@30 1976 good = true
flickerstreak@30 1977 style = 'ace2'
flickerstreak@30 1978 end
flickerstreak@30 1979 end
flickerstreak@30 1980 if not good and type(rawget(library, 'Embed')) == "function" then
flickerstreak@30 1981 good = true
flickerstreak@30 1982 style = 'libstub'
flickerstreak@30 1983 end
flickerstreak@30 1984 if not good then
flickerstreak@30 1985 error(("Bad argument #%d to `NewAddon'. Library %q is not a mixin."):format(i+2, tostring(libName)), 2)
flickerstreak@30 1986 end
flickerstreak@30 1987 end
flickerstreak@30 1988
flickerstreak@30 1989 if library == Rock then
flickerstreak@30 1990 error(("Bad argument #%d to `NewAddon'. Cannot use %q as a mixin."):format(i+2, tostring(libName)), 2)
flickerstreak@30 1991 end
flickerstreak@30 1992
flickerstreak@30 1993 if style == 'rock' then
flickerstreak@30 1994 library:Embed(addon)
flickerstreak@30 1995 elseif style == 'ace2' then
flickerstreak@30 1996 embedAce2Mixin(library, addon)
flickerstreak@30 1997 elseif style == 'libstub' then
flickerstreak@30 1998 embedLibStubMixin(library, addon)
flickerstreak@30 1999 end
flickerstreak@30 2000 end
flickerstreak@30 2001
flickerstreak@30 2002 mixinSet = del(mixinSet)
flickerstreak@30 2003
flickerstreak@30 2004 addons[name] = addon
flickerstreak@30 2005 pendingAddons[#pendingAddons+1] = addon
flickerstreak@30 2006 pendingAddonsEnable[#pendingAddonsEnable+1] = addon
flickerstreak@30 2007 addonToFolder[addon] = figureCurrentAddon(self == Rock and 2 or 4)
flickerstreak@30 2008
flickerstreak@30 2009 frame:Show()
flickerstreak@30 2010
flickerstreak@30 2011 return addon
flickerstreak@30 2012 end
flickerstreak@30 2013
flickerstreak@30 2014 --[[---------------------------------------------------------------------------
flickerstreak@30 2015 Arguments:
flickerstreak@30 2016 string - name of the addon.
flickerstreak@30 2017 Returns:
flickerstreak@30 2018 addon
flickerstreak@30 2019 * table or nil - the addon requested
flickerstreak@30 2020 Example:
flickerstreak@30 2021 local MyAddon = Rock:GetAddon("MyAddon")
flickerstreak@30 2022 -----------------------------------------------------------------------------]]
flickerstreak@30 2023 function Rock:GetAddon(name)
flickerstreak@30 2024 if type(name) ~= "string" then
flickerstreak@30 2025 return nil
flickerstreak@30 2026 end
flickerstreak@30 2027 local addon = addons[name]
flickerstreak@30 2028 if addon then
flickerstreak@30 2029 return addon
flickerstreak@30 2030 end
flickerstreak@30 2031 name = name:lower()
flickerstreak@30 2032 for k, v in pairs(addons) do
flickerstreak@30 2033 if k:lower() == name then
flickerstreak@30 2034 return v
flickerstreak@30 2035 end
flickerstreak@30 2036 end
flickerstreak@30 2037 return nil
flickerstreak@30 2038 end
flickerstreak@30 2039
flickerstreak@30 2040 --[[---------------------------------------------------------------------------
flickerstreak@30 2041 Arguments:
flickerstreak@30 2042 string or table - name of the addon or the addon itself.
flickerstreak@30 2043 Returns:
flickerstreak@30 2044 boolean - whether the addon requested exists.
flickerstreak@30 2045 Example:
flickerstreak@30 2046 local hasMyAddon = Rock:HasAddon("MyAddon")
flickerstreak@30 2047 -- or
flickerstreak@30 2048 local hasMyAddon = Rock:HasAddon(MyAddon)
flickerstreak@30 2049 -----------------------------------------------------------------------------]]
flickerstreak@30 2050 function Rock:HasAddon(name)
flickerstreak@30 2051 if type(name) == "string" then
flickerstreak@30 2052 local addon = addons[name]
flickerstreak@30 2053 if addon then
flickerstreak@30 2054 return true
flickerstreak@30 2055 end
flickerstreak@30 2056 name = name:lower()
flickerstreak@30 2057 for k, v in pairs(addons) do
flickerstreak@30 2058 if k:lower() == name then
flickerstreak@30 2059 return true
flickerstreak@30 2060 end
flickerstreak@30 2061 end
flickerstreak@30 2062 elseif type(name) == "table" then
flickerstreak@30 2063 for k,v in pairs(addons) do
flickerstreak@30 2064 if v == name then
flickerstreak@30 2065 return true
flickerstreak@30 2066 end
flickerstreak@30 2067 end
flickerstreak@30 2068 end
flickerstreak@30 2069 return false
flickerstreak@30 2070 end
flickerstreak@30 2071
flickerstreak@30 2072 --[[---------------------------------------------------------------------------
flickerstreak@30 2073 Returns:
flickerstreak@30 2074 an iterator to traverse all addons created with Rock.
flickerstreak@30 2075 Example:
flickerstreak@30 2076 for name, addon in Rock:IterateAddons() do
flickerstreak@30 2077 -- do something with name and addon
flickerstreak@30 2078 end
flickerstreak@30 2079 -----------------------------------------------------------------------------]]
flickerstreak@30 2080 function Rock:IterateAddons()
flickerstreak@30 2081 return pairs(addons)
flickerstreak@30 2082 end
flickerstreak@30 2083
flickerstreak@30 2084 --[[---------------------------------------------------------------------------
flickerstreak@30 2085 Arguments:
flickerstreak@30 2086 string - major version of the mixin library
flickerstreak@30 2087 Returns:
flickerstreak@30 2088 an iterator to traverse all objects that the given mixin has embedded into
flickerstreak@30 2089 Example:
flickerstreak@30 2090 local LibMonkey = Rock:NewLibrary("LibMonkey-1.0")
flickerstreak@30 2091 local Darwin = Rock:NewAddon("Darwin", "LibMonkey-1.0")
flickerstreak@30 2092 for object in LibMonkey:IterateMixinObjects("LibMonkey-1.0") do
flickerstreak@30 2093 assert(object == Darwin)
flickerstreak@30 2094 end
flickerstreak@30 2095 -----------------------------------------------------------------------------]]
flickerstreak@30 2096 function Rock:IterateMixinObjects(mixinName)
flickerstreak@30 2097 local mixin
flickerstreak@30 2098 if type(mixinName) == "table" then
flickerstreak@30 2099 mixin = mixinName
flickerstreak@30 2100 else
flickerstreak@30 2101 if type(mixinName) ~= "string" then
flickerstreak@30 2102 error(("Bad argument #2 to `IterateMixinObjects'. Expected %q or %q, got %q."):format("table", "string", type(mixinName)), 2)
flickerstreak@30 2103 end
flickerstreak@30 2104 mixin = libraries[mixinName]
flickerstreak@30 2105 end
flickerstreak@30 2106 local mixinToObject_mixin = mixinToObject[mixin]
flickerstreak@30 2107 if not mixinToObject_mixin then
flickerstreak@30 2108 return noop
flickerstreak@30 2109 end
flickerstreak@30 2110 return pairs(mixinToObject_mixin)
flickerstreak@30 2111 end
flickerstreak@30 2112
flickerstreak@30 2113 local function iter(object, mixin)
flickerstreak@30 2114 mixin = next(mixinToObject, mixin)
flickerstreak@30 2115 if not mixin then
flickerstreak@30 2116 return nil
flickerstreak@30 2117 elseif mixinToObject[mixin][object] then
flickerstreak@30 2118 return mixin
flickerstreak@30 2119 end
flickerstreak@30 2120 return iter(object, mixin) -- try next mixin
flickerstreak@30 2121 end
flickerstreak@30 2122 --[[---------------------------------------------------------------------------
flickerstreak@30 2123 Returns:
flickerstreak@30 2124 an iterator to traverse all mixins that an object has embedded
flickerstreak@30 2125 Example:
flickerstreak@30 2126 local LibMonkey = Rock:NewLibrary("LibMonkey-1.0")
flickerstreak@30 2127 local Darwin = Rock:NewAddon("Darwin", "LibMonkey-1.0")
flickerstreak@30 2128 for mixin in Rock:IterateObjectMixins(Darwin) do
flickerstreak@30 2129 assert(mixin == LibMonkey)
flickerstreak@30 2130 end
flickerstreak@30 2131 -----------------------------------------------------------------------------]]
flickerstreak@30 2132 function Rock:IterateObjectMixins(object)
flickerstreak@30 2133 if type(object) ~= "table" then
flickerstreak@30 2134 error(("Bad argument #2 to `IterateObjectMixins'. Expected %q, got %q."):format("table", type(object)), 2)
flickerstreak@30 2135 end
flickerstreak@30 2136 return iter, object, nil
flickerstreak@30 2137 end
flickerstreak@30 2138
flickerstreak@30 2139 --[[---------------------------------------------------------------------------
flickerstreak@30 2140 Arguments:
flickerstreak@30 2141 table - the object to check
flickerstreak@30 2142 string - the mixin to check
flickerstreak@30 2143 Returns:
flickerstreak@30 2144 boolean - whether the object has the given mixin embedded into it.
flickerstreak@30 2145 Example:
flickerstreak@30 2146 local LibMonkey = Rock:NewLibrary("LibMonkey-1.0")
flickerstreak@30 2147 local Darwin = Rock:NewAddon("Darwin", "LibMonkey-1.0")
flickerstreak@30 2148 assert(Rock:DoesObjectUseMixin(Darwin, "LibMonkey-1.0"))
flickerstreak@30 2149 -----------------------------------------------------------------------------]]
flickerstreak@30 2150 function Rock:DoesObjectUseMixin(object, mixinName)
flickerstreak@30 2151 if type(object) ~= "table" then
flickerstreak@30 2152 error(("Bad argument #2 to `IterateObjectMixins'. Expected %q, got %q."):format("table", type(object)), 2)
flickerstreak@30 2153 end
flickerstreak@30 2154 local mixin
flickerstreak@30 2155 if type(mixinName) == "table" then
flickerstreak@30 2156 mixin = mixinName
flickerstreak@30 2157 else
flickerstreak@30 2158 if type(mixinName) ~= "string" then
flickerstreak@30 2159 error(("Bad argument #3 to `IterateMiDoesObjectUseMixininObjects'. Expected %q or %q, got %q."):format("table", "string", type(mixinName)), 2)
flickerstreak@30 2160 end
flickerstreak@30 2161 mixin = libraries[mixinName]
flickerstreak@30 2162 end
flickerstreak@30 2163 if not mixin then
flickerstreak@30 2164 return false
flickerstreak@30 2165 end
flickerstreak@30 2166
flickerstreak@30 2167 local mixinToObject_mixin = mixinToObject[mixin]
flickerstreak@30 2168 if not mixinToObject_mixin then
flickerstreak@30 2169 return false
flickerstreak@30 2170 end
flickerstreak@30 2171 return not not mixinToObject_mixin[object]
flickerstreak@30 2172 end
flickerstreak@30 2173
flickerstreak@30 2174 Rock.UID_NUM = oldRock and oldRock.UID_NUM or 0
flickerstreak@30 2175 --[[---------------------------------------------------------------------------
flickerstreak@30 2176 Notes:
flickerstreak@30 2177 * This UID is not unique across sessions. If you save a UID in a saved variable, the same UID can be generated in another session.
flickerstreak@30 2178 Returns:
flickerstreak@30 2179 number - a unique number.
flickerstreak@30 2180 Example:
flickerstreak@30 2181 local UID = Rock:GetUID()
flickerstreak@30 2182 -----------------------------------------------------------------------------]]
flickerstreak@30 2183 function Rock:GetUID()
flickerstreak@30 2184 local num = Rock.UID_NUM + 1
flickerstreak@30 2185 Rock.UID_NUM = num
flickerstreak@30 2186 return num
flickerstreak@30 2187 end
flickerstreak@30 2188
flickerstreak@30 2189 local function unobfuscateEmail(email)
flickerstreak@30 2190 return email:gsub(" AT ", "@"):gsub(" DOT ", ".")
flickerstreak@30 2191 end
flickerstreak@30 2192 local function fix(char)
flickerstreak@30 2193 return ("%%%02x"):format(char:byte())
flickerstreak@30 2194 end
flickerstreak@30 2195 local function urlencode(text)
flickerstreak@30 2196 return text:gsub("[^0-9A-Za-z]", fix)
flickerstreak@30 2197 end
flickerstreak@30 2198
flickerstreak@30 2199 local url
flickerstreak@30 2200 local function makeURLFrame()
flickerstreak@30 2201 makeURLFrame = nil
flickerstreak@30 2202 local function bumpFrameLevels(frame, amount)
flickerstreak@30 2203 frame:SetFrameLevel(frame:GetFrameLevel()+amount)
flickerstreak@30 2204 local children = newList(frame:GetChildren())
flickerstreak@30 2205 for _,v in ipairs(children) do
flickerstreak@30 2206 bumpFrameLevels(v, amount)
flickerstreak@30 2207 end
flickerstreak@30 2208 children = del(children)
flickerstreak@30 2209 end
flickerstreak@30 2210 -- some code borrowed from Prat here
flickerstreak@30 2211 StaticPopupDialogs["ROCK_SHOW_URL"] = {
flickerstreak@30 2212 text = not IsMacClient() and L["Press Ctrl-C to copy, then Alt-Tab out of the game, open your favorite web browser, and paste the link into the address bar."] or L["Press Cmd-C to copy, then Cmd-Tab out of the game, open your favorite web browser, and paste the link into the address bar."],
flickerstreak@30 2213 button2 = ACCEPT,
flickerstreak@30 2214 hasEditBox = 1,
flickerstreak@30 2215 hasWideEditBox = 1,
flickerstreak@30 2216 showAlert = 1, -- HACK : it's the only way I found to make de StaticPopup have sufficient width to show WideEditBox :(
flickerstreak@30 2217
flickerstreak@30 2218 OnShow = function()
flickerstreak@30 2219 local editBox = _G[this:GetName() .. "WideEditBox"]
flickerstreak@30 2220 editBox:SetText(url)
flickerstreak@30 2221 editBox:SetFocus()
flickerstreak@30 2222 editBox:HighlightText(0)
flickerstreak@30 2223 editBox:SetScript("OnTextChanged", function() StaticPopup_EditBoxOnTextChanged() end)
flickerstreak@30 2224
flickerstreak@30 2225 local button = _G[this:GetName() .. "Button2"]
flickerstreak@30 2226 button:ClearAllPoints()
flickerstreak@30 2227 button:SetWidth(200)
flickerstreak@30 2228 button:SetPoint("CENTER", editBox, "CENTER", 0, -30)
flickerstreak@30 2229
flickerstreak@30 2230 _G[this:GetName() .. "AlertIcon"]:Hide() -- HACK : we hide the false AlertIcon
flickerstreak@30 2231 this:SetFrameStrata("FULLSCREEN_DIALOG")
flickerstreak@30 2232 bumpFrameLevels(this, 30)
flickerstreak@30 2233 end,
flickerstreak@30 2234 OnHide = function()
flickerstreak@30 2235 local editBox = _G[this:GetName() .. "WideEditBox"]
flickerstreak@30 2236 editBox:SetScript("OnTextChanged", nil)
flickerstreak@30 2237 this:SetFrameStrata("DIALOG")
flickerstreak@30 2238 bumpFrameLevels(this, -30)
flickerstreak@30 2239 end,
flickerstreak@30 2240 OnAccept = function() end,
flickerstreak@30 2241 OnCancel = function() end,
flickerstreak@30 2242 EditBoxOnEscapePressed = function() this:GetParent():Hide() end,
flickerstreak@30 2243 EditBoxOnTextChanged = function()
flickerstreak@30 2244 this:SetText(url)
flickerstreak@30 2245 this:SetFocus()
flickerstreak@30 2246 this:HighlightText(0)
flickerstreak@30 2247 end,
flickerstreak@30 2248 timeout = 0,
flickerstreak@30 2249 whileDead = 1,
flickerstreak@30 2250 hideOnEscape = 1
flickerstreak@30 2251 }
flickerstreak@30 2252 end
flickerstreak@30 2253
flickerstreak@30 2254 function OpenDonationFrame(self)
flickerstreak@30 2255 if makeURLFrame then
flickerstreak@30 2256 makeURLFrame()
flickerstreak@30 2257 end
flickerstreak@30 2258
flickerstreak@30 2259 local donate = self.donate
flickerstreak@30 2260 if type(donate) ~= "string" then
flickerstreak@30 2261 donate = "Wowace"
flickerstreak@30 2262 end
flickerstreak@30 2263 local style, data = (":"):split(donate, 2)
flickerstreak@30 2264 style = style:lower()
flickerstreak@30 2265 if style ~= "website" and style ~= "paypal" then
flickerstreak@30 2266 style = "wowace"
flickerstreak@30 2267 end
flickerstreak@30 2268 if style == "wowace" then
flickerstreak@30 2269 url = "http://www.wowace.com/wiki/Donations"
flickerstreak@30 2270 elseif style == "website" then
flickerstreak@30 2271 url = data
flickerstreak@30 2272 else -- PayPal
flickerstreak@30 2273 local text = "https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=" .. urlencode(unobfuscateEmail(data))
flickerstreak@30 2274 local name
flickerstreak@30 2275 if type(self.title) == "string" then
flickerstreak@30 2276 name = self.title
flickerstreak@30 2277 elseif type(self.name) == "string" then
flickerstreak@30 2278 name = self.name
flickerstreak@30 2279 end
flickerstreak@30 2280 if name == MAJOR_VERSION then
flickerstreak@30 2281 name = "Rock"
flickerstreak@30 2282 end
flickerstreak@30 2283 if name then
flickerstreak@30 2284 name = name:gsub("|c%x%x%x%x%x%x%x%x", ""):gsub("|r", "")
flickerstreak@30 2285 text = text .. "&item_name=" .. urlencode(name)
flickerstreak@30 2286 end
flickerstreak@30 2287 url = text
flickerstreak@30 2288 end
flickerstreak@30 2289
flickerstreak@30 2290 StaticPopup_Show("ROCK_SHOW_URL")
flickerstreak@30 2291 end
flickerstreak@30 2292 function OpenIssueFrame(self)
flickerstreak@30 2293 if makeURLFrame then
flickerstreak@30 2294 makeURLFrame()
flickerstreak@30 2295 end
flickerstreak@30 2296
flickerstreak@30 2297 local issueTracker = self.issueTracker
flickerstreak@30 2298 if type(issueTracker) ~= "string" then
flickerstreak@30 2299 return
flickerstreak@30 2300 end
flickerstreak@30 2301 local style, data = (":"):split(issueTracker, 2)
flickerstreak@30 2302 style = style:lower()
flickerstreak@30 2303 if style ~= "website" and style ~= "wowace" then
flickerstreak@30 2304 return
flickerstreak@30 2305 end
flickerstreak@30 2306 if style == "wowace" then
flickerstreak@30 2307 url = "http://jira.wowace.com/secure/CreateIssue.jspa?pid=" .. data
flickerstreak@30 2308 elseif style == "website" then
flickerstreak@30 2309 url = data
flickerstreak@30 2310 end
flickerstreak@30 2311
flickerstreak@30 2312 StaticPopup_Show("ROCK_SHOW_URL")
flickerstreak@30 2313 end
flickerstreak@30 2314 local function donate_hidden(addon)
flickerstreak@30 2315 return type(addon.donate) ~= "string"
flickerstreak@30 2316 end
flickerstreak@30 2317
flickerstreak@30 2318 local function issue_hidden(addon)
flickerstreak@30 2319 return type(addon.issueTracker) ~= "string"
flickerstreak@30 2320 end
flickerstreak@30 2321
flickerstreak@30 2322 -- #NODOC
flickerstreak@30 2323 function Rock:GetRockConfigOptions(addon)
flickerstreak@30 2324 return 'active', {
flickerstreak@30 2325 type = 'boolean',
flickerstreak@30 2326 name = L["Enabled"],
flickerstreak@30 2327 desc = L["Enable or disable this addon."],
flickerstreak@30 2328 get = 'IsActive',
flickerstreak@30 2329 set = 'ToggleActive',
flickerstreak@30 2330 handler = addon,
flickerstreak@30 2331 order = -1,
flickerstreak@30 2332 }, 'donate', {
flickerstreak@30 2333 type = 'execute',
flickerstreak@30 2334 name = L["Give donation"],
flickerstreak@30 2335 buttonText = L["Donate"],
flickerstreak@30 2336 desc = L["Give a much-needed donation to the author of this addon."],
flickerstreak@30 2337 func = OpenDonationFrame,
flickerstreak@30 2338 hidden = donate_hidden,
flickerstreak@30 2339 passValue = addon,
flickerstreak@30 2340 order = -2,
flickerstreak@30 2341 }, 'issue', {
flickerstreak@30 2342 type = 'execute',
flickerstreak@30 2343 name = L["File issue"],
flickerstreak@30 2344 buttonText = L["Report"],
flickerstreak@30 2345 desc = L["File a bug or request a new feature or an improvement to this addon."],
flickerstreak@30 2346 func = OpenIssueFrame,
flickerstreak@30 2347 hidden = issue_hidden,
flickerstreak@30 2348 passValue = addon,
flickerstreak@30 2349 order = -3,
flickerstreak@30 2350 }
flickerstreak@30 2351 end
flickerstreak@30 2352
flickerstreak@30 2353 local function initAddon(addon, name)
flickerstreak@30 2354 name = addonToFolder[addon] or name or ""
flickerstreak@30 2355 -- TOC checks
flickerstreak@30 2356 if addon.title == nil then
flickerstreak@30 2357 addon.title = GetAddOnMetadata(name, "Title")
flickerstreak@30 2358 end
flickerstreak@30 2359 if type(addon.title) == "string" then
flickerstreak@30 2360 addon.title = addon.title:gsub("|c%x%x%x%x%x%x%x%x", ""):gsub("|r", ""):gsub("%-Rock%-$", ""):trim()
flickerstreak@30 2361 end
flickerstreak@30 2362 if addon.notes == nil then
flickerstreak@30 2363 addon.notes = GetAddOnMetadata(name, "Notes")
flickerstreak@30 2364 end
flickerstreak@30 2365 if type(addon.notes) == "string" then
flickerstreak@30 2366 addon.notes = addon.notes:trim()
flickerstreak@30 2367 end
flickerstreak@30 2368 if addon.version == nil then
flickerstreak@30 2369 addon.version = GetAddOnMetadata(name, "Version")
flickerstreak@30 2370 end
flickerstreak@30 2371 if type(addon.version) == "string" then
flickerstreak@30 2372 addon.version = addon.version:trim()
flickerstreak@30 2373 end
flickerstreak@30 2374 if addon.author == nil then
flickerstreak@30 2375 addon.author = GetAddOnMetadata(name, "Author")
flickerstreak@30 2376 end
flickerstreak@30 2377 if type(addon.author) == "string" then
flickerstreak@30 2378 addon.author = addon.author:trim()
flickerstreak@30 2379 end
flickerstreak@30 2380 if addon.credits == nil then
flickerstreak@30 2381 addon.credits = GetAddOnMetadata(name, "X-Credits")
flickerstreak@30 2382 end
flickerstreak@30 2383 if type(addon.credits) == "string" then
flickerstreak@30 2384 addon.credits = addon.credits:trim()
flickerstreak@30 2385 end
flickerstreak@30 2386 if addon.donate == nil then
flickerstreak@30 2387 addon.donate = GetAddOnMetadata(name, "X-Donate")
flickerstreak@30 2388 end
flickerstreak@30 2389 if type(addon.donate) == "string" then
flickerstreak@30 2390 addon.donate = addon.donate:trim()
flickerstreak@30 2391 end
flickerstreak@30 2392 if addon.issueTracker == nil then
flickerstreak@30 2393 addon.issueTracker = GetAddOnMetadata(name, "X-IssueTracker")
flickerstreak@30 2394 end
flickerstreak@30 2395 if type(addon.issueTracker) == "string" then
flickerstreak@30 2396 addon.issueTracker = addon.issueTracker:trim()
flickerstreak@30 2397 end
flickerstreak@30 2398 if addon.category == nil then
flickerstreak@30 2399 addon.category = GetAddOnMetadata(name, "X-Category")
flickerstreak@30 2400 end
flickerstreak@30 2401 if type(addon.category) == "string" then
flickerstreak@30 2402 addon.category = addon.category:trim()
flickerstreak@30 2403 end
flickerstreak@30 2404 if addon.email == nil then
flickerstreak@30 2405 addon.email = GetAddOnMetadata(name, "X-eMail") or GetAddOnMetadata(name, "X-Email")
flickerstreak@30 2406 end
flickerstreak@30 2407 if type(addon.email) == "string" then
flickerstreak@30 2408 addon.email = addon.email:trim()
flickerstreak@30 2409 end
flickerstreak@30 2410 if addon.license == nil then
flickerstreak@30 2411 addon.license = GetAddOnMetadata(name, "X-License")
flickerstreak@30 2412 end
flickerstreak@30 2413 if type(addon.license) == "string" then
flickerstreak@30 2414 addon.license = addon.license:trim()
flickerstreak@30 2415 end
flickerstreak@30 2416 if addon.website == nil then
flickerstreak@30 2417 addon.website = GetAddOnMetadata(name, "X-Website")
flickerstreak@30 2418 end
flickerstreak@30 2419 if type(addon.website) == "string" then
flickerstreak@30 2420 addon.website = addon.website:trim()
flickerstreak@30 2421 end
flickerstreak@30 2422
flickerstreak@30 2423 for mixin in Rock:IterateObjectMixins(addon) do
flickerstreak@30 2424 local mixin_OnEmbedInitialize = mixin.OnEmbedInitialize
flickerstreak@30 2425 if mixin_OnEmbedInitialize then
flickerstreak@30 2426 local success, ret = pcall(mixin_OnEmbedInitialize, mixin, addon)
flickerstreak@30 2427 if not success then
flickerstreak@30 2428 geterrorhandler()(ret)
flickerstreak@30 2429 end
flickerstreak@30 2430 end
flickerstreak@30 2431 end
flickerstreak@30 2432
flickerstreak@30 2433 local addon_OnInitialize = addon.OnInitialize
flickerstreak@30 2434 if addon_OnInitialize then
flickerstreak@30 2435 local success, ret = pcall(addon_OnInitialize, addon)
flickerstreak@30 2436 if not success then
flickerstreak@30 2437 geterrorhandler()(ret)
flickerstreak@30 2438 end
flickerstreak@30 2439 end
flickerstreak@30 2440
flickerstreak@30 2441 if LibRockEvent then
flickerstreak@30 2442 Rock:DispatchEvent("AddonInitialized", addon)
flickerstreak@30 2443 end
flickerstreak@30 2444 end
flickerstreak@30 2445
flickerstreak@30 2446
flickerstreak@30 2447 local function manualEnable(addon)
flickerstreak@30 2448 for i,v in ipairs(pendingAddons) do
flickerstreak@30 2449 if v == addon then
flickerstreak@30 2450 return
flickerstreak@30 2451 end
flickerstreak@30 2452 end
flickerstreak@30 2453 if currentlyEnabledAddons[addon] then
flickerstreak@30 2454 return false
flickerstreak@30 2455 end
flickerstreak@30 2456 currentlyEnabledAddons[addon] = true
flickerstreak@30 2457
flickerstreak@30 2458 local first = not addonsAlreadyEnabled[addon]
flickerstreak@30 2459 addonsAlreadyEnabled[addon] = true
flickerstreak@30 2460
flickerstreak@30 2461 for mixin in Rock:IterateObjectMixins(addon) do
flickerstreak@30 2462 local mixin_OnEmbedEnable = mixin.OnEmbedEnable
flickerstreak@30 2463 if mixin_OnEmbedEnable then
flickerstreak@30 2464 local success, ret = pcall(mixin_OnEmbedEnable, mixin, addon, first)
flickerstreak@30 2465 if not success then
flickerstreak@30 2466 geterrorhandler()(ret)
flickerstreak@30 2467 end
flickerstreak@30 2468 end
flickerstreak@30 2469 end
flickerstreak@30 2470 local addon_OnEnable = addon.OnEnable
flickerstreak@30 2471 if addon_OnEnable then
flickerstreak@30 2472 local success, ret = pcall(addon_OnEnable, addon, first)
flickerstreak@30 2473 if not success then
flickerstreak@30 2474 geterrorhandler()(ret)
flickerstreak@30 2475 end
flickerstreak@30 2476 end
flickerstreak@30 2477
flickerstreak@30 2478 if LibRockEvent then
flickerstreak@30 2479 Rock:DispatchEvent("AddonEnabled", addon, first)
flickerstreak@30 2480 end
flickerstreak@30 2481
flickerstreak@30 2482 return true, first
flickerstreak@30 2483 end
flickerstreak@30 2484
flickerstreak@30 2485 local function manualDisable(addon)
flickerstreak@30 2486 if not currentlyEnabledAddons[addon] then
flickerstreak@30 2487 return false
flickerstreak@30 2488 end
flickerstreak@30 2489 currentlyEnabledAddons[addon] = nil
flickerstreak@30 2490
flickerstreak@30 2491 for mixin in Rock:IterateObjectMixins(addon) do
flickerstreak@30 2492 local mixin_OnEmbedDisable = mixin.OnEmbedDisable
flickerstreak@30 2493 if mixin_OnEmbedDisable then
flickerstreak@30 2494 local success, ret = pcall(mixin_OnEmbedDisable, mixin, addon)
flickerstreak@30 2495 if not success then
flickerstreak@30 2496 geterrorhandler()(ret)
flickerstreak@30 2497 end
flickerstreak@30 2498 end
flickerstreak@30 2499 end
flickerstreak@30 2500 local addon_OnDisable = addon.OnDisable
flickerstreak@30 2501 if addon_OnDisable then
flickerstreak@30 2502 local success, ret = pcall(addon_OnDisable, addon)
flickerstreak@30 2503 if not success then
flickerstreak@30 2504 geterrorhandler()(ret)
flickerstreak@30 2505 end
flickerstreak@30 2506 end
flickerstreak@30 2507
flickerstreak@30 2508 if LibRockEvent then
flickerstreak@30 2509 Rock:DispatchEvent("AddonDisabled", addon)
flickerstreak@30 2510 end
flickerstreak@30 2511 return true
flickerstreak@30 2512 end
flickerstreak@30 2513
flickerstreak@30 2514 local function enableAddon(addon)
flickerstreak@30 2515 for i,v in ipairs(pendingAddons) do
flickerstreak@30 2516 if v == addon then
flickerstreak@30 2517 return
flickerstreak@30 2518 end
flickerstreak@30 2519 end
flickerstreak@30 2520 if addon_mt___index.IsActive(addon) then
flickerstreak@30 2521 manualEnable(addon)
flickerstreak@30 2522 end
flickerstreak@30 2523 end
flickerstreak@30 2524
flickerstreak@30 2525 -- #NODOC
flickerstreak@30 2526 -- This is used by internal Rock libraries after updating the active state.
flickerstreak@30 2527 function Rock:RecheckEnabledStates()
flickerstreak@30 2528 local changed = false
flickerstreak@30 2529 for _,addon in pairs(addons) do
flickerstreak@30 2530 local good = true
flickerstreak@30 2531 for _,a in ipairs(pendingAddonsEnable) do
flickerstreak@30 2532 if addon == a then
flickerstreak@30 2533 good = false
flickerstreak@30 2534 break
flickerstreak@30 2535 end
flickerstreak@30 2536 end
flickerstreak@30 2537 if good then
flickerstreak@30 2538 if addon_mt___index.IsActive(addon) then
flickerstreak@30 2539 if manualEnable(addon) then
flickerstreak@30 2540 changed = true
flickerstreak@30 2541 end
flickerstreak@30 2542 else
flickerstreak@30 2543 if manualDisable(addon) then
flickerstreak@30 2544 changed = true
flickerstreak@30 2545 end
flickerstreak@30 2546 end
flickerstreak@30 2547 end
flickerstreak@30 2548 end
flickerstreak@30 2549 if changed then
flickerstreak@30 2550 return self:RecheckEnabledStates()
flickerstreak@30 2551 end
flickerstreak@30 2552 end
flickerstreak@30 2553
flickerstreak@30 2554 frame:UnregisterAllEvents()
flickerstreak@30 2555 frame:RegisterEvent("ADDON_LOADED")
flickerstreak@30 2556 frame:RegisterEvent("PLAYER_LOGIN")
flickerstreak@30 2557 local function runMainAddonLoadedChunk(name)
flickerstreak@30 2558 local tmp = newList()
flickerstreak@30 2559 tmp, pendingAddons = pendingAddons, tmp
flickerstreak@30 2560 for i, addon in ipairs(tmp) do
flickerstreak@30 2561 local folder = addonToFolder[addon]
flickerstreak@30 2562 if name and folder and not foldersLoaded[folder] then
flickerstreak@30 2563 for j = i, #tmp do
flickerstreak@30 2564 pendingAddons[#pendingAddons+1] = tmp[j]
flickerstreak@30 2565 tmp[j] = nil
flickerstreak@30 2566 end
flickerstreak@30 2567 break
flickerstreak@30 2568 end
flickerstreak@30 2569 initAddon(addon, name)
flickerstreak@30 2570 end
flickerstreak@30 2571
flickerstreak@30 2572 if IsLoggedIn() then
flickerstreak@30 2573 for i, addon in ipairs(tmp) do
flickerstreak@30 2574 for j, v in ipairs(pendingAddonsEnable) do
flickerstreak@30 2575 if v == addon then
flickerstreak@30 2576 table_remove(pendingAddonsEnable, i)
flickerstreak@30 2577 break
flickerstreak@30 2578 end
flickerstreak@30 2579 end
flickerstreak@30 2580 enableAddon(addon)
flickerstreak@30 2581 end
flickerstreak@30 2582 for i, addon in ipairs(pendingAddonsEnable) do
flickerstreak@30 2583 local good = true
flickerstreak@30 2584 for j, v in ipairs(pendingAddons) do
flickerstreak@30 2585 if v == addon then
flickerstreak@30 2586 good = false
flickerstreak@30 2587 break
flickerstreak@30 2588 end
flickerstreak@30 2589 end
flickerstreak@30 2590 if not good then
flickerstreak@30 2591 break
flickerstreak@30 2592 end
flickerstreak@30 2593 pendingAddonsEnable[i] = nil
flickerstreak@30 2594 enableAddon(addon)
flickerstreak@30 2595 end
flickerstreak@30 2596 end
flickerstreak@30 2597 tmp = del(tmp)
flickerstreak@30 2598 for library, addonName in pairs(pendingLibraries) do
flickerstreak@30 2599 if not name or foldersLoaded[addonName] then
flickerstreak@30 2600 local success, ret = pcall(error, ("Library %q not finalized before ADDON_LOADED."):format(better_tostring(library)), 3)
flickerstreak@30 2601 geterrorhandler()(ret)
flickerstreak@30 2602 Rock:FinalizeLibrary((library:GetLibraryVersion()))
flickerstreak@30 2603 end
flickerstreak@30 2604 end
flickerstreak@30 2605
flickerstreak@30 2606 if isStandalone then
flickerstreak@30 2607 local LibRock_1_0DB = _G.LibRock_1_0DB
flickerstreak@30 2608 if type(LibRock_1_0DB) ~= "table" then
flickerstreak@30 2609 LibRock_1_0DB = {}
flickerstreak@30 2610 _G.LibRock_1_0DB = LibRock_1_0DB
flickerstreak@30 2611 end
flickerstreak@30 2612 if type(LibRock_1_0DB.unitTests) ~= "table" then
flickerstreak@30 2613 LibRock_1_0DB.unitTests = {}
flickerstreak@30 2614 end
flickerstreak@30 2615 enableContracts = LibRock_1_0DB.contracts or false
flickerstreak@30 2616 unitTestDB = LibRock_1_0DB.unitTests
flickerstreak@30 2617 for namespace, data in pairs(unitTests) do
flickerstreak@30 2618 if not unitTestDB[namespace] then
flickerstreak@30 2619 if data then
flickerstreak@30 2620 del(data)
flickerstreak@30 2621 unitTests[namespace] = false
flickerstreak@30 2622 end
flickerstreak@30 2623 elseif data and (not name or data.addon == name) then
flickerstreak@30 2624 local stats = newList()
flickerstreak@30 2625 for i,v in ipairs(data) do
flickerstreak@30 2626 data[i] = nil
flickerstreak@30 2627
flickerstreak@30 2628 local libs = newList()
flickerstreak@30 2629 for k,v in pairs(libraries) do
flickerstreak@30 2630 libs[k] = v
flickerstreak@30 2631 end
flickerstreak@30 2632
flickerstreak@30 2633 local success, ret = pcall(v)
flickerstreak@30 2634 if not success then
flickerstreak@30 2635 geterrorhandler()(ret)
flickerstreak@30 2636 stats[i] = ret
flickerstreak@30 2637 else
flickerstreak@30 2638 stats[i] = false
flickerstreak@30 2639 end
flickerstreak@30 2640
flickerstreak@30 2641 for k in pairs(libraries) do
flickerstreak@30 2642 if not libs[k] then
flickerstreak@30 2643 __removeLibrary(k)
flickerstreak@30 2644 end
flickerstreak@30 2645 end
flickerstreak@30 2646 libs = del(libs)
flickerstreak@30 2647
flickerstreak@30 2648 local lastCount
flickerstreak@30 2649 repeat
flickerstreak@30 2650 lastCount = collectgarbage('count')
flickerstreak@30 2651 collectgarbage('collect')
flickerstreak@30 2652 until lastCount == collectgarbage('count')
flickerstreak@30 2653 end
flickerstreak@30 2654 del(data)
flickerstreak@30 2655 unitTests[namespace] = false
flickerstreak@30 2656 if #stats >= 1 then
flickerstreak@30 2657 local pass, fail = 0, 0
flickerstreak@30 2658 for i,v in ipairs(stats) do
flickerstreak@30 2659 if v then
flickerstreak@30 2660 fail = fail + 1
flickerstreak@30 2661 else
flickerstreak@30 2662 pass = pass + 1
flickerstreak@30 2663 end
flickerstreak@30 2664 end
flickerstreak@30 2665
flickerstreak@30 2666 local color
flickerstreak@30 2667 if fail == 0 then
flickerstreak@30 2668 _G.DEFAULT_CHAT_FRAME:AddMessage(("|cff00ff00%s: %d unit test(s) passed."):format(namespace, pass))
flickerstreak@30 2669 elseif pass > 0 then
flickerstreak@30 2670 _G.DEFAULT_CHAT_FRAME:AddMessage(("|cffff0000%s: %d unit test(s) passed, %d unit test(s) failed."):format(namespace, pass, fail))
flickerstreak@30 2671 else
flickerstreak@30 2672 _G.DEFAULT_CHAT_FRAME:AddMessage(("|cffff0000%s: %d unit test(s) failed."):format(namespace, fail))
flickerstreak@30 2673 end
flickerstreak@30 2674 for i,v in ipairs(stats) do
flickerstreak@30 2675 if v then
flickerstreak@30 2676 _G.DEFAULT_CHAT_FRAME:AddMessage(("|cffff0000%s|r"):format(tostring(v)))
flickerstreak@30 2677 end
flickerstreak@30 2678 end
flickerstreak@30 2679 if fail > 0 then
flickerstreak@30 2680 _G.DEFAULT_CHAT_FRAME:AddMessage("|cffff0000----------|r")
flickerstreak@30 2681 end
flickerstreak@30 2682 end
flickerstreak@30 2683 stats = del(stats)
flickerstreak@30 2684 end
flickerstreak@30 2685 end
flickerstreak@30 2686 end
flickerstreak@30 2687 if isStandalone and name == MAJOR_VERSION then
flickerstreak@30 2688 Rock("LibRockEvent-1.0", false, true) -- load if possible
flickerstreak@30 2689 Rock("LibRockConsole-1.0", false, true) -- load if possible - I like the default chat commands
flickerstreak@30 2690 Rock("LibRockComm-1.0", false, true) -- load if possible - has version checking and the like
flickerstreak@30 2691 Rock("LibRockConfig-1.0", false, true) -- load if possible - LibRock-1.0 registers with it.
flickerstreak@30 2692 end
flickerstreak@30 2693
flickerstreak@30 2694 for major, library in LibStub:IterateLibraries() do
flickerstreak@30 2695 manualFinalize(major, library)
flickerstreak@30 2696 end
flickerstreak@30 2697
flickerstreak@30 2698 if IsLoggedIn() then
flickerstreak@30 2699 collectgarbage('collect')
flickerstreak@30 2700 end
flickerstreak@30 2701 end
flickerstreak@30 2702
flickerstreak@30 2703 frame:Show()
flickerstreak@30 2704 frame:SetScript("OnUpdate", function(this, elapsed)
flickerstreak@30 2705 -- capture all un-initialized addons.
flickerstreak@30 2706 runMainAddonLoadedChunk()
flickerstreak@30 2707 collectgarbage('collect')
flickerstreak@30 2708 this:SetScript("OnUpdate", run)
flickerstreak@30 2709 end)
flickerstreak@30 2710 frame:SetScript("OnEvent", function(this, event, ...)
flickerstreak@30 2711 if event == "ADDON_LOADED" then
flickerstreak@30 2712 -- this creates a new table and flushes the old in case someone LoDs an addon inside ADDON_LOADED.
flickerstreak@30 2713 local name = ...
flickerstreak@30 2714 foldersLoaded[name] = true
flickerstreak@30 2715 runMainAddonLoadedChunk(name)
flickerstreak@30 2716 frame:Show()
flickerstreak@30 2717 elseif event == "PLAYER_LOGIN" then
flickerstreak@30 2718 for i, addon in ipairs(pendingAddonsEnable) do
flickerstreak@30 2719 local good = true
flickerstreak@30 2720 for _, a in ipairs(pendingAddons) do
flickerstreak@30 2721 if a == addon then
flickerstreak@30 2722 good = false
flickerstreak@30 2723 break
flickerstreak@30 2724 end
flickerstreak@30 2725 end
flickerstreak@30 2726 if good then
flickerstreak@30 2727 pendingAddonsEnable[i] = nil
flickerstreak@30 2728 enableAddon(addon)
flickerstreak@30 2729 end
flickerstreak@30 2730 end
flickerstreak@30 2731 collectgarbage('collect')
flickerstreak@30 2732 end
flickerstreak@30 2733 end)
flickerstreak@30 2734
flickerstreak@30 2735 Rock:SetExportedMethods("SetExportedMethods", "Embed", "Unembed", "GetLibraryVersion")
flickerstreak@30 2736
flickerstreak@30 2737 Rock:FinalizeLibrary(MAJOR_VERSION)
flickerstreak@30 2738
flickerstreak@30 2739 for major, library in LibStub:IterateLibraries() do
flickerstreak@30 2740 manualFinalize(major, library)
flickerstreak@30 2741 end
flickerstreak@30 2742
flickerstreak@30 2743 Rock:AddUnitTest(MAJOR_VERSION, function()
flickerstreak@30 2744 -- test recycling
flickerstreak@30 2745 local newList, newDict, newSet, del = Rock:GetRecyclingFunctions(MAJOR_VERSION .. "_UnitTest", "newList", "newDict", "newSet", "del", "Debug")
flickerstreak@30 2746 local t = newList("Alpha", "Bravo", "Charlie")
flickerstreak@30 2747 assert(t[1] == "Alpha")
flickerstreak@30 2748 assert(t[2] == "Bravo")
flickerstreak@30 2749 assert(t[3] == "Charlie")
flickerstreak@30 2750 t = del(t)
flickerstreak@30 2751 t = newList("Alpha", "Bravo", "Charlie")
flickerstreak@30 2752 -- check recycled table
flickerstreak@30 2753 assert(t[1] == "Alpha")
flickerstreak@30 2754 assert(t[2] == "Bravo")
flickerstreak@30 2755 assert(t[3] == "Charlie")
flickerstreak@30 2756 t = del(t)
flickerstreak@30 2757 t = newDict("Alpha", "Bravo", "Charlie", "Delta")
flickerstreak@30 2758 assert(t.Alpha == "Bravo")
flickerstreak@30 2759 assert(t.Charlie == "Delta")
flickerstreak@30 2760 t = del(t)
flickerstreak@30 2761 t = newSet("Alpha", "Bravo", "Charlie")
flickerstreak@30 2762 assert(t.Alpha)
flickerstreak@30 2763 assert(t.Bravo)
flickerstreak@30 2764 assert(t.Charlie)
flickerstreak@30 2765 t = del(t)
flickerstreak@30 2766
flickerstreak@30 2767 local debug = recycleData.debugPools[MAJOR_VERSION .. "_UnitTest"]
flickerstreak@30 2768 assert(debug.num == 0)
flickerstreak@30 2769 t = newList()
flickerstreak@30 2770 assert(debug.num == 1)
flickerstreak@30 2771 t[1] = newList()
flickerstreak@30 2772 assert(debug.num == 2)
flickerstreak@30 2773 t[2] = newList()
flickerstreak@30 2774 assert(debug.num == 3)
flickerstreak@30 2775 t[1] = del(t[1])
flickerstreak@30 2776 assert(debug.num == 2)
flickerstreak@30 2777 t[2] = del(t[2])
flickerstreak@30 2778 assert(debug.num == 1)
flickerstreak@30 2779 t = del(t)
flickerstreak@30 2780 assert(debug.num == 0)
flickerstreak@30 2781 end)
flickerstreak@30 2782
flickerstreak@30 2783 Rock:AddUnitTest(MAJOR_VERSION, function()
flickerstreak@30 2784 -- test :GetUID()
flickerstreak@30 2785 local t = {}
flickerstreak@30 2786 for i = 1, 10000 do
flickerstreak@30 2787 local uid = Rock:GetUID()
flickerstreak@30 2788 if t[i] then
flickerstreak@30 2789 error(("UID match for iteration %d, UID %s"):format(i, uid))
flickerstreak@30 2790 end
flickerstreak@30 2791 t[i] = true
flickerstreak@30 2792 end
flickerstreak@30 2793 end)
flickerstreak@30 2794
flickerstreak@30 2795 Rock:AddUnitTest(MAJOR_VERSION, function()
flickerstreak@30 2796 -- test basic creation and deletion
flickerstreak@30 2797 assert(not LibStub:GetLibrary("LibRockFakeLib-1.0", true))
flickerstreak@30 2798 assert(not Rock:HasLibrary("LibRockFakeLib-1.0"))
flickerstreak@30 2799 local lib = Rock:NewLibrary("LibRockFakeLib-1.0", 1)
flickerstreak@30 2800 Rock:FinalizeLibrary("LibRockFakeLib-1.0")
flickerstreak@30 2801 lib = nil
flickerstreak@30 2802 assert(LibStub:GetLibrary("LibRockFakeLib-1.0", true))
flickerstreak@30 2803 assert(Rock:HasLibrary("LibRockFakeLib-1.0"))
flickerstreak@30 2804 local good = false
flickerstreak@30 2805 for _, lib in pairs(libraries) do
flickerstreak@30 2806 if lib.name == "LibRockFakeLib-1.0" then
flickerstreak@30 2807 good = true
flickerstreak@30 2808 break
flickerstreak@30 2809 end
flickerstreak@30 2810 end
flickerstreak@30 2811 assert(good)
flickerstreak@30 2812 __removeLibrary("LibRockFakeLib-1.0")
flickerstreak@30 2813 for _, lib in pairs(libraries) do
flickerstreak@30 2814 assert(lib.name ~= "LibRockFakeLib-1.0")
flickerstreak@30 2815 end
flickerstreak@30 2816 assert(not LibStub:GetLibrary("LibRockFakeLib-1.0", true))
flickerstreak@30 2817 assert(not Rock:HasLibrary("LibRockFakeLib-1.0"))
flickerstreak@30 2818 end)
flickerstreak@30 2819
flickerstreak@30 2820 Rock:AddUnitTest(MAJOR_VERSION, function()
flickerstreak@30 2821 -- test library creation and the like
flickerstreak@30 2822 assert(not Rock:HasLibrary("LibRockFakeLib-1.0"))
flickerstreak@30 2823 for name in Rock:IterateLibraries() do
flickerstreak@30 2824 assert(name ~= "LibRockFakeLib-1.0")
flickerstreak@30 2825 end
flickerstreak@30 2826
flickerstreak@30 2827 local myLib, oldLib = Rock:NewLibrary("LibRockFakeLib-1.0", 1)
flickerstreak@30 2828 assert(myLib)
flickerstreak@30 2829 assert(myLib.name == "LibRockFakeLib-1.0")
flickerstreak@30 2830 assert(not oldLib)
flickerstreak@30 2831
flickerstreak@30 2832 assert(myLib:GetLibraryVersion() == "LibRockFakeLib-1.0")
flickerstreak@30 2833 assert(select(2, myLib:GetLibraryVersion()) == 1)
flickerstreak@30 2834
flickerstreak@30 2835 local good = false
flickerstreak@30 2836 for name in Rock:IterateLibraries() do
flickerstreak@30 2837 if name == "LibRockFakeLib-1.0" then
flickerstreak@30 2838 good = true
flickerstreak@30 2839 break
flickerstreak@30 2840 end
flickerstreak@30 2841 end
flickerstreak@30 2842 assert(good)
flickerstreak@30 2843 assert(Rock:HasLibrary("LibRockFakeLib-1.0"))
flickerstreak@30 2844 assert(Rock:GetLibrary("LibRockFakeLib-1.0") == myLib)
flickerstreak@30 2845 assert(Rock("LibRockFakeLib-1.0") == myLib)
flickerstreak@30 2846
flickerstreak@30 2847 assert(not Rock:IsLibraryMixin("LibRockFakeLib-1.0"))
flickerstreak@30 2848 function myLib:DoSomething()
flickerstreak@30 2849 return "Something"
flickerstreak@30 2850 end
flickerstreak@30 2851 myLib:SetExportedMethods("DoSomething")
flickerstreak@30 2852 assert(Rock:IsLibraryMixin("LibRockFakeLib-1.0"))
flickerstreak@30 2853 local t = {}
flickerstreak@30 2854 assert(not Rock:DoesObjectUseMixin(t, "LibRockFakeLib-1.0"))
flickerstreak@30 2855 assert(not t.DoSomething)
flickerstreak@30 2856 for mixin in Rock:IterateObjectMixins(t) do
flickerstreak@30 2857 assert(false)
flickerstreak@30 2858 end
flickerstreak@30 2859 for object in Rock:IterateMixinObjects("LibRockFakeLib-1.0") do
flickerstreak@30 2860 assert(false)
flickerstreak@30 2861 end
flickerstreak@30 2862 myLib:Embed(t)
flickerstreak@30 2863 assert(t:DoSomething() == "Something")
flickerstreak@30 2864 assert(Rock:DoesObjectUseMixin(t, "LibRockFakeLib-1.0"))
flickerstreak@30 2865 for mixin in Rock:IterateObjectMixins(t) do
flickerstreak@30 2866 assert(mixin == myLib)
flickerstreak@30 2867 end
flickerstreak@30 2868 for object in Rock:IterateMixinObjects("LibRockFakeLib-1.0") do
flickerstreak@30 2869 assert(object == t)
flickerstreak@30 2870 end
flickerstreak@30 2871
flickerstreak@30 2872 Rock:FinalizeLibrary("LibRockFakeLib-1.0")
flickerstreak@30 2873
flickerstreak@30 2874 local myNewLib, oldLib = Rock:NewLibrary("LibRockFakeLib-1.0", 2)
flickerstreak@30 2875 assert(myNewLib == myLib)
flickerstreak@30 2876 assert(oldLib)
flickerstreak@30 2877 assert(Rock:GetLibrary("LibRockFakeLib-1.0") == myLib)
flickerstreak@30 2878
flickerstreak@30 2879 function myLib:DoSomething()
flickerstreak@30 2880 return "Something else"
flickerstreak@30 2881 end
flickerstreak@30 2882 function myLib:TrySomething()
flickerstreak@30 2883 return "Blah"
flickerstreak@30 2884 end
flickerstreak@30 2885 myLib:SetExportedMethods("DoSomething", "TrySomething")
flickerstreak@30 2886 assert(Rock:IsLibraryMixin("LibRockFakeLib-1.0"))
flickerstreak@30 2887 assert(t:DoSomething() == "Something else")
flickerstreak@30 2888 assert(t:TrySomething() == "Blah")
flickerstreak@30 2889 assert(Rock:DoesObjectUseMixin(t, "LibRockFakeLib-1.0"))
flickerstreak@30 2890 for mixin in Rock:IterateObjectMixins(t) do
flickerstreak@30 2891 assert(mixin == myLib)
flickerstreak@30 2892 end
flickerstreak@30 2893 for object in Rock:IterateMixinObjects("LibRockFakeLib-1.0") do
flickerstreak@30 2894 assert(object == t)
flickerstreak@30 2895 end
flickerstreak@30 2896
flickerstreak@30 2897 Rock:FinalizeLibrary("LibRockFakeLib-1.0")
flickerstreak@30 2898
flickerstreak@30 2899 local myNewLib, oldLib = Rock:NewLibrary("LibRockFakeLib-1.0", 3)
flickerstreak@30 2900 assert(myNewLib == myLib)
flickerstreak@30 2901 assert(oldLib)
flickerstreak@30 2902 assert(Rock:GetLibrary("LibRockFakeLib-1.0") == myLib)
flickerstreak@30 2903
flickerstreak@30 2904 function myLib:DoSomething()
flickerstreak@30 2905 return "Something"
flickerstreak@30 2906 end
flickerstreak@30 2907 myLib:SetExportedMethods("DoSomething")
flickerstreak@30 2908 assert(Rock:IsLibraryMixin("LibRockFakeLib-1.0"))
flickerstreak@30 2909 assert(t:DoSomething() == "Something")
flickerstreak@30 2910 assert(t.TrySomething == nil)
flickerstreak@30 2911 assert(Rock:DoesObjectUseMixin(t, "LibRockFakeLib-1.0"))
flickerstreak@30 2912 for mixin in Rock:IterateObjectMixins(t) do
flickerstreak@30 2913 assert(mixin == myLib)
flickerstreak@30 2914 end
flickerstreak@30 2915 for object in Rock:IterateMixinObjects("LibRockFakeLib-1.0") do
flickerstreak@30 2916 assert(object == t)
flickerstreak@30 2917 end
flickerstreak@30 2918
flickerstreak@30 2919 Rock:FinalizeLibrary("LibRockFakeLib-1.0")
flickerstreak@30 2920
flickerstreak@30 2921 assert(not Rock:NewLibrary("LibRockFakeLib-1.0", 2)) -- out of date
flickerstreak@30 2922 assert(not Rock:NewLibrary("LibRockFakeLib-1.0", 3)) -- same revision
flickerstreak@30 2923 end)
flickerstreak@30 2924
flickerstreak@30 2925 Rock:AddUnitTest(MAJOR_VERSION, function()
flickerstreak@30 2926 assert(not Rock:HasAddon("RockFakeAddon"))
flickerstreak@30 2927 for name in Rock:IterateAddons() do
flickerstreak@30 2928 assert(name ~= "RockFakeAddon")
flickerstreak@30 2929 end
flickerstreak@30 2930
flickerstreak@30 2931 local myAddon = Rock:NewAddon("RockFakeAddon")
flickerstreak@30 2932
flickerstreak@30 2933 assert(myAddon)
flickerstreak@30 2934 assert(myAddon.name == "RockFakeAddon")
flickerstreak@30 2935
flickerstreak@30 2936 local good = false
flickerstreak@30 2937 for name in Rock:IterateAddons() do
flickerstreak@30 2938 if name == "RockFakeAddon" then
flickerstreak@30 2939 good = true
flickerstreak@30 2940 break
flickerstreak@30 2941 end
flickerstreak@30 2942 end
flickerstreak@30 2943 assert(good)
flickerstreak@30 2944 assert(Rock:HasAddon("RockFakeAddon"))
flickerstreak@30 2945 assert(Rock:GetAddon("RockFakeAddon") == myAddon)
flickerstreak@30 2946 end)
flickerstreak@30 2947
flickerstreak@30 2948 Rock:AddUnitTest(MAJOR_VERSION, function()
flickerstreak@30 2949 -- test :OnLibraryLoad
flickerstreak@30 2950 local lib = Rock:NewLibrary("LibRockFakeLib-1.0", 1)
flickerstreak@30 2951 local triggered = false
flickerstreak@30 2952 function lib:OnLibraryLoad(major, instance)
flickerstreak@30 2953 if major == "LibRockFakeLib-2.0" then
flickerstreak@30 2954 triggered = true
flickerstreak@30 2955 end
flickerstreak@30 2956 end
flickerstreak@30 2957 Rock:FinalizeLibrary("LibRockFakeLib-1.0")
flickerstreak@30 2958
flickerstreak@30 2959 local lib = Rock:NewLibrary("LibRockFakeLib-2.0", 1)
flickerstreak@30 2960 assert(not triggered)
flickerstreak@30 2961 Rock:FinalizeLibrary("LibRockFakeLib-2.0")
flickerstreak@30 2962 assert(triggered)
flickerstreak@30 2963 triggered = false
flickerstreak@30 2964 local lib = Rock:NewLibrary("LibRockFakeLib-2.0", 2)
flickerstreak@30 2965 assert(not triggered)
flickerstreak@30 2966 Rock:FinalizeLibrary("LibRockFakeLib-2.0")
flickerstreak@30 2967 assert(not triggered)
flickerstreak@30 2968 end)