DATABASE now also follows correctly the players.

This commit is contained in:
FlightControl 2016-05-27 13:21:39 +02:00
parent 645d074a7d
commit 7efbd60b9e
6 changed files with 157 additions and 212 deletions

View File

@ -487,7 +487,10 @@ function BASE:E( Arguments )
end
local LineCurrent = DebugInfoCurrent.currentline
local LineFrom = DebugInfoFrom.currentline
local LineFrom = -1
if DebugInfoFrom then
LineFrom = DebugInfoFrom.currentline
end
env.info( string.format( "%6d(%6d)/%1s:%20s%05d.%s(%s)" , LineCurrent, LineFrom, "E", self.ClassName, self.ClassID, Function, routines.utils.oneLineSerialize( Arguments ) ) )
end

View File

@ -1,64 +1,34 @@
--- Manage sets of units and groups.
--- Manage the mission database.
--
-- @{#Database} class
-- @{#DATABASE} class
-- ==================
-- Mission designers can use the DATABASE class to build sets of units belonging to certain:
-- Mission designers can use the DATABASE class to refer to:
--
-- * Coalitions
-- * Categories
-- * Countries
-- * Unit types
-- * Starting with certain prefix strings.
-- * UNITS
-- * GROUPS
-- * players
-- * alive players
-- * CLIENTS
-- * alive CLIENTS
--
-- This list will grow over time. Planned developments are to include filters and iterators.
-- Additional filters will be added around @{Zone#ZONEs}, Radiuses, Active players, ...
-- More iterators will be implemented in the near future ...
--
-- Administers the Initial Sets of the Mission Templates as defined within the Mission Editor.
--
-- DATABASE construction methods:
-- =================================
-- Create a new DATABASE object with the @{#DATABASE.New} method:
--
-- * @{#DATABASE.New}: Creates a new DATABASE object.
--
--
-- DATABASE filter criteria:
-- =========================
-- You can set filter criteria to define the set of units within the database.
-- Filter criteria are defined by:
--
-- * @{#DATABASE.FilterCoalitions}: Builds the DATABASE with the units belonging to the coalition(s).
-- * @{#DATABASE.FilterCategories}: Builds the DATABASE with the units belonging to the category(ies).
-- * @{#DATABASE.FilterTypes}: Builds the DATABASE with the units belonging to the unit type(s).
-- * @{#DATABASE.FilterCountries}: Builds the DATABASE with the units belonging to the country(ies).
-- * @{#DATABASE.FilterUnitPrefixes}: Builds the DATABASE with the units starting with the same prefix string(s).
--
-- Once the filter criteria have been set for the DATABASE, you can start filtering using:
--
-- * @{#DATABASE.FilterStart}: Starts the filtering of the units within the database.
--
-- Planned filter criteria within development are (so these are not yet available):
--
-- * @{#DATABASE.FilterGroupPrefixes}: Builds the DATABASE with the groups of the units starting with the same prefix string(s).
-- * @{#DATABASE.FilterZones}: Builds the DATABASE with the units within a @{Zone#ZONE}.
-- On top, for internal MOOSE administration purposes, the DATBASE administers the Unit and Gruop templates as defined within the Mission Editor.
--
-- Moose will automatically create one instance of the DATABASE class into the **global** object _DATABASE.
-- Moose refers to _DATABASE within the framework extensively, but you can also refer to the _DATABASE object within your missions if required.
--
-- DATABASE iterators:
-- ===================
-- Once the filters have been defined and the DATABASE has been built, you can iterate the database with the available iterator methods.
-- You can iterate the database with the available iterator methods.
-- The iterator methods will walk the DATABASE set, and call for each element within the set a function that you provide.
-- The following iterator methods are currently available within the DATABASE:
--
-- * @{#DATABASE.ForEachAliveUnit}: Calls a function for each alive unit it finds within the DATABASE.
-- * @{#DATABASE.ForEachUnit}: Calls a function for each @{UNIT} it finds within the DATABASE.
-- * @{#DATABASE.ForEachGroup}: Calls a function for each @{GROUP} it finds within the DATABASE.
-- * @{#DATABASE.ForEachPlayer}: Calls a function for each player it finds within the DATABASE.
-- * @{#DATABASE.ForEachPlayerAlive}: Calls a function for each alive player it finds within the DATABASE.
-- * @{#DATABASE.ForEachClient}: Calls a function for each @{CLIENT} it finds within the DATABASE.
-- * @{#DATABASE.ForEachClientAlive}: Calls a function for each alive @{CLIENT} it finds within the DATABASE.
--
-- Planned iterators methods in development are (so these are not yet available):
--
-- * @{#DATABASE.ForEachUnit}: Calls a function for each unit contained within the DATABASE.
-- * @{#DATABASE.ForEachGroup}: Calls a function for each group contained within the DATABASE.
-- * @{#DATABASE.ForEachUnitInZone}: Calls a function for each unit within a certain zone contained within the DATABASE.
--
-- ====
-- @module Database
-- @author FlightControl
@ -70,6 +40,7 @@ Include.File( "Unit" )
Include.File( "Event" )
Include.File( "Client" )
--- DATABASE class
-- @type DATABASE
-- @extends Base#BASE
@ -85,34 +56,11 @@ DATABASE = {
DCSGroups = {},
UNITS = {},
GROUPS = {},
NavPoints = {},
Statics = {},
Players = {},
PlayersAlive = {},
PLAYERS = {},
PLAYERSALIVE = {},
CLIENTS = {},
ClientsAlive = {},
Filter = {
Coalitions = nil,
Categories = nil,
Types = nil,
Countries = nil,
UnitPrefixes = nil,
GroupPrefixes = nil,
},
FilterMeta = {
Coalitions = {
red = coalition.side.RED,
blue = coalition.side.BLUE,
neutral = coalition.side.NEUTRAL,
},
Categories = {
plane = Unit.Category.AIRPLANE,
helicopter = Unit.Category.HELICOPTER,
ground = Unit.Category.GROUND_UNIT,
ship = Unit.Category.SHIP,
structure = Unit.Category.STRUCTURE,
},
},
CLIENTSALIVE = {},
NavPoints = {},
}
local _DATABASECoalition =
@ -147,12 +95,13 @@ function DATABASE:New()
_EVENTDISPATCHER:OnCrash( self._EventOnDeadOrCrash, self )
-- Add database with registered clients and already alive players
-- Follow alive players and clients
_EVENTDISPATCHER:OnPlayerEnterUnit( self._EventOnPlayerEnterUnit, self )
_EVENTDISPATCHER:OnPlayerLeaveUnit( self._EventOnPlayerLeaveUnit, self )
self:_RegisterTemplates()
self:_RegisterDatabase()
self:_RegisterPlayers()
return self
end
@ -167,6 +116,7 @@ function DATABASE:FindUnit( UnitName )
return UnitFound
end
--- Adds a Unit based on the Unit Name in the DATABASE.
-- @param #DATABASE self
function DATABASE:AddUnit( DCSUnit, DCSUnitName )
@ -175,6 +125,7 @@ function DATABASE:AddUnit( DCSUnit, DCSUnitName )
self.UNITS[DCSUnitName] = UNIT:Register( DCSUnitName )
end
--- Deletes a Unit from the DATABASE based on the Unit Name.
-- @param #DATABASE self
function DATABASE:DeleteUnit( DCSUnitName )
@ -182,6 +133,7 @@ function DATABASE:DeleteUnit( DCSUnitName )
self.DCSUnits[DCSUnitName] = nil
end
--- Finds a CLIENT based on the ClientName.
-- @param #DATABASE self
-- @param #string ClientName
@ -192,6 +144,7 @@ function DATABASE:FindClient( ClientName )
return ClientFound
end
--- Adds a CLIENT based on the ClientName in the DATABASE.
-- @param #DATABASE self
function DATABASE:AddClient( ClientName )
@ -200,6 +153,7 @@ function DATABASE:AddClient( ClientName )
self:E( self.CLIENTS[ClientName]:GetClassNameAndID() )
end
--- Finds a GROUP based on the GroupName.
-- @param #DATABASE self
-- @param #string GroupName
@ -210,6 +164,7 @@ function DATABASE:FindGroup( GroupName )
return GroupFound
end
--- Adds a GROUP based on the GroupName in the DATABASE.
-- @param #DATABASE self
function DATABASE:AddGroup( DCSGroup, GroupName )
@ -218,6 +173,30 @@ function DATABASE:AddGroup( DCSGroup, GroupName )
self.GROUPS[GroupName] = GROUP:Register( GroupName )
end
--- Adds a player based on the Player Name in the DATABASE.
-- @param #DATABASE self
function DATABASE:AddPlayer( UnitName, PlayerName )
if PlayerName then
self:E( { "Add player for unit:", UnitName, PlayerName } )
self.PLAYERS[PlayerName] = PlayerName
self.PLAYERSALIVE[PlayerName] = PlayerName
self.CLIENTSALIVE[PlayerName] = self:FindClient( UnitName )
end
end
--- Deletes a player from the DATABASE based on the Player Name.
-- @param #DATABASE self
function DATABASE:DeletePlayer( PlayerName )
if PlayerName then
self:E( { "Clean player:", PlayerName } )
self.PLAYERSALIVE[PlayerName] = nil
self.CLIENTSALIVE[PlayerName] = nil
end
end
--- Instantiate new Groups within the DCSRTE.
-- This method expects EXACTLY the same structure as a structure within the ME, and needs 2 additional fields defined:
-- SpawnCountryID, SpawnCategoryID
@ -253,7 +232,6 @@ function DATABASE:Spawn( SpawnTemplate )
return SpawnGroup
end
--- Set a status to a Group within the Database, this to check crossing events for example.
function DATABASE:SetStatusGroup( GroupName, Status )
self:F2( Status )
@ -261,7 +239,6 @@ function DATABASE:SetStatusGroup( GroupName, Status )
self.Templates.Groups[GroupName].Status = Status
end
--- Get a status to a Group within the Database, this to check crossing events for example.
function DATABASE:GetStatusGroup( GroupName )
self:F2( Status )
@ -273,6 +250,7 @@ function DATABASE:GetStatusGroup( GroupName )
end
end
--- Private method that registers new Group Templates within the DATABASE Object.
-- @param #DATABASE self
-- @param #table GroupTemplate
@ -317,6 +295,7 @@ function DATABASE:_RegisterTemplate( GroupTemplate )
end
end
--- Private method that registers all alive players in the mission.
-- @param #DATABASE self
-- @return #DATABASE self
@ -328,9 +307,10 @@ function DATABASE:_RegisterPlayers()
self:T3( { "UnitData:", UnitData } )
if UnitData and UnitData:isExist() then
local UnitName = UnitData:getName()
if not self.PlayersAlive[UnitName] then
self:E( { "Add player for unit:", UnitName, UnitData:getPlayerName() } )
self.PlayersAlive[UnitName] = UnitData:getPlayerName()
local PlayerName = UnitData:getPlayerName()
if not self.PLAYERS[PlayerName] then
self:E( { "Add player for unit:", UnitName, PlayerName } )
self:AddPlayer( UnitName, PlayerName )
end
end
end
@ -339,6 +319,7 @@ function DATABASE:_RegisterPlayers()
return self
end
--- Private method that registers all datapoints within in the mission.
-- @param #DATABASE self
-- @return #DATABASE self
@ -384,14 +365,13 @@ function DATABASE:_EventOnBirth( Event )
self:F2( { Event } )
if Event.IniDCSUnit then
if self:_IsIncludeDCSUnit( Event.IniDCSUnit ) then
self:AddUnit( Event.IniDCSUnit, Event.IniDCSUnitName )
self:AddGroup( Event.IniDCSGroup, Event.IniDCSGroupName )
self:_EventOnPlayerEnterUnit( Event )
end
self:AddUnit( Event.IniDCSUnit, Event.IniDCSUnitName )
self:AddGroup( Event.IniDCSGroup, Event.IniDCSGroupName )
self:_EventOnPlayerEnterUnit( Event )
end
end
--- Handles the OnDead or OnCrash event for alive units set.
-- @param #DATABASE self
-- @param Event#EVENTDATA Event
@ -406,6 +386,7 @@ function DATABASE:_EventOnDeadOrCrash( Event )
end
end
--- Handles the OnPlayerEnterUnit event to fill the active players table (with the unit filter applied).
-- @param #DATABASE self
-- @param Event#EVENTDATA Event
@ -413,16 +394,14 @@ function DATABASE:_EventOnPlayerEnterUnit( Event )
self:F2( { Event } )
if Event.IniDCSUnit then
if self:_IsIncludeDCSUnit( Event.IniDCSUnit ) then
if not self.PlayersAlive[Event.IniDCSUnitName] then
self:E( { "Add player for unit:", Event.IniDCSUnitName, Event.IniDCSUnit:getPlayerName() } )
self.PlayersAlive[Event.IniDCSUnitName] = Event.IniDCSUnit:getPlayerName()
self.ClientsAlive[Event.IniDCSUnitName] = self.CLIENTS[ Event.IniDCSUnitName ]
end
local PlayerName = Event.IniDCSUnit:getPlayerName()
if not self.PLAYERSALIVE[PlayerName] then
self:AddPlayer( Event.IniDCSUnitName, PlayerName )
end
end
end
--- Handles the OnPlayerLeaveUnit event to clean the active players table.
-- @param #DATABASE self
-- @param Event#EVENTDATA Event
@ -430,19 +409,16 @@ function DATABASE:_EventOnPlayerLeaveUnit( Event )
self:F2( { Event } )
if Event.IniDCSUnit then
if self:_IsIncludeDCSUnit( Event.IniDCSUnit ) then
if self.PlayersAlive[Event.IniDCSUnitName] then
self:E( { "Cleaning player for unit:", Event.IniDCSUnitName, Event.IniDCSUnit:getPlayerName() } )
self.PlayersAlive[Event.IniDCSUnitName] = nil
self.ClientsAlive[Event.IniDCSUnitName] = nil
end
local PlayerName = Event.IniDCSUnit:getPlayerName()
if self.PLAYERSALIVE[PlayerName] then
self:DeletePlayer( PlayerName )
end
end
end
--- Iterators
--- Interate the DATABASE and call an interator function for the given set, providing the Object for each element within the set and optional parameters.
--- Iterate the DATABASE and call an iterator function for the given set, providing the Object for each element within the set and optional parameters.
-- @param #DATABASE self
-- @param #function IteratorFunction The function that will be called when there is an alive player in the database.
-- @return #DATABASE self
@ -485,9 +461,9 @@ function DATABASE:ForEach( IteratorFunction, arg, Set )
end
--- Interate the DATABASE and call an interator function for each **alive** unit, providing the Unit and optional parameters.
--- Iterate the DATABASE and call an iterator function for each **alive** unit, providing the DCSUnit and optional parameters.
-- @param #DATABASE self
-- @param #function IteratorFunction The function that will be called when there is an alive unit in the database. The function needs to accept a UNIT parameter.
-- @param #function IteratorFunction The function that will be called when there is an alive unit in the database. The function needs to accept a DCSUnit parameter.
-- @return #DATABASE self
function DATABASE:ForEachDCSUnit( IteratorFunction, ... )
self:F2( arg )
@ -497,20 +473,58 @@ function DATABASE:ForEachDCSUnit( IteratorFunction, ... )
return self
end
--- Interate the DATABASE and call an interator function for each **alive** player, providing the Unit of the player and optional parameters.
--- Iterate the DATABASE and call an iterator function for each **alive** UNIT, providing the UNIT and optional parameters.
-- @param #DATABASE self
-- @param #function IteratorFunction The function that will be called when there is an alive player in the database. The function needs to accept a UNIT parameter.
-- @param #function IteratorFunction The function that will be called when there is an alive UNIT in the database. The function needs to accept a UNIT parameter.
-- @return #DATABASE self
function DATABASE:ForEachUnit( IteratorFunction, ... )
self:F2( arg )
self:ForEach( IteratorFunction, arg, self.UNITS )
return self
end
--- Iterate the DATABASE and call an iterator function for each **alive** GROUP, providing the GROUP and optional parameters.
-- @param #DATABASE self
-- @param #function IteratorFunction The function that will be called when there is an alive GROUP in the database. The function needs to accept a GROUP parameter.
-- @return #DATABASE self
function DATABASE:ForEachGroup( IteratorFunction, ... )
self:F2( arg )
self:ForEach( IteratorFunction, arg, self.GROUPS )
return self
end
--- Iterate the DATABASE and call an iterator function for each player, providing the player name and optional parameters.
-- @param #DATABASE self
-- @param #function IteratorFunction The function that will be called when there is an player in the database. The function needs to accept the player name.
-- @return #DATABASE self
function DATABASE:ForEachPlayer( IteratorFunction, ... )
self:F2( arg )
self:ForEach( IteratorFunction, arg, self.PlayersAlive )
self:ForEach( IteratorFunction, arg, self.PLAYERS )
return self
end
--- Interate the DATABASE and call an interator function for each client, providing the Client to the function and optional parameters.
--- Iterate the DATABASE and call an iterator function for each **alive** player, providing the Unit of the player and optional parameters.
-- @param #DATABASE self
-- @param #function IteratorFunction The function that will be called when there is an alive player in the database. The function needs to accept a UNIT parameter.
-- @return #DATABASE self
function DATABASE:ForEachPlayerAlive( IteratorFunction, ... )
self:F2( arg )
self:ForEach( IteratorFunction, arg, self.PLAYERSALIVE )
return self
end
--- Iterate the DATABASE and call an iterator function for each CLIENT, providing the CLIENT to the function and optional parameters.
-- @param #DATABASE self
-- @param #function IteratorFunction The function that will be called when there is an alive player in the database. The function needs to accept a CLIENT parameter.
-- @return #DATABASE self
@ -522,8 +536,20 @@ function DATABASE:ForEachClient( IteratorFunction, ... )
return self
end
--- Iterate the DATABASE and call an iterator function for each **ALIVE** CLIENT, providing the CLIENT to the function and optional parameters.
-- @param #DATABASE self
-- @param #function IteratorFunction The function that will be called when there is an alive CLIENT in the database. The function needs to accept a CLIENT parameter.
-- @return #DATABASE self
function DATABASE:ForEachClientAlive( IteratorFunction, ... )
self:F2( arg )
self:ForEach( IteratorFunction, arg, self.CLIENTSALIVE )
function DATABASE:ScanEnvironment()
return self
end
function DATABASE:_RegisterTemplates()
self:F2()
self.Navpoints = {}
@ -586,110 +612,9 @@ function DATABASE:ScanEnvironment()
end --if coa_name == 'red' or coa_name == 'blue' and type(coa_data) == 'table' then
end --for coa_name, coa_data in pairs(mission.coalition) do
self:_RegisterDatabase()
self:_RegisterPlayers()
return self
end
---
-- @param #DATABASE self
-- @param DCSUnit#Unit DCSUnit
-- @return #DATABASE self
function DATABASE:_IsIncludeDCSUnit( DCSUnit )
self:F2( DCSUnit )
local DCSUnitInclude = true
if self.Filter.Coalitions then
local DCSUnitCoalition = false
for CoalitionID, CoalitionName in pairs( self.Filter.Coalitions ) do
self:T2( { "Coalition:", DCSUnit:getCoalition(), self.FilterMeta.Coalitions[CoalitionName], CoalitionName } )
if self.FilterMeta.Coalitions[CoalitionName] and self.FilterMeta.Coalitions[CoalitionName] == DCSUnit:getCoalition() then
DCSUnitCoalition = true
end
end
DCSUnitInclude = DCSUnitInclude and DCSUnitCoalition
end
if self.Filter.Categories then
local DCSUnitCategory = false
for CategoryID, CategoryName in pairs( self.Filter.Categories ) do
self:T2( { "Category:", DCSUnit:getDesc().category, self.FilterMeta.Categories[CategoryName], CategoryName } )
if self.FilterMeta.Categories[CategoryName] and self.FilterMeta.Categories[CategoryName] == DCSUnit:getDesc().category then
DCSUnitCategory = true
end
end
DCSUnitInclude = DCSUnitInclude and DCSUnitCategory
end
if self.Filter.Types then
local DCSUnitType = false
for TypeID, TypeName in pairs( self.Filter.Types ) do
self:T2( { "Type:", DCSUnit:getTypeName(), TypeName } )
if TypeName == DCSUnit:getTypeName() then
DCSUnitType = true
end
end
DCSUnitInclude = DCSUnitInclude and DCSUnitType
end
if self.Filter.Countries then
local DCSUnitCountry = false
for CountryID, CountryName in pairs( self.Filter.Countries ) do
self:T2( { "Country:", DCSUnit:getCountry(), CountryName } )
if country.id[CountryName] == DCSUnit:getCountry() then
DCSUnitCountry = true
end
end
DCSUnitInclude = DCSUnitInclude and DCSUnitCountry
end
if self.Filter.UnitPrefixes then
local DCSUnitPrefix = false
for UnitPrefixId, UnitPrefix in pairs( self.Filter.UnitPrefixes ) do
self:T2( { "Unit Prefix:", string.find( DCSUnit:getName(), UnitPrefix, 1 ), UnitPrefix } )
if string.find( DCSUnit:getName(), UnitPrefix, 1 ) then
DCSUnitPrefix = true
end
end
DCSUnitInclude = DCSUnitInclude and DCSUnitPrefix
end
self:T2( DCSUnitInclude )
return DCSUnitInclude
end
---
-- @param #DATABASE self
-- @param DCSUnit#Unit DCSUnit
-- @return #DATABASE self
function DATABASE:_IsAliveDCSUnit( DCSUnit )
self:F2( DCSUnit )
local DCSUnitAlive = false
if DCSUnit and DCSUnit:isExist() and DCSUnit:isActive() then
if self.DCSUnits[DCSUnit:getName()] then
DCSUnitAlive = true
end
end
self:T2( DCSUnitAlive )
return DCSUnitAlive
end
---
-- @param #DATABASE self
-- @param DCSGroup#Group DCSGroup
-- @return #DATABASE self
function DATABASE:_IsAliveDCSGroup( DCSGroup )
self:F2( DCSGroup )
local DCSGroupAlive = false
if DCSGroup and DCSGroup:isExist() then
if self.DCSGroups[DCSGroup:getName()] then
DCSGroupAlive = true
end
end
self:T2( DCSGroupAlive )
return DCSGroupAlive
end

View File

@ -11,5 +11,5 @@ Include.File( "Event" )
_EVENTDISPATCHER = EVENT:New() -- #EVENT
--- Declare the main database object, which is used internally by the MOOSE classes.
_DATABASE = DATABASE:New():ScanEnvironment() -- Database#DATABASE
_DATABASE = DATABASE:New() -- Database#DATABASE

View File

@ -325,7 +325,7 @@ end
--- Flushes the current SET contents in the log ... (for debug reasons).
-- @param #SET self
-- @return #SET self
-- @return #string A string with the names of the objects.
function SET:Flush()
self:F3()
@ -334,6 +334,8 @@ function SET:Flush()
ObjectNames = ObjectNames .. ObjectName .. ", "
end
self:T( { "Objects in Set:", ObjectNames } )
return ObjectNames
end

View File

@ -88,6 +88,21 @@ DBRedVehicles
:ForEachUnit( function( MooseUnit )
DBRedVehicles:T( MooseUnit:GetName() )
end )
local function FlushPlayers()
_DATABASE:E( "FlushPlayers" )
_DATABASE
:ForEachPlayerAlive( function( Player )
_DATABASE:E( Player )
MESSAGE:New( Player, "Test", 5, "Player Test" ):ToAll()
return true
end )
return true
end
_DATABASE:E( "Schedule" )
local PlayerShow = SCHEDULER:New( nil, FlushPlayers, {}, 1, 10 )