🐳 chore(工具): 增加 全局事件 和 事件对象基础类

develop
xiaojin 5 years ago
parent 2ebfd2654c
commit b7815395e8

@ -14,7 +14,7 @@ globals = {
"class", "class",
"singleton", "singleton",
"handler", "handler",
"zlog", "ZLog",
} }
ignore = { ignore = {

@ -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
Loading…
Cancel
Save