🐳 chore(工具): 增加 全局事件 和 事件对象基础类
parent
2ebfd2654c
commit
b7815395e8
@ -1,221 +0,0 @@
|
|||||||
------------------------------------------------------------------------------
|
|
||||||
-- https://github.com/simenkid/lua-events
|
|
||||||
------------------------------------------------------------------------------
|
|
||||||
local PFX = '__lsn_'
|
|
||||||
local PFX_LEN = #PFX
|
|
||||||
local Events = {
|
|
||||||
defaultMaxListeners = 10,
|
|
||||||
}
|
|
||||||
|
|
||||||
setmetatable(Events, {
|
|
||||||
__call = function(_, ...)
|
|
||||||
return Events:new(...)
|
|
||||||
end,
|
|
||||||
})
|
|
||||||
|
|
||||||
local function rmEntry(tbl, pred)
|
|
||||||
local x, len = 0, #tbl
|
|
||||||
for i = 1, len do
|
|
||||||
local trusy, idx = false, (i - x)
|
|
||||||
if (type(pred) == 'function') then
|
|
||||||
trusy = pred(tbl[idx])
|
|
||||||
else
|
|
||||||
trusy = tbl[idx] == pred
|
|
||||||
end
|
|
||||||
|
|
||||||
if (tbl[idx] ~= nil and trusy) then
|
|
||||||
tbl[idx] = nil
|
|
||||||
table.remove(tbl, idx)
|
|
||||||
x = x + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return tbl
|
|
||||||
end
|
|
||||||
|
|
||||||
function Events:new(obj)
|
|
||||||
obj = obj or {}
|
|
||||||
self.__index = self
|
|
||||||
setmetatable(obj, self)
|
|
||||||
obj._on = {}
|
|
||||||
|
|
||||||
return obj
|
|
||||||
end
|
|
||||||
|
|
||||||
function Events:evTable(ev)
|
|
||||||
if (type(self._on[ev]) ~= 'table') then
|
|
||||||
self._on[ev] = {}
|
|
||||||
end
|
|
||||||
return self._on[ev]
|
|
||||||
end
|
|
||||||
|
|
||||||
function Events:getEvTable(ev)
|
|
||||||
return self._on[ev]
|
|
||||||
end
|
|
||||||
|
|
||||||
-- ************************************************************************ --
|
|
||||||
-- ** Public APIs * --
|
|
||||||
-- ************************************************************************ --
|
|
||||||
function Events:addListener(ev, listener)
|
|
||||||
local pfx_ev = PFX .. tostring(ev)
|
|
||||||
local evtbl = self:evTable(pfx_ev)
|
|
||||||
local maxLsnNum = self.currentMaxListeners or self.defaultMaxListeners
|
|
||||||
local lsnNum = self:listenerCount(ev)
|
|
||||||
table.insert(evtbl, listener)
|
|
||||||
|
|
||||||
if (lsnNum > maxLsnNum) then
|
|
||||||
print('WARN: Number of ' .. string.sub(pfx_ev, PFX_LEN + 1) .. " event listeners: " .. tostring(lsnNum))
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
function Events:emit(ev, ...)
|
|
||||||
local pfx_ev = PFX .. tostring(ev)
|
|
||||||
local evtbl = self:getEvTable(pfx_ev)
|
|
||||||
if (evtbl ~= nil) then
|
|
||||||
for _, lsn in ipairs(evtbl) do
|
|
||||||
local status, err = pcall(lsn, ...)
|
|
||||||
if not (status) then
|
|
||||||
print(string.sub(_, PFX_LEN + 1) .. " emit error: " .. tostring(err))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- one-time listener
|
|
||||||
pfx_ev = pfx_ev .. ':once'
|
|
||||||
evtbl = self:getEvTable(pfx_ev)
|
|
||||||
|
|
||||||
if (evtbl ~= nil) then
|
|
||||||
for _, lsn in ipairs(evtbl) do
|
|
||||||
local status, err = pcall(lsn, ...)
|
|
||||||
if not (status) then
|
|
||||||
print(string.sub(_, PFX_LEN + 1) .. " emit error: " .. tostring(err))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
rmEntry(evtbl, function(v)
|
|
||||||
return v ~= nil
|
|
||||||
end)
|
|
||||||
self._on[pfx_ev] = nil
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
function Events:getMaxListeners()
|
|
||||||
return self.currentMaxListeners or self.defaultMaxListeners
|
|
||||||
end
|
|
||||||
|
|
||||||
function Events:listenerCount(ev)
|
|
||||||
local totalNum = 0
|
|
||||||
local pfx_ev = PFX .. tostring(ev)
|
|
||||||
local evtbl = self:getEvTable(pfx_ev)
|
|
||||||
|
|
||||||
if (evtbl ~= nil) then
|
|
||||||
totalNum = totalNum + #evtbl
|
|
||||||
end
|
|
||||||
|
|
||||||
pfx_ev = pfx_ev .. ':once'
|
|
||||||
evtbl = self:getEvTable(pfx_ev)
|
|
||||||
|
|
||||||
if (evtbl ~= nil) then
|
|
||||||
totalNum = totalNum + #evtbl
|
|
||||||
end
|
|
||||||
|
|
||||||
return totalNum
|
|
||||||
end
|
|
||||||
|
|
||||||
function Events:listeners(ev)
|
|
||||||
local pfx_ev = PFX .. tostring(ev)
|
|
||||||
local evtbl = self:getEvTable(pfx_ev)
|
|
||||||
local clone = {}
|
|
||||||
|
|
||||||
if (evtbl ~= nil) then
|
|
||||||
for i, lsn in ipairs(evtbl) do
|
|
||||||
table.insert(clone, lsn)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
pfx_ev = pfx_ev .. ':once'
|
|
||||||
evtbl = self:getEvTable(pfx_ev)
|
|
||||||
|
|
||||||
if (evtbl ~= nil) then
|
|
||||||
for i, lsn in ipairs(evtbl) do
|
|
||||||
table.insert(clone, lsn)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return clone
|
|
||||||
end
|
|
||||||
|
|
||||||
Events.on = Events.addListener
|
|
||||||
|
|
||||||
function Events:once(ev, listener)
|
|
||||||
local pfx_ev = PFX .. tostring(ev) .. ':once'
|
|
||||||
local evtbl = self:evTable(pfx_ev)
|
|
||||||
local maxLsnNum = self.currentMaxListeners or self.defaultMaxListeners
|
|
||||||
local lsnNum = self:listenerCount(ev)
|
|
||||||
if (lsnNum > maxLsnNum) then
|
|
||||||
print('WARN: Number of ' .. ev .. " event listeners: " .. tostring(lsnNum))
|
|
||||||
end
|
|
||||||
|
|
||||||
table.insert(evtbl, listener)
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
function Events:removeAllListeners(ev)
|
|
||||||
if ev ~= nil then
|
|
||||||
local pfx_ev = PFX .. tostring(ev)
|
|
||||||
local evtbl = self:evTable(pfx_ev)
|
|
||||||
rmEntry(evtbl, function(v)
|
|
||||||
return v ~= nil
|
|
||||||
end)
|
|
||||||
|
|
||||||
pfx_ev = pfx_ev .. ':once'
|
|
||||||
evtbl = self:evTable(pfx_ev)
|
|
||||||
rmEntry(evtbl, function(v)
|
|
||||||
return v ~= nil
|
|
||||||
end)
|
|
||||||
self._on[pfx_ev] = nil
|
|
||||||
else
|
|
||||||
for _pfx_ev, _t in pairs(self._on) do
|
|
||||||
self:removeAllListeners(string.sub(_pfx_ev, PFX_LEN + 1))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
for _pfx_ev, _t in pairs(self._on) do
|
|
||||||
if (#_t == 0) then
|
|
||||||
self._on[_pfx_ev] = nil
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
function Events:removeListener(ev, listener)
|
|
||||||
local pfx_ev = PFX .. tostring(ev)
|
|
||||||
local evtbl = self:evTable(pfx_ev)
|
|
||||||
local lsnCount = 0
|
|
||||||
assert(listener ~= nil, "listener is nil")
|
|
||||||
-- normal listener
|
|
||||||
rmEntry(evtbl, listener)
|
|
||||||
|
|
||||||
if (#evtbl == 0) then
|
|
||||||
self._on[pfx_ev] = nil
|
|
||||||
end
|
|
||||||
|
|
||||||
-- emit-once listener
|
|
||||||
pfx_ev = pfx_ev .. ':once'
|
|
||||||
evtbl = self:evTable(pfx_ev)
|
|
||||||
rmEntry(evtbl, listener)
|
|
||||||
|
|
||||||
if (#evtbl == 0) then
|
|
||||||
self._on[pfx_ev] = nil
|
|
||||||
end
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
function Events:setMaxListeners(n)
|
|
||||||
self.currentMaxListeners = n
|
|
||||||
return self
|
|
||||||
end
|
|
||||||
|
|
||||||
return Events
|
|
||||||
@ -0,0 +1,178 @@
|
|||||||
|
-- local skynet = require("skynet")
|
||||||
|
-- local serviceAddress = require("serviceAddress")
|
||||||
|
-- local serviceProxy = require("serviceProxy")
|
||||||
|
-- local eventd
|
||||||
|
-- local curlistenerHandleIndex = 1
|
||||||
|
-- local string_format = string.format
|
||||||
|
-- local table_insert = table.insert
|
||||||
|
|
||||||
|
-- local dispatch = {}
|
||||||
|
|
||||||
|
-- local crossEventClient = {}
|
||||||
|
|
||||||
|
-- function crossEventClient.addEventListener(crossEventType, eventId, objId, cb, obj)
|
||||||
|
-- assert(objId == nil or (type(objId) == "number" and objId > 0) or (type(objId) == "string" and #objId > 0),
|
||||||
|
-- string_format("[crossEventClient].addEventListener,objId"))
|
||||||
|
-- local dispatchKey = string_format("%s-%s", crossEventType, eventId)
|
||||||
|
-- local handle = curlistenerHandleIndex
|
||||||
|
-- curlistenerHandleIndex = curlistenerHandleIndex + 1
|
||||||
|
-- local listener = {cb, obj}
|
||||||
|
-- local eventListener = dispatch[dispatchKey]
|
||||||
|
-- if not eventListener then
|
||||||
|
-- eventListener = {}
|
||||||
|
-- dispatch[dispatchKey] = eventListener
|
||||||
|
-- end
|
||||||
|
-- local listeners
|
||||||
|
-- if objId then
|
||||||
|
-- eventListener.single = eventListener.single or {}
|
||||||
|
-- listeners = eventListener.single[objId]
|
||||||
|
-- if not listeners then
|
||||||
|
-- listeners = {}
|
||||||
|
-- eventListener.single[objId] = listeners
|
||||||
|
-- end
|
||||||
|
-- else
|
||||||
|
-- eventListener.all = eventListener.all or {}
|
||||||
|
-- listeners = eventListener.all
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- if not next(listeners) then
|
||||||
|
-- local addr = skynet.self()
|
||||||
|
-- skynet.send(eventd, "lua", "addEventListener", dispatchKey, addr, objId)
|
||||||
|
-- end
|
||||||
|
-- listeners[handle] = listener
|
||||||
|
-- return handle
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- function crossEventClient.removeEventListener(handle)
|
||||||
|
-- for dispatchKey, eventListener in pairs(dispatch) do
|
||||||
|
-- local singleListener = eventListener.single
|
||||||
|
-- if singleListener then
|
||||||
|
-- for objId, listeners in pairs(singleListener) do
|
||||||
|
-- for h, _ in pairs(listeners) do
|
||||||
|
-- if h == handle then
|
||||||
|
-- listeners[h] = nil
|
||||||
|
-- if not next(singleListener) then
|
||||||
|
-- eventListener.single = nil
|
||||||
|
-- local addr = skynet.self()
|
||||||
|
-- skynet.send(eventd, "lua", "removeEventListener", dispatchKey, addr, objId)
|
||||||
|
-- end
|
||||||
|
-- break
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- local allListener = eventListener.all
|
||||||
|
-- if allListener then
|
||||||
|
-- for h, _ in pairs(allListener) do
|
||||||
|
-- if h == handle then
|
||||||
|
-- allListener[h] = nil
|
||||||
|
-- if not next(allListener) then
|
||||||
|
-- eventListener.all = nil
|
||||||
|
-- local addr = skynet.self()
|
||||||
|
-- skynet.send(eventd, "lua", "removeEventListener", dispatchKey, addr)
|
||||||
|
-- end
|
||||||
|
-- break
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- function crossEventClient.dispatchEventBySend(crossEventType, eventId, objId, event)
|
||||||
|
-- assert(objId == nil or (type(objId) == "number" and objId > 0) or (type(objId) == "string" and #objId > 0),
|
||||||
|
-- string_format("[crossEventClient].addEventListener,objId"))
|
||||||
|
-- local dispatchKey = string_format("%s-%s", crossEventType, eventId)
|
||||||
|
-- event.dispatchKey = dispatchKey
|
||||||
|
-- event.dispatchObjId = objId
|
||||||
|
-- local strEvent = skynet.tostring(skynet.pack(event))
|
||||||
|
-- skynet.send(eventd, "lua", "dispatchEventBySend", dispatchKey, strEvent, objId)
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- function crossEventClient.dispatchEventByCall(crossEventType, eventId, objId, event)
|
||||||
|
-- assert(objId == nil or (type(objId) == "number" and objId > 0) or (type(objId) == "string" and #objId > 0),
|
||||||
|
-- string_format("[crossEventClient].addEventListener,objId"))
|
||||||
|
-- local dispatchKey = string_format("%s-%s", crossEventType, eventId)
|
||||||
|
-- event.dispatchKey = dispatchKey
|
||||||
|
-- event.dispatchObjId = objId
|
||||||
|
-- local strEvent = skynet.tostring(skynet.pack(event))
|
||||||
|
-- skynet.call(eventd, "lua", "dispatchEventByCall", dispatchKey, strEvent, objId)
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- function crossEventClient.dispatchEventComposeBySend(crossEventType, eventId, objId, event, amongSvr, amongCluster,
|
||||||
|
-- nodeNames)
|
||||||
|
-- assert(objId == nil or (type(objId) == "number" and objId > 0) or (type(objId) == "string" and #objId > 0),
|
||||||
|
-- string_format("[crossEventClient].addEventListener,objId"))
|
||||||
|
-- local dispatchKey = string_format("%s-%s", crossEventType, eventId)
|
||||||
|
-- event.dispatchKey = dispatchKey
|
||||||
|
-- event.dispatchObjId = objId
|
||||||
|
-- local strEvent = skynet.tostring(skynet.pack(event))
|
||||||
|
-- if amongSvr then
|
||||||
|
-- skynet.send(eventd, "lua", "dispatchEventBySend", dispatchKey, strEvent, objId)
|
||||||
|
-- end
|
||||||
|
-- if amongCluster then
|
||||||
|
-- for _, nodeName in pairs(nodeNames) do
|
||||||
|
-- local crossEventServerProxy = serviceProxy.remote(nodeName, "crossEvent")
|
||||||
|
-- crossEventServerProxy.remotePost.dispatchEventBySend(nodeName, dispatchKey, strEvent, objId)
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- local function dispatchEvent(session, _, strEvent)
|
||||||
|
-- local event = skynet.unpack(strEvent)
|
||||||
|
-- local dispatchKey = event.dispatchKey
|
||||||
|
-- local objId = event.dispatchObjId
|
||||||
|
-- local eventListener = dispatch[dispatchKey]
|
||||||
|
-- if not eventListener then
|
||||||
|
-- return
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- local tmpListeners = {}
|
||||||
|
-- if objId then
|
||||||
|
-- local singleListener = eventListener.single
|
||||||
|
-- if singleListener then
|
||||||
|
-- local listeners = singleListener[objId]
|
||||||
|
-- if listeners then
|
||||||
|
-- for _, listener in pairs(listeners) do
|
||||||
|
-- table_insert(tmpListeners, listener)
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- local allListener = eventListener.all
|
||||||
|
-- if allListener then
|
||||||
|
-- for _, listener in pairs(allListener) do
|
||||||
|
-- table_insert(tmpListeners, listener)
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- for _, listener in pairs(tmpListeners) do
|
||||||
|
-- local cb = listener[1]
|
||||||
|
-- local obj = listener[2]
|
||||||
|
-- if obj then
|
||||||
|
-- cb(obj, event)
|
||||||
|
-- else
|
||||||
|
-- cb(event)
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- if session > 0 then
|
||||||
|
-- skynet.ret(skynet.pack(true))
|
||||||
|
-- end
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- local function init()
|
||||||
|
-- eventd = serviceAddress.crossEvent()
|
||||||
|
-- log.debug("[crossEventClient].init,eventd=%s", eventd)
|
||||||
|
-- skynet.register_protocol {
|
||||||
|
-- name = "crossevent",
|
||||||
|
-- id = skynet.PTYPE_TEXT,
|
||||||
|
-- unpack = skynet.tostring,
|
||||||
|
-- dispatch = dispatchEvent,
|
||||||
|
-- }
|
||||||
|
-- end
|
||||||
|
|
||||||
|
-- init()
|
||||||
|
|
||||||
|
-- return crossEventClient
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
-- local crossEventType = require("crossEvent.crossEventType")
|
||||||
|
-- local PlayerEventEnum = gEnum("PlayerEventEnum")
|
||||||
|
-- local PlayerEventId = PlayerEventEnum.PlayerEventId
|
||||||
|
-- local ClusterEnum = gEnum("ClusterEnum")
|
||||||
|
-- local ClusterEventId = ClusterEnum.ClusterEventId
|
||||||
|
|
||||||
|
|
||||||
|
-- local eventRouteConfig = {
|
||||||
|
-- amongService = {
|
||||||
|
-- [crossEventType.CLUSTER] = {
|
||||||
|
-- [ClusterEventId.NODE_STATUS_CHANGE] = true,
|
||||||
|
-- },
|
||||||
|
-- [crossEventType.PLAYER] = {
|
||||||
|
-- [PlayerEventId.ONLINE] = true,
|
||||||
|
-- [PlayerEventId.OFFLINE] = true,
|
||||||
|
-- },
|
||||||
|
-- },
|
||||||
|
-- amongCluster = {
|
||||||
|
-- [crossEventType.CLUSTER] = {
|
||||||
|
-- [ClusterEventId.NODE_STATUS_CHANGE] = {
|
||||||
|
-- "login",
|
||||||
|
-- "game",
|
||||||
|
-- },
|
||||||
|
-- }
|
||||||
|
-- }
|
||||||
|
-- }
|
||||||
|
|
||||||
|
-- return eventRouteConfig
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
-- 跨服务 事件类型
|
||||||
|
local crossEventType = {
|
||||||
|
CLUSTER = 1, -- 集群
|
||||||
|
PLAYER = 2, -- 玩家
|
||||||
|
ALLIANCE = 3, -- 联盟
|
||||||
|
}
|
||||||
|
|
||||||
|
return crossEventType
|
||||||
@ -0,0 +1,270 @@
|
|||||||
|
--[[--
|
||||||
|
Provides custom event broadcaster / listener mechanism to regular Lua objects.
|
||||||
|
|
||||||
|
All listeners receive the following fields in the parameter event table:
|
||||||
|
|
||||||
|
<code>event.name</code> (name of the event)
|
||||||
|
|
||||||
|
<code>event.target</code> (the listener itself)
|
||||||
|
|
||||||
|
<code>event.source</code> (the dispatcher)
|
||||||
|
|
||||||
|
Latest code: https://github.com/daveyang/EventDispatcher
|
||||||
|
|
||||||
|
@module EventDispatcher
|
||||||
|
@usage
|
||||||
|
local EvtD = require "EventDispatcher"
|
||||||
|
|
||||||
|
local dispatcher = EvtD()
|
||||||
|
|
||||||
|
-- listener as table
|
||||||
|
local listener = {
|
||||||
|
eventName = function(event, ...)
|
||||||
|
print(event.name, event.target, event.source)
|
||||||
|
end
|
||||||
|
}
|
||||||
|
|
||||||
|
-- listener as function
|
||||||
|
local function listener(event, ...)
|
||||||
|
print(event.name, event.target, event.source)
|
||||||
|
end
|
||||||
|
|
||||||
|
dispatcher:addEventListener( "eventName", listener ) -- or
|
||||||
|
dispatcher:on( "eventName", listener )
|
||||||
|
|
||||||
|
dispatcher:once( "eventName", listener )
|
||||||
|
|
||||||
|
dispatcher:hasEventListener( "eventName", listener )
|
||||||
|
|
||||||
|
dispatcher:dispatchEvent( { name="eventName" } ) -- or
|
||||||
|
dispatcher:dispatchEvent( "eventName" ) -- or
|
||||||
|
dispatcher:emit( { name="eventName" } ) -- or
|
||||||
|
dispatcher:emit( "eventName" )
|
||||||
|
|
||||||
|
dispatcher:removeEventListener( "eventName", listener )
|
||||||
|
|
||||||
|
dispatcher:removeAllListeners( "eventName" ) -- or
|
||||||
|
dispatcher:removeAllListeners()
|
||||||
|
|
||||||
|
dispatcher:printListeners()
|
||||||
|
]]
|
||||||
|
|
||||||
|
|
||||||
|
local EventDispatcher = {}
|
||||||
|
|
||||||
|
-- Initializes an object (this is automatically invoked and is considered a private method)
|
||||||
|
-- @param o table object to become event dispatcher
|
||||||
|
-- @return a table
|
||||||
|
function EventDispatcher:init(o)
|
||||||
|
o = o or {}
|
||||||
|
o._listeners = {}
|
||||||
|
self.__index = self
|
||||||
|
return setmetatable(o, self)
|
||||||
|
end
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Checks if the event dispatcher has registered listener for the event eventName.
|
||||||
|
-- @param eventName event name (string)
|
||||||
|
-- @param listener object (table or function)
|
||||||
|
-- @return found status (boolean); if found also returns the index of listener object.
|
||||||
|
function EventDispatcher:hasEventListener(eventName, listener)
|
||||||
|
if eventName == nil or #eventName == 0 or listener == nil then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local a = self._listeners
|
||||||
|
if a == nil then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
for i, o in next, a do
|
||||||
|
if o ~= nil and o.evt == eventName and o.obj == listener then
|
||||||
|
return true, i
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Adds a listener for the event eventName. Optional runs once flag.
|
||||||
|
-- @param eventName event name (string)
|
||||||
|
-- @param listener object (table or function)
|
||||||
|
-- @param isOnce flag to specify the listener only runs once (boolean)
|
||||||
|
-- @return success/fail status (boolean); position of listener is also returned if false; position=0 if failed.
|
||||||
|
-- @see on
|
||||||
|
-- @see once
|
||||||
|
function EventDispatcher:addEventListener(eventName, listener, isOnce)
|
||||||
|
if not isOnce then
|
||||||
|
local found, pos = self:hasEventListener(eventName, listener)
|
||||||
|
if found then
|
||||||
|
return false, pos
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local a = self._listeners
|
||||||
|
if a == nil then
|
||||||
|
return false, 0
|
||||||
|
end
|
||||||
|
|
||||||
|
a[#a + 1] = {
|
||||||
|
evt = eventName,
|
||||||
|
obj = listener,
|
||||||
|
isOnce = isOnce,
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
--- 'on' is an alias of 'addEventListener'
|
||||||
|
EventDispatcher.on = EventDispatcher.addEventListener
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Adds a one-time listener for the event eventName. Once the event is dispatched, the listener is removed.
|
||||||
|
-- @param eventName event name (string)
|
||||||
|
-- @param listener object (table or function)
|
||||||
|
-- @return success/fail status (boolean); position of listener is also returned if false; position=0 if failed.
|
||||||
|
-- @see addEventListener
|
||||||
|
-- @see on
|
||||||
|
function EventDispatcher:once(eventName, listener)
|
||||||
|
return self:addEventListener(eventName, listener, true)
|
||||||
|
end
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Dispatches an event, with optional extra parameters.
|
||||||
|
-- @param event the event (table, must have a 'name' key; e.g. { name="eventName" }, or as string)
|
||||||
|
-- @param ... optional extra parameters
|
||||||
|
-- @return dispatch status (boolean).
|
||||||
|
-- @see emit
|
||||||
|
function EventDispatcher:dispatchEvent(event, ...)
|
||||||
|
if event == nil then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
if type(event) == "table" then
|
||||||
|
if event.name == nil or type(event.name) ~= "string" or #event.name == 0 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
elseif type(event) == "string" then
|
||||||
|
if #event == 0 then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
event = {
|
||||||
|
name = event,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
local a = self._listeners
|
||||||
|
if a == nil then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local dispatched = false
|
||||||
|
for _, o in next, a do
|
||||||
|
if o ~= nil and o.obj ~= nil and o.evt == event.name then
|
||||||
|
event.target = o.obj
|
||||||
|
event.source = self
|
||||||
|
|
||||||
|
if type(o.obj) == "function" then
|
||||||
|
o.obj(event, ...)
|
||||||
|
if o.isOnce then
|
||||||
|
self:removeEventListener(event.name, o.obj, true)
|
||||||
|
end
|
||||||
|
dispatched = true
|
||||||
|
elseif type(o.obj) == "table" then
|
||||||
|
local f = o.obj[event.name]
|
||||||
|
if f ~= nil then
|
||||||
|
f(event, ...)
|
||||||
|
if o.isOnce then
|
||||||
|
self:removeEventListener(event.name, o.obj, true)
|
||||||
|
end
|
||||||
|
dispatched = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return dispatched
|
||||||
|
end
|
||||||
|
|
||||||
|
--- 'emit' is an alias of 'dispatchEvent'
|
||||||
|
EventDispatcher.emit = EventDispatcher.dispatchEvent
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Removes listener with the eventName event from the event dispatcher.
|
||||||
|
-- @param eventName event name (string)
|
||||||
|
-- @param listener object (table or function)
|
||||||
|
-- @return removal status (boolean).
|
||||||
|
-- @see removeAllListeners
|
||||||
|
function EventDispatcher:removeEventListener(eventName, listener)
|
||||||
|
local found, pos = self:hasEventListener(eventName, listener)
|
||||||
|
if found then
|
||||||
|
table.remove(self._listeners, pos)
|
||||||
|
end
|
||||||
|
return found
|
||||||
|
end
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Removes all listeners with the eventName event from the event dispatcher.
|
||||||
|
--- If the optional eventName is nil, all listeners are removed from the event dispatcher.
|
||||||
|
-- @param eventName event name (string)
|
||||||
|
-- @return removal status (boolean), with the number of listeners removed.
|
||||||
|
-- @see removeEventListener
|
||||||
|
function EventDispatcher:removeAllListeners(eventName)
|
||||||
|
local a = self._listeners
|
||||||
|
if a == nil then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
if eventName == nil then
|
||||||
|
local n = #self._listeners
|
||||||
|
self._listeners = {}
|
||||||
|
return true, n
|
||||||
|
else
|
||||||
|
local found = false
|
||||||
|
local i = #a
|
||||||
|
local n = 0
|
||||||
|
|
||||||
|
while i > 0 do
|
||||||
|
local o = a[i]
|
||||||
|
if o ~= nil and o.evt == eventName then
|
||||||
|
table.remove(a, i)
|
||||||
|
found = true
|
||||||
|
n = n + 1
|
||||||
|
end
|
||||||
|
i = i - 1
|
||||||
|
end
|
||||||
|
return found, n
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
--- Prints the content of the _listeners array (for debugging).
|
||||||
|
-- Format: index, eventName, listener, isOnce.
|
||||||
|
function EventDispatcher:printListeners()
|
||||||
|
local a = self._listeners
|
||||||
|
if a == nil then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
for i, o in next, a do
|
||||||
|
if o ~= nil then
|
||||||
|
print(i, o.evt, o.obj, o.isOnce)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-- Create syntactic sugar to automatically call init().
|
||||||
|
setmetatable(EventDispatcher, {
|
||||||
|
__call = function(_, ...)
|
||||||
|
return EventDispatcher:init(...)
|
||||||
|
end,
|
||||||
|
})
|
||||||
|
|
||||||
|
return EventDispatcher
|
||||||
@ -0,0 +1,125 @@
|
|||||||
|
local eventRouteConfig = require("crossEvent.cross_event_router")
|
||||||
|
local crossEventClient = require("events.cross.cross_event_client")
|
||||||
|
|
||||||
|
------------------------------------------------
|
||||||
|
local EventDispatcher = class("EventDispatcher")
|
||||||
|
|
||||||
|
function EventDispatcher:initialize(crossEventType)
|
||||||
|
self.crossEventType = crossEventType
|
||||||
|
self.beforeListeners = {}
|
||||||
|
self.listeners = {}
|
||||||
|
self.nextListenerHandleIndex = 0
|
||||||
|
|
||||||
|
self.eventAmongService = eventRouteConfig.amongService[self.crossEventType]
|
||||||
|
self.eventAmongCluster = eventRouteConfig.amongCluster[self.crossEventType]
|
||||||
|
end
|
||||||
|
|
||||||
|
function EventDispatcher:addEventListener(eventId, listener, obj)
|
||||||
|
assert(type(eventId) == "number" and eventId ~= "", "EventDispatcher:addEventListener() - invalid eventId")
|
||||||
|
if self.listeners[eventId] == nil then
|
||||||
|
self.listeners[eventId] = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
self.nextListenerHandleIndex = self.nextListenerHandleIndex + 1
|
||||||
|
local handle = self.nextListenerHandleIndex
|
||||||
|
self.listeners[eventId][handle] = {listener, obj}
|
||||||
|
|
||||||
|
return handle
|
||||||
|
end
|
||||||
|
|
||||||
|
function EventDispatcher:addBeforeEventListener(eventId, listener, obj)
|
||||||
|
assert(type(eventId) == "number" or type(eventId) == "string" and eventId,
|
||||||
|
"EventDispatcher:addBeforeEventListener() - invalid eventId")
|
||||||
|
if self.beforeListeners[eventId] == nil then
|
||||||
|
self.beforeListeners[eventId] = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
self.nextListenerHandleIndex = self.nextListenerHandleIndex + 1
|
||||||
|
local handle = self.nextListenerHandleIndex
|
||||||
|
self.beforeListeners[eventId][handle] = {listener, obj}
|
||||||
|
|
||||||
|
return handle
|
||||||
|
end
|
||||||
|
|
||||||
|
local function execListeners(listeners, event)
|
||||||
|
local listenerlist = {}
|
||||||
|
for _, listener in pairs(listeners) do
|
||||||
|
table.insert(listenerlist, listener)
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, listener in ipairs(listenerlist) do
|
||||||
|
if listener[2] then
|
||||||
|
listener[1](listener[2], event)
|
||||||
|
else
|
||||||
|
listener[1](event)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function EventDispatcher:dispatchEvent(eventId, event)
|
||||||
|
local beforeListeners = self.beforeListeners[eventId]
|
||||||
|
if beforeListeners then
|
||||||
|
event.eventId = eventId
|
||||||
|
execListeners(beforeListeners, event)
|
||||||
|
end
|
||||||
|
|
||||||
|
local listeners = self.listeners[eventId]
|
||||||
|
if listeners then
|
||||||
|
event.eventId = eventId
|
||||||
|
execListeners(listeners, event)
|
||||||
|
end
|
||||||
|
|
||||||
|
local amongSvr = self.eventAmongService and self.eventAmongService[eventId]
|
||||||
|
local amongCluster = self.eventAmongCluster and self.eventAmongCluster[eventId]
|
||||||
|
local nodeNames
|
||||||
|
|
||||||
|
if amongCluster then
|
||||||
|
nodeNames = {}
|
||||||
|
for _, nodeTypeName in pairs(self.eventAmongCluster[eventId]) do
|
||||||
|
local tmpNodeNames = self:getNodeNames(nodeTypeName)
|
||||||
|
for _, nodeName in pairs(tmpNodeNames) do
|
||||||
|
table.insert(nodeNames, nodeName)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if amongSvr or amongCluster then
|
||||||
|
local eventType = self.crossEventType
|
||||||
|
local objId = self:getOwnerId()
|
||||||
|
ZLog.debug("[EventDispatcher].dispatchEvent,cross,eventType=%s,objId=%s", eventType, objId)
|
||||||
|
crossEventClient.dispatchEventDispatcheroseBySend(eventType, eventId, objId, event, amongSvr, amongCluster,
|
||||||
|
nodeNames)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function EventDispatcher:removeEventListener(handleToRemove)
|
||||||
|
for _, listenersForEvent in pairs(self.beforeListeners) do
|
||||||
|
local isRemoved = false
|
||||||
|
for handle, _ in pairs(listenersForEvent) do
|
||||||
|
if handle == handleToRemove then
|
||||||
|
listenersForEvent[handle] = nil
|
||||||
|
isRemoved = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if isRemoved then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, listenersForEvent in pairs(self.listeners) do
|
||||||
|
local isRemoved = false
|
||||||
|
for handle, _ in pairs(listenersForEvent) do
|
||||||
|
if handle == handleToRemove then
|
||||||
|
listenersForEvent[handle] = nil
|
||||||
|
isRemoved = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if isRemoved then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return EventDispatcher
|
||||||
@ -0,0 +1 @@
|
|||||||
|
本服务事件定义
|
||||||
Loading…
Reference in New Issue