PageRenderTime 66ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/Libraries/AceEvent-2.0/AceEvent-2.0.lua

https://bitbucket.org/zazu/lcvadminhg
Lua | 998 lines | 932 code | 26 blank | 40 comment | 74 complexity | ca7e6bec0eaf4645daa1e71f10d69b29 MD5 | raw file
  1. --[[
  2. Name: AceEvent-2.0
  3. Revision: $Rev: 1091 $
  4. Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team)
  5. Inspired By: Ace 1.x by Turan (turan@gryphon.com)
  6. Website: http://www.wowace.com/
  7. Documentation: http://www.wowace.com/index.php/AceEvent-2.0
  8. SVN: http://svn.wowace.com/wowace/trunk/Ace2/AceEvent-2.0
  9. Description: Mixin to allow for event handling, scheduling, and inter-addon
  10. communication.
  11. Dependencies: AceLibrary, AceOO-2.0
  12. License: LGPL v2.1
  13. ]]
  14. local MAJOR_VERSION = "AceEvent-2.0"
  15. local MINOR_VERSION = 90000 + tonumber(("$Revision: 1091 $"):match("(%d+)"))
  16. if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end
  17. if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
  18. if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0") end
  19. local AceOO = AceLibrary:GetInstance("AceOO-2.0")
  20. local Mixin = AceOO.Mixin
  21. local AceEvent = Mixin {
  22. "RegisterEvent",
  23. "RegisterAllEvents",
  24. "UnregisterEvent",
  25. "UnregisterAllEvents",
  26. "TriggerEvent",
  27. "ScheduleEvent",
  28. "ScheduleRepeatingEvent",
  29. "CancelScheduledEvent",
  30. "CancelAllScheduledEvents",
  31. "IsEventRegistered",
  32. "IsEventScheduled",
  33. "RegisterBucketEvent",
  34. "UnregisterBucketEvent",
  35. "UnregisterAllBucketEvents",
  36. "IsBucketEventRegistered",
  37. "ScheduleLeaveCombatAction",
  38. "CancelAllCombatSchedules",
  39. }
  40. local weakKey = {__mode="k"}
  41. local FAKE_NIL
  42. local RATE
  43. local eventsWhichHappenOnce = {
  44. PLAYER_LOGIN = true,
  45. AceEvent_FullyInitialized = true,
  46. VARIABLES_LOADED = true,
  47. PLAYER_LOGOUT = true,
  48. }
  49. local next = next
  50. local pairs = pairs
  51. local pcall = pcall
  52. local type = type
  53. local GetTime = GetTime
  54. local gcinfo = gcinfo
  55. local unpack = unpack
  56. local geterrorhandler = geterrorhandler
  57. local new, del
  58. do
  59. local cache = setmetatable({}, {__mode='k'})
  60. function new(...)
  61. local t = next(cache)
  62. if t then
  63. cache[t] = nil
  64. for i = 1, select('#', ...) do
  65. t[i] = select(i, ...)
  66. end
  67. return t
  68. else
  69. return { ... }
  70. end
  71. end
  72. function del(t)
  73. for k in pairs(t) do
  74. t[k] = nil
  75. end
  76. cache[t] = true
  77. return nil
  78. end
  79. end
  80. local registeringFromAceEvent
  81. --[[----------------------------------------------------------------------------------
  82. Notes:
  83. * Registers the addon with a Blizzard event or a custom AceEvent, which will cause the given method to be called when that is triggered.
  84. Arguments:
  85. string - name of the event to register
  86. [optional] string or function - name of the method or function to call. Default: same name as "event".
  87. [optional] boolean - whether to have method called only once. Default: false
  88. ------------------------------------------------------------------------------------]]
  89. function AceEvent:RegisterEvent(event, method, once)
  90. AceEvent:argCheck(event, 2, "string")
  91. if self == AceEvent and not registeringFromAceEvent then
  92. AceEvent:argCheck(method, 3, "function")
  93. self = method
  94. else
  95. AceEvent:argCheck(method, 3, "string", "function", "nil", "boolean", "number")
  96. if type(method) == "boolean" or type(method) == "number" then
  97. AceEvent:argCheck(once, 4, "nil")
  98. once, method = method, event
  99. end
  100. end
  101. AceEvent:argCheck(once, 4, "number", "boolean", "nil")
  102. if eventsWhichHappenOnce[event] then
  103. once = true
  104. end
  105. local throttleRate
  106. if type(once) == "number" then
  107. throttleRate, once = once
  108. end
  109. if not method then
  110. method = event
  111. end
  112. if type(method) == "string" and type(self[method]) ~= "function" then
  113. AceEvent:error("Cannot register event %q to method %q, it does not exist", event, method)
  114. else
  115. assert(type(method) == "function" or type(method) == "string")
  116. end
  117. local AceEvent_registry = AceEvent.registry
  118. if not AceEvent_registry[event] then
  119. AceEvent_registry[event] = new()
  120. AceEvent.frame:RegisterEvent(event)
  121. end
  122. local remember = true
  123. if AceEvent_registry[event][self] then
  124. remember = false
  125. end
  126. AceEvent_registry[event][self] = method
  127. local AceEvent_onceRegistry = AceEvent.onceRegistry
  128. if once then
  129. if not AceEvent_onceRegistry then
  130. AceEvent.onceRegistry = {}
  131. AceEvent_onceRegistry = AceEvent.onceRegistry
  132. end
  133. if not AceEvent_onceRegistry[event] then
  134. AceEvent_onceRegistry[event] = new()
  135. end
  136. AceEvent_onceRegistry[event][self] = true
  137. else
  138. if AceEvent_onceRegistry and AceEvent_onceRegistry[event] then
  139. AceEvent_onceRegistry[event][self] = nil
  140. if not next(AceEvent_onceRegistry[event]) then
  141. AceEvent_onceRegistry[event] = del(AceEvent_onceRegistry[event])
  142. end
  143. end
  144. end
  145. local AceEvent_throttleRegistry = AceEvent.throttleRegistry
  146. if throttleRate then
  147. if not AceEvent_throttleRegistry then
  148. AceEvent.throttleRegistry = {}
  149. AceEvent_throttleRegistry = AceEvent.throttleRegistry
  150. end
  151. if not AceEvent_throttleRegistry[event] then
  152. AceEvent_throttleRegistry[event] = new()
  153. end
  154. if AceEvent_throttleRegistry[event][self] then
  155. AceEvent_throttleRegistry[event][self] = nil
  156. end
  157. AceEvent_throttleRegistry[event][self] = setmetatable(new(), weakKey)
  158. local t = AceEvent_throttleRegistry[event][self]
  159. t[RATE] = throttleRate
  160. else
  161. if AceEvent_throttleRegistry and AceEvent_throttleRegistry[event] then
  162. if AceEvent_throttleRegistry[event][self] then
  163. AceEvent_throttleRegistry[event][self] = nil
  164. end
  165. if not next(AceEvent_throttleRegistry[event]) then
  166. AceEvent_throttleRegistry[event] = del(AceEvent_throttleRegistry[event])
  167. end
  168. end
  169. end
  170. if remember then
  171. AceEvent:TriggerEvent("AceEvent_EventRegistered", self, event)
  172. end
  173. end
  174. local ALL_EVENTS
  175. --[[----------------------------------------------------------------------------------
  176. Notes:
  177. * Registers all events to the given method
  178. * To access the current event, check AceEvent.currentEvent
  179. * To access the current event's unique identifier, check AceEvent.currentEventUID
  180. * This is only for debugging purposes.
  181. Arguments:
  182. [optional] string or function - name of the method or function to call. Default: same name as "event".
  183. ------------------------------------------------------------------------------------]]
  184. function AceEvent:RegisterAllEvents(method)
  185. if self == AceEvent then
  186. AceEvent:argCheck(method, 1, "function")
  187. self = method
  188. else
  189. AceEvent:argCheck(method, 1, "string", "function")
  190. if type(method) == "string" and type(self[method]) ~= "function" then
  191. AceEvent:error("Cannot register all events to method %q, it does not exist", method)
  192. end
  193. end
  194. local AceEvent_registry = AceEvent.registry
  195. if not AceEvent_registry[ALL_EVENTS] then
  196. AceEvent_registry[ALL_EVENTS] = new()
  197. AceEvent.frame:RegisterAllEvents()
  198. end
  199. local remember = not AceEvent_registry[ALL_EVENTS][self]
  200. AceEvent_registry[ALL_EVENTS][self] = method
  201. if remember then
  202. AceEvent:TriggerEvent("AceEvent_EventRegistered", self, "all")
  203. end
  204. end
  205. --[[----------------------------------------------------------------------------------
  206. Notes:
  207. * Trigger a custom AceEvent.
  208. * This should never be called to simulate fake Blizzard events.
  209. * Custom events should be in the form of AddonName_SpecificEvent
  210. Arguments:
  211. string - name of the event
  212. tuple - list of arguments to pass along
  213. ------------------------------------------------------------------------------------]]
  214. function AceEvent:TriggerEvent(event, ...)
  215. AceEvent:argCheck(event, 2, "string")
  216. local AceEvent_registry = AceEvent.registry
  217. if (not AceEvent_registry[event] or not next(AceEvent_registry[event])) and (not AceEvent_registry[ALL_EVENTS] or not next(AceEvent_registry[ALL_EVENTS])) then
  218. return
  219. end
  220. local lastEvent = AceEvent.currentEvent
  221. AceEvent.currentEvent = event
  222. local lastEventUID = AceEvent.currentEventUID
  223. local uid = AceEvent.UID_NUM + 1
  224. AceEvent.UID_NUM = uid
  225. AceEvent.currentEventUID = uid
  226. local tmp = new()
  227. local AceEvent_onceRegistry = AceEvent.onceRegistry
  228. if AceEvent_onceRegistry and AceEvent_onceRegistry[event] then
  229. for obj, method in pairs(AceEvent_onceRegistry[event]) do
  230. tmp[obj] = AceEvent_registry[event] and AceEvent_registry[event][obj] or nil
  231. end
  232. local obj = next(tmp)
  233. while obj do
  234. local method = tmp[obj]
  235. AceEvent.UnregisterEvent(obj, event)
  236. if type(method) == "string" then
  237. local obj_method = obj[method]
  238. if obj_method then
  239. local success, err = pcall(obj_method, obj, ...)
  240. if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("(.-: )in.-\n") or "") .. err) end
  241. end
  242. elseif method then -- function
  243. local success, err = pcall(method, ...)
  244. if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("(.-: )in.-\n") or "") .. err) end
  245. end
  246. tmp[obj] = nil
  247. obj = next(tmp)
  248. end
  249. end
  250. local AceEvent_throttleRegistry = AceEvent.throttleRegistry
  251. local throttleTable = AceEvent_throttleRegistry and AceEvent_throttleRegistry[event]
  252. if AceEvent_registry[event] then
  253. for obj, method in pairs(AceEvent_registry[event]) do
  254. tmp[obj] = method
  255. end
  256. local obj = next(tmp)
  257. while obj do
  258. local cont = nil
  259. if throttleTable and throttleTable[obj] then
  260. local a1 = ...
  261. if a1 == nil then
  262. a1 = FAKE_NIL
  263. end
  264. if not throttleTable[obj][a1] or GetTime() - throttleTable[obj][a1] >= throttleTable[obj][RATE] then
  265. throttleTable[obj][a1] = GetTime()
  266. else
  267. cont = true
  268. end
  269. end
  270. if not cont then
  271. local method = tmp[obj]
  272. local t = type(method)
  273. if t == "string" then
  274. local obj_method = obj[method]
  275. if obj_method then
  276. local success, err = pcall(obj_method, obj, ...)
  277. if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("(.-: )in.-\n") or "") .. err) end
  278. end
  279. elseif t == "function" then -- function
  280. local success, err = pcall(method, ...)
  281. if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("(.-: )in.-\n") or "") .. err) end
  282. else
  283. AceEvent:error("Cannot trigger event %q. %q's handler, %q, is not a method or function (%s).", event, obj, method, t)
  284. end
  285. end
  286. tmp[obj] = nil
  287. obj = next(tmp)
  288. end
  289. end
  290. if AceEvent_registry[ALL_EVENTS] then
  291. for obj, method in pairs(AceEvent_registry[ALL_EVENTS]) do
  292. tmp[obj] = method
  293. end
  294. local obj = next(tmp)
  295. while obj do
  296. local method = tmp[obj]
  297. local t = type(method)
  298. if t == "string" then
  299. local obj_method = obj[method]
  300. if obj_method then
  301. local success, err = pcall(obj_method, obj, ...)
  302. if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("(.-: )in.-\n") or "") .. err) end
  303. end
  304. elseif t == "function" then
  305. local success, err = pcall(method, ...)
  306. if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("(.-: )in.-\n") or "") .. err) end
  307. else
  308. AceEvent:error("Cannot trigger event %q. %q's handler, %q, is not a method or function (%s).", event, obj, method, t)
  309. end
  310. tmp[obj] = nil
  311. obj = next(tmp)
  312. end
  313. end
  314. tmp = del(tmp)
  315. AceEvent.currentEvent = lastEvent
  316. AceEvent.currentEventUID = lastEventUID
  317. end
  318. local delayRegistry
  319. local OnUpdate
  320. do
  321. local tmp = {}
  322. OnUpdate = function()
  323. local t = GetTime()
  324. for k,v in pairs(delayRegistry) do
  325. tmp[k] = true
  326. end
  327. for k in pairs(tmp) do
  328. local v = delayRegistry[k]
  329. if v then
  330. local v_time = v.time
  331. if not v_time then
  332. delayRegistry[k] = nil
  333. elseif v_time <= t then
  334. local v_repeatDelay = v.repeatDelay
  335. if v_repeatDelay then
  336. -- use the event time, not the current time, else timing inaccuracies add up over time
  337. v.time = v_time + v_repeatDelay
  338. end
  339. local event = v.event
  340. local t = type(event)
  341. if t == "function" then
  342. local uid = AceEvent.UID_NUM + 1
  343. AceEvent.UID_NUM = uid
  344. AceEvent.currentEventUID = uid
  345. local success, err = pcall(event, unpack(v, 1, v.n))
  346. if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("(.-: )in.-\n") or "") .. err) end
  347. AceEvent.currentEventUID = nil
  348. elseif t == "string" then
  349. AceEvent:TriggerEvent(event, unpack(v, 1, v.n))
  350. else
  351. AceEvent:error("Cannot trigger event %q, it's not a method or function (%s).", event, t)
  352. end
  353. if not v_repeatDelay then
  354. local x = delayRegistry[k]
  355. if x and x.time == v_time then -- check if it was manually reset
  356. if type(k) == "string" then
  357. del(delayRegistry[k])
  358. end
  359. delayRegistry[k] = nil
  360. end
  361. end
  362. end
  363. end
  364. end
  365. for k in pairs(tmp) do
  366. tmp[k] = nil
  367. end
  368. if not next(delayRegistry) then
  369. AceEvent.frame:Hide()
  370. end
  371. end
  372. end
  373. local function ScheduleEvent(self, repeating, event, delay, ...)
  374. local id
  375. if type(event) == "string" and type(delay) ~= "number" then
  376. id, event, delay = event, delay, ...
  377. AceEvent:argCheck(event, 3, "string", "function", --[[ so message is right ]] "number")
  378. AceEvent:argCheck(delay, 4, "number")
  379. self:CancelScheduledEvent(id)
  380. else
  381. AceEvent:argCheck(event, 2, "string", "function")
  382. AceEvent:argCheck(delay, 3, "number")
  383. end
  384. if not delayRegistry then
  385. AceEvent.delayRegistry = {}
  386. delayRegistry = AceEvent.delayRegistry
  387. AceEvent.frame:SetScript("OnUpdate", OnUpdate)
  388. end
  389. local t
  390. if id then
  391. t = new(select(2, ...))
  392. t.n = select('#', ...) - 1
  393. else
  394. t = new(...)
  395. t.n = select('#', ...)
  396. end
  397. t.event = event
  398. t.time = GetTime() + delay
  399. t.self = self
  400. t.id = id or t
  401. t.repeatDelay = repeating and delay
  402. delayRegistry[t.id] = t
  403. AceEvent.frame:Show()
  404. end
  405. --[[----------------------------------------------------------------------------------
  406. Notes:
  407. * Schedule an event to fire.
  408. * To fire on the next frame, specify a delay of 0.
  409. Arguments:
  410. string or function - name of the event to fire, or a function to call.
  411. number - the amount of time to wait until calling.
  412. tuple - a list of arguments to pass along.
  413. ------------------------------------------------------------------------------------]]
  414. function AceEvent:ScheduleEvent(event, delay, ...)
  415. if type(event) == "string" and type(delay) ~= "number" then
  416. AceEvent:argCheck(delay, 3, "string", "function", --[[ so message is right ]] "number")
  417. AceEvent:argCheck(..., 4, "number")
  418. else
  419. AceEvent:argCheck(event, 2, "string", "function")
  420. AceEvent:argCheck(delay, 3, "number")
  421. end
  422. return ScheduleEvent(self, false, event, delay, ...)
  423. end
  424. function AceEvent:ScheduleRepeatingEvent(event, delay, ...)
  425. if type(event) == "string" and type(delay) ~= "number" then
  426. AceEvent:argCheck(delay, 3, "string", "function", --[[ so message is right ]] "number")
  427. AceEvent:argCheck(..., 4, "number")
  428. else
  429. AceEvent:argCheck(event, 2, "string", "function")
  430. AceEvent:argCheck(delay, 3, "number")
  431. end
  432. return ScheduleEvent(self, true, event, delay, ...)
  433. end
  434. function AceEvent:CancelScheduledEvent(t)
  435. AceEvent:argCheck(t, 2, "string")
  436. if delayRegistry then
  437. local v = delayRegistry[t]
  438. if v then
  439. if type(t) == "string" then
  440. del(delayRegistry[t])
  441. end
  442. delayRegistry[t] = nil
  443. if not next(delayRegistry) then
  444. AceEvent.frame:Hide()
  445. end
  446. return true
  447. end
  448. end
  449. return false
  450. end
  451. function AceEvent:IsEventScheduled(t)
  452. AceEvent:argCheck(t, 2, "string")
  453. if delayRegistry then
  454. local v = delayRegistry[t]
  455. if v then
  456. return true, v.time - GetTime()
  457. end
  458. end
  459. return false, nil
  460. end
  461. function AceEvent:UnregisterEvent(event)
  462. AceEvent:argCheck(event, 2, "string")
  463. local AceEvent_registry = AceEvent.registry
  464. if AceEvent_registry[event] and AceEvent_registry[event][self] then
  465. AceEvent_registry[event][self] = nil
  466. local AceEvent_onceRegistry = AceEvent.onceRegistry
  467. if AceEvent_onceRegistry and AceEvent_onceRegistry[event] and AceEvent_onceRegistry[event][self] then
  468. AceEvent_onceRegistry[event][self] = nil
  469. if not next(AceEvent_onceRegistry[event]) then
  470. AceEvent_onceRegistry[event] = del(AceEvent_onceRegistry[event])
  471. end
  472. end
  473. local AceEvent_throttleRegistry = AceEvent.throttleRegistry
  474. if AceEvent_throttleRegistry and AceEvent_throttleRegistry[event] and AceEvent_throttleRegistry[event][self] then
  475. AceEvent_throttleRegistry[event][self] = nil
  476. if not next(AceEvent_throttleRegistry[event]) then
  477. AceEvent_throttleRegistry[event] = del(AceEvent_throttleRegistry[event])
  478. end
  479. end
  480. if not next(AceEvent_registry[event]) then
  481. AceEvent_registry[event] = del(AceEvent_registry[event])
  482. if not AceEvent_registry[ALL_EVENTS] or not next(AceEvent_registry[ALL_EVENTS]) then
  483. AceEvent.frame:UnregisterEvent(event)
  484. end
  485. end
  486. else
  487. if self == AceEvent then
  488. error(("Cannot unregister event %q. Improperly unregistering from AceEvent-2.0."):format(event), 2)
  489. else
  490. AceEvent:error("Cannot unregister event %q. %q is not registered with it.", event, self)
  491. end
  492. end
  493. AceEvent:TriggerEvent("AceEvent_EventUnregistered", self, event)
  494. end
  495. function AceEvent:UnregisterAllEvents()
  496. local AceEvent_registry = AceEvent.registry
  497. if AceEvent_registry[ALL_EVENTS] and AceEvent_registry[ALL_EVENTS][self] then
  498. AceEvent_registry[ALL_EVENTS][self] = nil
  499. if not next(AceEvent_registry[ALL_EVENTS]) then
  500. AceEvent_registry[ALL_EVENTS] = del(AceEvent_registry[ALL_EVENTS])
  501. AceEvent.frame:UnregisterAllEvents()
  502. for k,v in pairs(AceEvent_registry) do
  503. AceEvent.frame:RegisterEvent(k)
  504. end
  505. end
  506. end
  507. if AceEvent_registry.AceEvent_EventUnregistered then
  508. local event, data = "AceEvent_EventUnregistered", AceEvent_registry.AceEvent_EventUnregistered
  509. local x = data[self]
  510. data[self] = nil
  511. if x then
  512. if not next(data) then
  513. if not AceEvent_registry[ALL_EVENTS] then
  514. AceEvent.frame:UnregisterEvent(event)
  515. end
  516. AceEvent_registry[event] = del(AceEvent_registry[event])
  517. end
  518. AceEvent:TriggerEvent("AceEvent_EventUnregistered", self, event)
  519. end
  520. end
  521. for event, data in pairs(AceEvent_registry) do
  522. local x = data[self]
  523. data[self] = nil
  524. if x and event ~= ALL_EVENTS then
  525. if not next(data) then
  526. if not AceEvent_registry[ALL_EVENTS] then
  527. AceEvent.frame:UnregisterEvent(event)
  528. end
  529. AceEvent_registry[event] = del(AceEvent_registry[event])
  530. end
  531. AceEvent:TriggerEvent("AceEvent_EventUnregistered", self, event)
  532. end
  533. end
  534. if AceEvent.onceRegistry then
  535. for event, data in pairs(AceEvent.onceRegistry) do
  536. data[self] = nil
  537. end
  538. end
  539. end
  540. function AceEvent:CancelAllScheduledEvents()
  541. if delayRegistry then
  542. for k,v in pairs(delayRegistry) do
  543. if v.self == self then
  544. if type(k) == "string" then
  545. del(delayRegistry[k])
  546. end
  547. delayRegistry[k] = nil
  548. end
  549. end
  550. if not next(delayRegistry) then
  551. AceEvent.frame:Hide()
  552. end
  553. end
  554. end
  555. function AceEvent:IsEventRegistered(event)
  556. AceEvent:argCheck(event, 2, "string")
  557. local AceEvent_registry = AceEvent.registry
  558. if self == AceEvent then
  559. return AceEvent_registry[event] and next(AceEvent_registry[event]) or AceEvent_registry[ALL_EVENTS] and next(AceEvent_registry[ALL_EVENTS]) and true or false
  560. end
  561. if AceEvent_registry[event] and AceEvent_registry[event][self] then
  562. return true, AceEvent_registry[event][self]
  563. end
  564. if AceEvent_registry[ALL_EVENTS] and AceEvent_registry[ALL_EVENTS][self] then
  565. return true, AceEvent_registry[ALL_EVENTS][self]
  566. end
  567. return false, nil
  568. end
  569. local UnitExists = UnitExists
  570. local bucketfunc
  571. function AceEvent:RegisterBucketEvent(event, delay, method, ...)
  572. AceEvent:argCheck(event, 2, "string", "table")
  573. if type(event) == "table" then
  574. for k,v in pairs(event) do
  575. if type(k) ~= "number" then
  576. AceEvent:error("All keys to argument #2 to `RegisterBucketEvent' must be numbers.")
  577. elseif type(v) ~= "string" then
  578. AceEvent:error("All values to argument #2 to `RegisterBucketEvent' must be strings.")
  579. end
  580. end
  581. end
  582. AceEvent:argCheck(delay, 3, "number")
  583. if AceEvent == self then
  584. AceEvent:argCheck(method, 4, "function")
  585. self = method
  586. else
  587. if type(event) == "string" then
  588. AceEvent:argCheck(method, 4, "string", "function", "nil")
  589. if not method then
  590. method = event
  591. end
  592. else
  593. AceEvent:argCheck(method, 4, "string", "function")
  594. end
  595. if type(method) == "string" and type(self[method]) ~= "function" then
  596. AceEvent:error("Cannot register event %q to method %q, it does not exist", event, method)
  597. end
  598. end
  599. local buckets = AceEvent.buckets
  600. if not buckets[event] then
  601. buckets[event] = new()
  602. end
  603. if not buckets[event][self] then
  604. local t = {}
  605. t.current = {}
  606. t.self = self
  607. buckets[event][self] = t
  608. else
  609. AceEvent.CancelScheduledEvent(self, buckets[event][self].id)
  610. end
  611. local bucket = buckets[event][self]
  612. bucket.method = method
  613. local n = select('#', ...)
  614. if n > 0 then
  615. for i = 1, n do
  616. bucket[i] = select(i, ...)
  617. end
  618. end
  619. bucket.n = n
  620. local func = function(arg1)
  621. bucket.run = true
  622. if arg1 then
  623. bucket.current[arg1] = true
  624. end
  625. end
  626. buckets[event][self].func = func
  627. local isUnitBucket = true
  628. if type(event) == "string" then
  629. AceEvent.RegisterEvent(self, event, func)
  630. if not event:find("^UNIT_") then
  631. isUnitBucket = nil
  632. end
  633. else
  634. for _,v in ipairs(event) do
  635. AceEvent.RegisterEvent(self, v, func)
  636. if isUnitBucket and not v:find("^UNIT_") then
  637. isUnitBucket = nil
  638. end
  639. end
  640. end
  641. bucket.unit = isUnitBucket
  642. if not bucketfunc then
  643. bucketfunc = function(bucket)
  644. if bucket.run then
  645. local current = bucket.current
  646. local method = bucket.method
  647. local self = bucket.self
  648. if bucket.unit then
  649. for unit in pairs(current) do
  650. if not UnitExists(unit) then
  651. current[unit] = nil
  652. end
  653. end
  654. end
  655. if type(method) == "string" then
  656. self[method](self, current, unpack(bucket, 1, bucket.n))
  657. elseif method then -- function
  658. method(current, unpack(bucket, 1, bucket.n))
  659. end
  660. for k in pairs(current) do
  661. current[k] = nil
  662. k = nil
  663. end
  664. bucket.run = nil
  665. end
  666. end
  667. end
  668. bucket.id = "AceEvent-Bucket-" .. tostring(bucket)
  669. AceEvent.ScheduleRepeatingEvent(self, bucket.id, bucketfunc, delay, bucket)
  670. end
  671. function AceEvent:IsBucketEventRegistered(event)
  672. AceEvent:argCheck(event, 2, "string", "table")
  673. return AceEvent.buckets and AceEvent.buckets[event] and AceEvent.buckets[event][self]
  674. end
  675. function AceEvent:UnregisterBucketEvent(event)
  676. AceEvent:argCheck(event, 2, "string", "table")
  677. if not AceEvent.buckets or not AceEvent.buckets[event] or not AceEvent.buckets[event][self] then
  678. AceEvent:error("Cannot unregister bucket event %q. %q is not registered with it.", event, self)
  679. end
  680. local bucket = AceEvent.buckets[event][self]
  681. if type(event) == "string" then
  682. AceEvent.UnregisterEvent(self, event)
  683. else
  684. for _,v in ipairs(event) do
  685. AceEvent.UnregisterEvent(self, v)
  686. end
  687. end
  688. AceEvent:CancelScheduledEvent(bucket.id)
  689. bucket.current = nil
  690. AceEvent.buckets[event][self] = nil
  691. if not next(AceEvent.buckets[event]) then
  692. AceEvent.buckets[event] = del(AceEvent.buckets[event])
  693. end
  694. end
  695. function AceEvent:UnregisterAllBucketEvents()
  696. if not AceEvent.buckets or not next(AceEvent.buckets) then
  697. return
  698. end
  699. for k,v in pairs(AceEvent.buckets) do
  700. if v == self then
  701. AceEvent.UnregisterBucketEvent(self, k)
  702. k = nil
  703. end
  704. end
  705. end
  706. local combatSchedules
  707. function AceEvent:CancelAllCombatSchedules()
  708. local i = 0
  709. while true do
  710. i = i + 1
  711. if not combatSchedules[i] then
  712. break
  713. end
  714. local v = combatSchedules[i]
  715. if v.self == self then
  716. v = del(v)
  717. table.remove(combatSchedules, i)
  718. i = i - 1
  719. end
  720. end
  721. end
  722. local inCombat = false
  723. function AceEvent:PLAYER_REGEN_DISABLED()
  724. inCombat = true
  725. end
  726. do
  727. local tmp = {}
  728. function AceEvent:PLAYER_REGEN_ENABLED()
  729. inCombat = false
  730. for i, v in ipairs(combatSchedules) do
  731. tmp[i] = v
  732. combatSchedules[i] = nil
  733. end
  734. for i, v in ipairs(tmp) do
  735. local func = v.func
  736. if func then
  737. local success, err = pcall(func, unpack(v, 1, v.n))
  738. if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("(.-: )in.-\n") or "") .. err) end
  739. else
  740. local obj = v.obj or v.self
  741. local method = v.method
  742. local obj_method = obj[method]
  743. if obj_method then
  744. local success, err = pcall(obj_method, obj, unpack(v, 1, v.n))
  745. if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("(.-: )in.-\n") or "") .. err) end
  746. end
  747. end
  748. tmp[i] = del(v)
  749. end
  750. end
  751. end
  752. function AceEvent:ScheduleLeaveCombatAction(method, ...)
  753. local style = type(method)
  754. if self == AceEvent then
  755. if style == "table" then
  756. local func = (...)
  757. AceEvent:argCheck(func, 3, "string")
  758. if type(method[func]) ~= "function" then
  759. AceEvent:error("Cannot schedule a combat action to method %q, it does not exist", func)
  760. end
  761. else
  762. AceEvent:argCheck(method, 2, "function", --[[so message is right]] "table")
  763. end
  764. self = method
  765. else
  766. AceEvent:argCheck(method, 2, "function", "string", "table")
  767. if style == "string" and type(self[method]) ~= "function" then
  768. AceEvent:error("Cannot schedule a combat action to method %q, it does not exist", method)
  769. elseif style == "table" then
  770. local func = (...)
  771. AceEvent:argCheck(func, 3, "string")
  772. if type(method[func]) ~= "function" then
  773. AceEvent:error("Cannot schedule a combat action to method %q, it does not exist", func)
  774. end
  775. end
  776. end
  777. if not inCombat then
  778. local success, err
  779. if type(method) == "function" then
  780. success, err = pcall(method, ...)
  781. elseif type(method) == "table" then
  782. local func = (...)
  783. success, err = pcall(method[func], method, select(2, ...))
  784. else
  785. success, err = pcall(self[method], self, ...)
  786. end
  787. if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("(.-: )in.-\n") or "") .. err) end
  788. return
  789. end
  790. local t
  791. local n = select('#', ...)
  792. if style == "table" then
  793. t = new(select(2, ...))
  794. t.obj = method
  795. t.method = (...)
  796. t.n = n-1
  797. else
  798. t = new(...)
  799. t.n = n
  800. if style == "function" then
  801. t.func = method
  802. else
  803. t.method = method
  804. end
  805. end
  806. t.self = self
  807. table.insert(combatSchedules, t)
  808. end
  809. function AceEvent:OnEmbedDisable(target)
  810. self.UnregisterAllEvents(target)
  811. self.CancelAllScheduledEvents(target)
  812. self.UnregisterAllBucketEvents(target)
  813. self.CancelAllCombatSchedules(target)
  814. end
  815. function AceEvent:IsFullyInitialized()
  816. return self.postInit or false
  817. end
  818. local function activate(self, oldLib, oldDeactivate)
  819. AceEvent = self
  820. self.onceRegistry = oldLib and oldLib.onceRegistry or {}
  821. self.throttleRegistry = oldLib and oldLib.throttleRegistry or {}
  822. self.delayRegistry = oldLib and oldLib.delayRegistry or {}
  823. self.buckets = oldLib and oldLib.buckets or {}
  824. self.registry = oldLib and oldLib.registry or {}
  825. self.frame = oldLib and oldLib.frame or CreateFrame("Frame", "AceEvent20Frame")
  826. self.playerLogin = IsLoggedIn() and true
  827. self.postInit = oldLib and oldLib.postInit or self.playerLogin and ChatTypeInfo and ChatTypeInfo.WHISPER and ChatTypeInfo.WHISPER.r and true
  828. self.ALL_EVENTS = oldLib and oldLib.ALL_EVENTS or _G.newproxy()
  829. self.FAKE_NIL = oldLib and oldLib.FAKE_NIL or _G.newproxy()
  830. self.RATE = oldLib and oldLib.RATE or _G.newproxy()
  831. self.combatSchedules = oldLib and oldLib.combatSchedules or {}
  832. self.UID_NUM = oldLib and oldLib.UID_NUM or 0
  833. combatSchedules = self.combatSchedules
  834. ALL_EVENTS = self.ALL_EVENTS
  835. FAKE_NIL = self.FAKE_NIL
  836. RATE = self.RATE
  837. local inPlw = false
  838. local blacklist = {
  839. UNIT_INVENTORY_CHANGED = true,
  840. BAG_UPDATE = true,
  841. ITEM_LOCK_CHANGED = true,
  842. ACTIONBAR_SLOT_CHANGED = true,
  843. }
  844. self.frame:SetScript("OnEvent", function(_, event, ...)
  845. if event == "PLAYER_ENTERING_WORLD" then
  846. inPlw = false
  847. elseif event == "PLAYER_LEAVING_WORLD" then
  848. inPlw = true
  849. end
  850. if event and (not inPlw or not blacklist[event]) then
  851. self:TriggerEvent(event, ...)
  852. end
  853. end)
  854. if self.delayRegistry then
  855. delayRegistry = self.delayRegistry
  856. self.frame:SetScript("OnUpdate", OnUpdate)
  857. end
  858. self:UnregisterAllEvents()
  859. self:CancelAllScheduledEvents()
  860. local function handleFullInit()
  861. if not self.postInit then
  862. local function func()
  863. self.postInit = true
  864. self:TriggerEvent("AceEvent_FullyInitialized")
  865. if self.registry["CHAT_MSG_CHANNEL_NOTICE"] and self.registry["CHAT_MSG_CHANNEL_NOTICE"][self] then
  866. self:UnregisterEvent("CHAT_MSG_CHANNEL_NOTICE")
  867. end
  868. if self.registry["MEETINGSTONE_CHANGED"] and self.registry["MEETINGSTONE_CHANGED"][self] then
  869. self:UnregisterEvent("MEETINGSTONE_CHANGED")
  870. end
  871. end
  872. registeringFromAceEvent = true
  873. self:RegisterEvent("MEETINGSTONE_CHANGED", func, true)
  874. self:RegisterEvent("CHAT_MSG_CHANNEL_NOTICE", func, true)
  875. self:ScheduleEvent("AceEvent_FullyInitialized", func, 10)
  876. registeringFromAceEvent = nil
  877. end
  878. end
  879. if not self.playerLogin then
  880. registeringFromAceEvent = true
  881. self:RegisterEvent("PLAYER_LOGIN", function()
  882. self.playerLogin = true
  883. handleFullInit()
  884. handleFullInit = nil
  885. end, true)
  886. registeringFromAceEvent = nil
  887. else
  888. handleFullInit()
  889. handleFullInit = nil
  890. end
  891. if not AceEvent20EditBox then
  892. CreateFrame("Editbox", "AceEvent20EditBox")
  893. end
  894. local editbox = AceEvent20EditBox
  895. function editbox:Execute(line)
  896. local defaulteditbox = DEFAULT_CHAT_FRAME.editBox
  897. self:SetAttribute("chatType", defaulteditbox:GetAttribute("chatType"))
  898. self:SetAttribute("tellTarget", defaulteditbox:GetAttribute("tellTarget"))
  899. self:SetAttribute("channelTarget", defaulteditbox:GetAttribute("channelTarget"))
  900. self:SetText(line)
  901. ChatEdit_SendText(self)
  902. end
  903. editbox:Hide()
  904. _G["SLASH_IN1"] = "/in"
  905. SlashCmdList["IN"] = function(msg)
  906. local seconds, command, rest = msg:match("^([^%s]+)%s+(/[^%s]+)(.*)$")
  907. seconds = tonumber(seconds)
  908. if not seconds then
  909. DEFAULT_CHAT_FRAME:AddMessage("Error, bad arguments to /in. Must be in the form of `/in 5 /say hi'")
  910. return
  911. end
  912. if IsSecureCmd(command) then
  913. DEFAULT_CHAT_FRAME:AddMessage(("Error, /in cannot call secure command: %s"):format(command))
  914. return
  915. end
  916. self:ScheduleEvent("AceEventSlashIn-" .. math.random(1, 1000000000), editbox.Execute, seconds, editbox, command .. rest)
  917. end
  918. registeringFromAceEvent = true
  919. self:RegisterEvent("PLAYER_REGEN_ENABLED")
  920. self:RegisterEvent("PLAYER_REGEN_DISABLED")
  921. self:RegisterEvent("LOOT_OPENED", function()
  922. SendAddonMessage("LOOT_OPENED", "", "RAID")
  923. end)
  924. inCombat = InCombatLockdown()
  925. registeringFromAceEvent = nil
  926. self:activate(oldLib, oldDeactivate)
  927. if oldLib then
  928. oldDeactivate(oldLib)
  929. end
  930. end
  931. AceLibrary:Register(AceEvent, MAJOR_VERSION, MINOR_VERSION, activate)