New Event Dispatching based on priorities

-- First _DATABASE
-- then SETS
-- then the rest
-- changed AIRBASEPOLICE
This commit is contained in:
FlightControl
2017-02-03 22:18:51 +01:00
parent 33af2b4f95
commit ab345f5ad2
13 changed files with 291 additions and 71 deletions

View File

@@ -55,6 +55,8 @@ DATABASE = {
CLIENTS = {},
AIRBASES = {},
NavPoints = {},
EventPriority = 1, -- Used to sort the DCS event order processing (complicated). Database has highest priority.
}
local _DATABASECoalition =
@@ -228,6 +230,7 @@ end
function DATABASE:AddGroup( GroupName )
if not self.GROUPS[GroupName] then
self:E( { "Add GROUP:", GroupName } )
self.GROUPS[GroupName] = GROUP:Register( GroupName )
end
@@ -569,6 +572,8 @@ function DATABASE:_EventOnPlayerEnterUnit( Event )
self:F2( { Event } )
if Event.IniUnit then
self:AddUnit( Event.IniDCSUnitName )
self:AddGroup( Event.IniDCSGroupName )
local PlayerName = Event.IniUnit:GetPlayerName()
if not self.PLAYERS[PlayerName] then
self:AddPlayer( Event.IniUnitName, PlayerName )

View File

@@ -21,6 +21,7 @@
EVENT = {
ClassName = "EVENT",
ClassID = 0,
SortedEvents = {},
}
local _EVENTCODES = {
@@ -50,6 +51,33 @@ local _EVENTCODES = {
"S_EVENT_MAX",
}
local _EVENTORDER = {
[world.event.S_EVENT_SHOT] = 1,
[world.event.S_EVENT_HIT] = 1,
[world.event.S_EVENT_TAKEOFF] = 1,
[world.event.S_EVENT_LAND] = 1,
[world.event.S_EVENT_CRASH] = -1,
[world.event.S_EVENT_EJECTION] = -1,
[world.event.S_EVENT_REFUELING] = 1,
[world.event.S_EVENT_DEAD] = -1,
[world.event.S_EVENT_PILOT_DEAD] = -1,
[world.event.S_EVENT_BASE_CAPTURED] = 1,
[world.event.S_EVENT_MISSION_START] = 1,
[world.event.S_EVENT_MISSION_END] = -1,
[world.event.S_EVENT_TOOK_CONTROL] = 1,
[world.event.S_EVENT_REFUELING_STOP] = 1,
[world.event.S_EVENT_BIRTH] = 1,
[world.event.S_EVENT_HUMAN_FAILURE] = 1,
[world.event.S_EVENT_ENGINE_STARTUP] = 1,
[world.event.S_EVENT_ENGINE_SHUTDOWN] = 1,
[world.event.S_EVENT_PLAYER_ENTER_UNIT] = 1,
[world.event.S_EVENT_PLAYER_LEAVE_UNIT] = -1,
[world.event.S_EVENT_PLAYER_COMMENT] = 1,
[world.event.S_EVENT_SHOOTING_START] = 1,
[world.event.S_EVENT_SHOOTING_END] = 1,
[world.event.S_EVENT_MAX] = 1,
}
--- The Event structure
-- @type EVENTDATA
-- @field id
@@ -102,7 +130,7 @@ 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
if not self.Events[EventID][EventClass] then
@@ -121,6 +149,12 @@ function EVENT:Remove( EventClass, 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 )
end
--- Clears all event subscriptions for a @{Core.Base#BASE} derived object.
@@ -132,6 +166,7 @@ function EVENT:RemoveAll( EventObject )
local EventClass = EventObject:GetClassNameAndID()
for EventID, EventData in pairs( self.Events ) do
self.Events[EventID][EventClass] = nil
self.SortedEvents[EventID] = nil
end
end
@@ -165,6 +200,13 @@ 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
@@ -741,6 +783,8 @@ function EVENT:onEvent( Event )
Event.IniDCSGroupName = ""
if Event.IniDCSGroup and Event.IniDCSGroup:isExist() then
Event.IniDCSGroupName = Event.IniDCSGroup:getName()
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName )
self:E( { IniGroup = Event.IniGroup } )
end
end
if Event.target then
@@ -763,11 +807,27 @@ function EVENT:onEvent( Event )
end
self:E( { _EVENTCODES[Event.id], Event, Event.IniDCSUnitName, Event.TgtDCSUnitName } )
-- Okay, we got the event from DCS. Now loop the self.Events[] 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] ) do
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
self:E( { Order = _EVENTORDER[Event.id] } )
-- 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:T( { "Calling EventFunction for Class ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName } )
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
@@ -775,7 +835,8 @@ function EVENT:onEvent( Event )
-- 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:T( { "Calling EventFunction for Class ", EventClass:GetClassNameAndID() } )
self:E( { "Calling EventFunction for Class ", EventClass:GetClassNameAndID(), EventData.EventTime } )
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

View File

@@ -240,6 +240,7 @@ SET_BASE = {
Filter = {},
Set = {},
List = {},
EventPriority = 2, -- Used to sort the DCS event order processing (complicated)
}
--- Creates a new SET_BASE object, building a set of units belonging to a coalitions, categories, countries, types or with defined prefix names.

View File

@@ -182,7 +182,7 @@ function AIRBASEPOLICE_BASE:_AirbaseMonitor()
Client:SetState( self, "Warnings", SpeedingWarnings + 1 )
else
MESSAGE:New( "Player " .. Client:GetPlayerName() .. " has been removed from the airbase, due to a speeding violation ...", 10, "Airbase Police" ):ToAll()
Client:GetGroup():Destroy()
Client:Destroy()
Client:SetState( self, "Speeding", false )
Client:SetState( self, "Warnings", 0 )
end

View File

@@ -81,7 +81,8 @@ function COMMANDCENTER:New( CommandCenterPositionable, CommandCenterName )
local PlayerUnit = EventData.IniUnit
for MissionID, Mission in pairs( self:GetMissions() ) do
local Mission = Mission -- Tasking.Mission#MISSION
Mission:JoinUnit( PlayerUnit )
local PlayerGroup = EventData.IniGroup -- The GROUP object should be filled!
Mission:JoinUnit( PlayerUnit, PlayerGroup )
Mission:ReportDetails()
end
@@ -100,7 +101,8 @@ function COMMANDCENTER:New( CommandCenterPositionable, CommandCenterName )
local PlayerUnit = EventData.IniUnit
for MissionID, Mission in pairs( self:GetMissions() ) do
local Mission = Mission -- Tasking.Mission#MISSION
Mission:JoinUnit( PlayerUnit )
local PlayerGroup = EventData.IniGroup -- The GROUP object should be filled!
Mission:JoinUnit( PlayerUnit, PlayerGroup )
Mission:ReportDetails()
end
end
@@ -115,6 +117,7 @@ function COMMANDCENTER:New( CommandCenterPositionable, CommandCenterName )
function( self, EventData )
local PlayerUnit = EventData.IniUnit
for MissionID, Mission in pairs( self:GetMissions() ) do
local Mission = Mission -- Tasking.Mission#MISSION
Mission:AbortUnit( PlayerUnit )
end
end

View File

@@ -103,15 +103,16 @@ end
-- If the Unit is part of a Task in the Mission, true is returned.
-- @param #MISSION self
-- @param Wrapper.Unit#UNIT PlayerUnit The CLIENT or UNIT of the Player joining the Mission.
-- @param Wrapper.Group#GROUP PlayerGroup The GROUP of the player joining the Mission.
-- @return #boolean true if Unit is part of a Task in the Mission.
function MISSION:JoinUnit( PlayerUnit )
self:F( { PlayerUnit = PlayerUnit } )
function MISSION:JoinUnit( PlayerUnit, PlayerGroup )
self:F( { PlayerUnit = PlayerUnit, PlayerGroup = PlayerGroup } )
local PlayerUnitAdded = false
for TaskID, Task in pairs( self:GetTasks() ) do
local Task = Task -- Tasking.Task#TASK
if Task:JoinUnit( PlayerUnit ) then
if Task:JoinUnit( PlayerUnit, PlayerGroup ) then
PlayerUnitAdded = true
end
end

View File

@@ -234,14 +234,14 @@ end
-- If the Unit is part of the Task, true is returned.
-- @param #TASK self
-- @param Wrapper.Unit#UNIT PlayerUnit The CLIENT or UNIT of the Player joining the Mission.
-- @param Wrapper.Group#GROUP PlayerGroup The GROUP of the player joining the Mission.
-- @return #boolean true if Unit is part of the Task.
function TASK:JoinUnit( PlayerUnit )
self:F( { PlayerUnit = PlayerUnit } )
function TASK:JoinUnit( PlayerUnit, PlayerGroup )
self:F( { PlayerUnit = PlayerUnit, PlayerGroup = PlayerGroup } )
local PlayerUnitAdded = false
local PlayerGroups = self:GetGroups()
local PlayerGroup = PlayerUnit:GetGroup()
-- Is the PlayerGroup part of the PlayerGroups?
if PlayerGroups:IsIncludeObject( PlayerGroup ) then
@@ -394,7 +394,6 @@ end
-- @return #boolean
function TASK:HasGroup( FindGroup )
self:GetGroups():FilterOnce() -- Ensure that the filter is updated.
return self:GetGroups():IsIncludeObject( FindGroup )
end