5e0d58cfad
EN: 1.2.0.60 CN: 1.2.0.61 JP: 1.2.0.63 KR: 1.2.0.67
217 lines
5.8 KiB
Lua
217 lines
5.8 KiB
Lua
local Luvent = {}
|
|
Luvent.__index = Luvent
|
|
function Luvent.newEvent()
|
|
local event = {}
|
|
event.actions = {}
|
|
return setmetatable(event, Luvent)
|
|
end
|
|
function Luvent.__eq(e1, e2)
|
|
if getmetatable(e1) ~= Luvent or getmetatable(e2) ~= Luvent then
|
|
return false
|
|
end
|
|
if #e1.actions ~= #e2.actions then
|
|
return false
|
|
end
|
|
for _, a1 in ipairs(e1.actions) do
|
|
local found = false
|
|
for _, a2 in ipairs(e2.actions) do
|
|
if a1 == a2 then
|
|
found = true
|
|
break
|
|
end
|
|
end
|
|
if found == false then
|
|
return false
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
Luvent.Action = {}
|
|
Luvent.Action.__index = Luvent.Action
|
|
local isActionCallable = function(callable)
|
|
if type(callable) == "table" then
|
|
if type(getmetatable(callable).__call) == "function" then
|
|
return true
|
|
end
|
|
elseif type(callable) == "function" then
|
|
return true
|
|
elseif type(callable) == "thread" and coroutine.status(callable) ~= "dead" then
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
local newAction = function(callable)
|
|
local action = {}
|
|
assert(isActionCallable(callable))
|
|
action.callable = callable
|
|
action.id = tostring(callable)
|
|
action.enabled = true
|
|
action.priority = 0
|
|
action.limit = -1
|
|
action.numberOfInvocations = 0
|
|
action.interval = 0
|
|
action.timeOfLastInvocation = os.time()
|
|
return setmetatable(action, Luvent.Action)
|
|
end
|
|
function Luvent.Action.__eq(a1, a2)
|
|
if getmetatable(a1) ~= Luvent.Action or getmetatable(a2) ~= Luvent.Action then
|
|
return false
|
|
end
|
|
return a1.id == a2.id
|
|
end
|
|
local findAction = function(event, actionToFind)
|
|
local key
|
|
if type(actionToFind) == "string" then
|
|
key = "id"
|
|
elseif isActionCallable(actionToFind) then
|
|
key = "callable"
|
|
else
|
|
error("Invalid action parameter: " .. tostring(actionToFind))
|
|
end
|
|
for index, action in ipairs(event.actions) do
|
|
if action[key] == actionToFind then
|
|
return true, index
|
|
end
|
|
end
|
|
return false, nil
|
|
end
|
|
local sortActionsByPriority = function(event)
|
|
table.sort(event.actions, function(a1, a2)
|
|
return a1.priority > a2.priority
|
|
end)
|
|
end
|
|
function Luvent:addAction(actionToAdd)
|
|
assert(isActionCallable(actionToAdd) == true)
|
|
if self:hasAction(actionToAdd) then
|
|
return
|
|
end
|
|
local new = newAction(actionToAdd)
|
|
table.insert(self.actions, new)
|
|
return new.id
|
|
end
|
|
function Luvent:removeAction(actionToRemove)
|
|
local exists, index = findAction(self, actionToRemove)
|
|
if exists == true then
|
|
table.remove(self.actions, index)
|
|
end
|
|
end
|
|
function Luvent:removeAllActions()
|
|
self.actions = {}
|
|
end
|
|
function Luvent:getActionCount()
|
|
return #self.actions
|
|
end
|
|
function Luvent:hasAction(actionToFind)
|
|
return (findAction(self, actionToFind))
|
|
end
|
|
local invokeAction = function(action, ...)
|
|
if action.enabled == false then
|
|
return true
|
|
end
|
|
if type(action.callable) == "thread" then
|
|
coroutine.resume(action.callable, ...)
|
|
if coroutine.status(action.callable) == "dead" then
|
|
return false
|
|
end
|
|
else
|
|
action.callable(...)
|
|
end
|
|
action.numberOfInvocations = action.numberOfInvocations + 1
|
|
if action.limit >= 0 and action.numberOfInvocations >= action.limit then
|
|
action.enabled = false
|
|
end
|
|
return true
|
|
end
|
|
function Luvent:trigger(...)
|
|
local call = function(action, ...)
|
|
local keep = invokeAction(action, ...)
|
|
if keep == false then
|
|
self:removeAction(action.id)
|
|
end
|
|
end
|
|
sortActionsByPriority(self)
|
|
for _, action in ipairs(self.actions) do
|
|
if action.interval > 0 then
|
|
if os.difftime(os.time(), action.timeOfLastInvocation) >= action.interval then
|
|
call(action, ...)
|
|
action.timeOfLastInvocation = os.time()
|
|
end
|
|
else
|
|
call(action, ...)
|
|
end
|
|
end
|
|
end
|
|
local createActionSetter = function(property, valueType, default)
|
|
return function(event, actionToFind, newValue)
|
|
local propertyValue = newValue or default
|
|
local propertyValueType = type(propertyValue)
|
|
local exists, index = findAction(event, actionToFind)
|
|
assert(exists)
|
|
assert(propertyValueType == valueType)
|
|
if propertyValueType == "number" then
|
|
assert(0 <= propertyValue)
|
|
end
|
|
event.actions[index][property] = propertyValue
|
|
end
|
|
end
|
|
local createActionGetter = function(property)
|
|
return function(event, action)
|
|
local exists, index = findAction(event, action)
|
|
assert(exists)
|
|
assert(event.actions[index][property])
|
|
return event.actions[index][property]
|
|
end
|
|
end
|
|
Luvent.setActionInterval = createActionSetter("interval", "number")
|
|
Luvent.getActionInterval = createActionGetter("interval")
|
|
Luvent.removeActionInterval = createActionSetter("interval", "number", 0)
|
|
Luvent.setActionPriority = createActionSetter("priority", "number")
|
|
Luvent.getActionPriority = createActionGetter("priority")
|
|
Luvent.removeActionPriority = createActionSetter("priority", "number", 0)
|
|
Luvent.enableAction = createActionSetter("enabled", "boolean", true)
|
|
Luvent.disableAction = createActionSetter("enabled", "boolean", false)
|
|
function Luvent:isActionEnabled(actionToFind)
|
|
local exists, index = findAction(self, actionToFind)
|
|
assert(exists)
|
|
return self.actions[index].enabled
|
|
end
|
|
function Luvent:setActionTriggerLimit(actionToFind, limit)
|
|
local exists, index = findAction(self, actionToFind)
|
|
assert(exists)
|
|
assert(type(limit) == "number" and 0 <= limit)
|
|
self.actions[index].limit = limit
|
|
self.actions[index].numberOfInvocations = 0
|
|
if limit == 0 then
|
|
self.actions[index].enabled = false
|
|
end
|
|
end
|
|
function Luvent:getActionTriggerLimit(actionToFind)
|
|
local exists, index = findAction(self, actionToFind)
|
|
assert(exists)
|
|
assert(self.actions[index].limit)
|
|
return self.actions[index].limit
|
|
end
|
|
function Luvent:removeActionTriggerLimit(actionToFind)
|
|
local exists, index = findAction(self, actionToFind)
|
|
assert(exists)
|
|
self.actions[index].limit = -1
|
|
self.actions[index].numberOfInvocations = 0
|
|
self.actions[index].enabled = true
|
|
end
|
|
function Luvent:allActions()
|
|
local index = 0
|
|
return function()
|
|
index = index + 1
|
|
local action = self.actions[index]
|
|
if action then
|
|
return action.id
|
|
end
|
|
end
|
|
end
|
|
function Luvent:forEachAction(f)
|
|
for action in self:allActions() do
|
|
f(self, action)
|
|
end
|
|
end
|
|
return Luvent
|