Hmm i have a similar event system but i focus on making adding and removal easier by handling events and hooks as OOP object...
---
Code: Select all
EvCo = {
Events = {},
}
local event = {}
function event:new()
local o = {}
setmetatable(o, self)
self.__index = self
return o
end
local Hook = {}
function Hook:new()
local o = {}
setmetatable(o, self)
self.__index = self
return o
end
function Hook:setFunction(func,selfed)
self.selfed = selfed
self.func = func
end
function Hook:setEvent(event)
self.event = event
end
--[[
Ignore the
CuCo._RESERVED.MOD_DATABASE_Host.BUILD
CuCo._RESERVED.MOD_DATABASE_PROXY.BUILD
code as its related to my assetModule and Engine...
--]]
function event:fire(...)
local returns = {}
for k,v in pairs(self.Hooks) do
local ret
if v.selfed then
--check if the asset still exists, for auto cleaning dead assets!
if not CuCo._RESERVED.MOD_DATABASE_PROXY.BUILD[v.selfed.address] and not
CuCo._RESERVED.MOD_DATABASE_HOST.BUILD[v.selfed.address] then
self:removeHook(k)
else
ret = v.func(v.selfed,...)
end
else
ret = v.func(...)
end
if ret then
table.insert(returns,ret)
end
end
return returns
end
function event:getOpenSlot()
local slot
local Address = self.Hooks
local lowerLimit = 1
local upperLimit = 2^32 --can really make this anything to 2^256 (scary though)
for i = 1,upperLimit do
if not Address[tostring(i)] then
slot = tostring(i)
break
end
end
return tostring(slot)
end
function event:newHook(func,selfed)
local slot = self:getOpenSlot()
self.Hooks[slot] = Hook:new()
self.Hooks[slot]:setFunction(func,selfed)
self.Hooks[slot]:setEvent(self)
return slot
end
function event:removeHook(hook)
if self.Hooks[hook] then
self.Hooks[hook] = nil
end
end
function EvCo.getOpenEventSlot()
local slot
local Address = EvCo.Events
local lowerLimit = 1
local upperLimit = 2^32 --again, van make it very high
for i = 1,upperLimit do
if not Address[tostring(i)] then
slot = tostring(i)
break
end
end
return tostring(slot)
end
function EvCo.newEvent(eventName)
local slot = EvCo.getOpenEventSlot()
local newEvent = event:new()
newEvent.address = slot
newEvent.Hooks = {}
EvCo.Events[slot] = newEvent
return newEvent
end
The way i handle events is make it so you can reference them directly, ie
Hook onto the default love.update() and create an event that fires when love.Update is called... thus you can throw functions into love.update at anytime?
Code: Select all
myEvent = EvCo.newEvent()
function printThis(this)
print(this)
end
myHook = myEvent:newHook(printThis)
love.update(dt)
myEvent:fire(dt)
end
Also note that if you have ANOTHER OOP object and are hooking one of its functions to an event then you MUST pass the object aswell :
Code: Select all
---object definition :
local object = {}
function object:new()
local o = {}
setmetatable(o, self)
self.__index = self
return o
end
function object:printMyName()
if self.name then
print("My name is '"..self.name.."'")
else
print("I dont have a name!")
end
end
---love functions
love.update(dt)
myEvent:fire(dt)
end
function love.load()
--create event
myEvent = EvCo.newEvent()
--create objects :
myObject = object:new()
myObject.name = "SnoweeJohn"
myOtherObject = object:new()
myOtherObject.name = "YankAlWierd"
--create hooks :
myObjectsHook = myEvent:newHook(myObject.printMyName,myObject)
myOtherObjectsHook = myEvent:newHook(myOtherObject.printMyName) --notice how we dont pass the object aswell!
end
Now update will cause both objects to call printMyName, EXCEPT :
myObject output --> "My name is 'SnoweeJohn'"
myOtherObject output --> "I dont have a name"
Im pretty sure i explained well?
Also id be happy to strip away any CurseEngine bits from my event system for sharing