Improved the event handling

-- Removed the sort
-- Implemented the order in the existing table.
-- 5 levels
-- _DATABASE = 1
-- SET and SET_ derived classes = 2
-- UNIT = 3
-- GROUP = 4
-- all other = 5
This commit is contained in:
FlightControl
2017-02-04 11:35:58 +01:00
parent ab345f5ad2
commit be4d51237b
10 changed files with 98 additions and 63503 deletions

View File

@@ -21,7 +21,6 @@
EVENT = {
ClassName = "EVENT",
ClassID = 0,
SortedEvents = {},
}
local _EVENTCODES = {
@@ -122,6 +121,7 @@ end
--- Initializes the Events structure for the event
-- @param #EVENT self
-- @param Dcs.DCSWorld#world.event EventID
-- @param #number EventPriority The priority of the EventClass.
-- @param Core.Base#BASE EventClass
-- @return #EVENT.Events
function EVENT:Init( EventID, EventClass )
@@ -130,8 +130,13 @@ function EVENT:Init( EventID, EventClass )
if not self.Events[EventID] then
-- Create a WEAK table to ensure that the garbage collector is cleaning the event links when the object usage is cleaned.
self.Events[EventID] = setmetatable( {}, { __mode = "k" } )
self.SortedEvents[EventID] = setmetatable( {}, { __mode = "k" } )
end
-- Each event has a subtable of EventClasses, ordered by EventPriority.
local EventPriority = EventClass:GetEventPriority()
if not self.Events[EventID][EventPriority] then
self.Events[EventID][EventPriority] = {}
end
if not self.Events[EventID][EventClass] then
self.Events[EventID][EventClass] = setmetatable( {}, { __mode = "k" } )
@@ -148,13 +153,8 @@ function EVENT:Remove( EventClass, EventID )
self:F3( { EventClass, _EVENTCODES[EventID] } )
local EventClass = EventClass
self.Events[EventID][EventClass] = nil
self.SortedEvents[EventID] = nil
self.SortedEvents[EventID] = {}
for EventClass, Event in pairs(self.Events[EventID]) do table.insert( self.SortedEvents[EventID], Event) end
table.sort( self.SortedEvents[EventID], function( Event1, Event2 ) return Event1.EventTime < Event2.EventTime end )
local EventPriority = EventClass:GetEventPriority()
self.Events[EventID][EventPriority][EventClass] = nil
end
--- Clears all event subscriptions for a @{Core.Base#BASE} derived object.
@@ -164,9 +164,9 @@ function EVENT:RemoveAll( EventObject )
self:F3( { EventObject:GetClassNameAndID() } )
local EventClass = EventObject:GetClassNameAndID()
local EventPriority = EventClass:GetEventPriority()
for EventID, EventData in pairs( self.Events ) do
self.Events[EventID][EventClass] = nil
self.SortedEvents[EventID] = nil
self.Events[EventID][EventPriority][EventClass] = nil
end
end
@@ -200,12 +200,6 @@ function EVENT:OnEventGeneric( EventFunction, EventClass, EventID )
local Event = self:Init( EventID, EventClass )
Event.EventFunction = EventFunction
Event.EventClass = EventClass
Event.EventTime = EventClass.EventPriority and EventClass.EventPriority or 10
self.SortedEvents[EventID] = nil
self.SortedEvents[EventID] = {}
for EventClass, Event in pairs(self.Events[EventID]) do table.insert( self.SortedEvents[EventID], Event) end
table.sort( self.SortedEvents[EventID], function( Event1, Event2 ) return Event1.EventTime < Event2.EventTime end )
return self
end
@@ -807,38 +801,33 @@ function EVENT:onEvent( Event )
end
self:E( { _EVENTCODES[Event.id], Event, Event.IniDCSUnitName, Event.TgtDCSUnitName } )
local function pairsByEventSorted( EventSorted, Order )
local i = Order == -1 and #EventSorted or 0
local iter = function()
i = i + Order
if EventSorted[i] == nil then
return nil
else
return EventSorted[i].EventClass, EventSorted[i]
end
end
return iter
end
local Order = _EVENTORDER[Event.id]
self:E( { Order = Order } )
self:E( { Order = _EVENTORDER[Event.id] } )
for EventPriority = Order == -1 and 5 or 1, Order == -1 and 1 or 5, Order do
-- Okay, we got the event from DCS. Now loop the SORTED self.EventSorted[] table for the received Event.id, and for each EventData registered, check if a function needs to be called.
for EventClass, EventData in pairsByEventSorted( self.SortedEvents[Event.id], _EVENTORDER[Event.id] ) do
-- If the EventData is for a UNIT, the call directly the EventClass EventFunction for that UNIT.
if Event.IniDCSUnitName and EventData.IniUnit and EventData.IniUnit[Event.IniDCSUnitName] then
self:E( { "Calling EventFunction for Class ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName, EventData.EventTime } )
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName )
local Result, Value = xpcall( function() return EventData.IniUnit[Event.IniDCSUnitName].EventFunction( EventData.IniUnit[Event.IniDCSUnitName].EventClass, Event ) end, ErrorHandler )
--EventData.IniUnit[Event.IniDCSUnitName].EventFunction( EventData.IniUnit[Event.IniDCSUnitName].EventClass, Event )
else
-- If the EventData is not bound to a specific unit, then call the EventClass EventFunction.
-- Note that here the EventFunction will need to implement and determine the logic for the relevant source- or target unit, or weapon.
if Event.IniDCSUnit and not EventData.IniUnit then
if EventClass == EventData.EventClass then
self:E( { "Calling EventFunction for Class ", EventClass:GetClassNameAndID(), EventData.EventTime } )
if self.Events[Event.id][EventPriority] then
-- Okay, we got the event from DCS. Now loop the SORTED self.EventSorted[] table for the received Event.id, and for each EventData registered, check if a function needs to be called.
for EventClass, EventData in pairs( self.Events[Event.id][EventPriority] ) do
-- If the EventData is for a UNIT, the call directly the EventClass EventFunction for that UNIT.
if Event.IniDCSUnitName and EventData.IniUnit and EventData.IniUnit[Event.IniDCSUnitName] then
self:E( { "Calling EventFunction for Class ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName } )
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName )
local Result, Value = xpcall( function() return EventData.EventFunction( EventData.EventClass, Event ) end, ErrorHandler )
--EventData.EventFunction( EventData.EventClass, Event )
local Result, Value = xpcall( function() return EventData.IniUnit[Event.IniDCSUnitName].EventFunction( EventData.IniUnit[Event.IniDCSUnitName].EventClass, Event ) end, ErrorHandler )
--EventData.IniUnit[Event.IniDCSUnitName].EventFunction( EventData.IniUnit[Event.IniDCSUnitName].EventClass, Event )
else
-- If the EventData is not bound to a specific unit, then call the EventClass EventFunction.
-- Note that here the EventFunction will need to implement and determine the logic for the relevant source- or target unit, or weapon.
if Event.IniDCSUnit and not EventData.IniUnit then
if EventClass == EventData.EventClass then
self:E( { "Calling EventFunction for Class ", EventClass:GetClassNameAndID() } )
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName )
local Result, Value = xpcall( function() return EventData.EventFunction( EventData.EventClass, Event ) end, ErrorHandler )
--EventData.EventFunction( EventData.EventClass, Event )
end
end
end
end
end