From ecf80e52098596e6c9766e79e97fa84a65a64f6b Mon Sep 17 00:00:00 2001 From: Sven Van de Velde Date: Sun, 21 Feb 2016 19:34:48 +0100 Subject: [PATCH] Changes of loading and cleanup. Added dynamic and static loading strategies for MOOSE of a mission file. --- .../Moose_Load_Dynamic.lua | 25 ++- Loaders/Moose_Load_Embedded.lua | 23 +++ Loaders/Moose_Test.lua | 159 ++++++++++++++++++ Moose/Base.lua | 21 ++- Moose/ClientBug.lua | 50 ------ Moose/Mission.lua | 58 +++---- Moose/SlingLoadHookTask.lua | 39 ----- Moose/SlingLoadUnHookTask.lua | 38 ----- Moose/Spawn.lua | 2 + 9 files changed, 243 insertions(+), 172 deletions(-) rename Moose/Moose.lua => Loaders/Moose_Load_Dynamic.lua (90%) create mode 100644 Loaders/Moose_Load_Embedded.lua create mode 100644 Loaders/Moose_Test.lua delete mode 100644 Moose/ClientBug.lua delete mode 100644 Moose/SlingLoadHookTask.lua delete mode 100644 Moose/SlingLoadUnHookTask.lua diff --git a/Moose/Moose.lua b/Loaders/Moose_Load_Dynamic.lua similarity index 90% rename from Moose/Moose.lua rename to Loaders/Moose_Load_Dynamic.lua index 4c27ec554..e12d51570 100644 --- a/Moose/Moose.lua +++ b/Loaders/Moose_Load_Dynamic.lua @@ -1,22 +1,13 @@ local base = _G - env.info("Loading MOOSE " .. base.timer.getAbsTime() ) -function script_path() - local str = debug.getinfo(2, "S").source - return str:match("(.*/)"):sub(1,-2) -end - - Include = {} -Include.MissionPath = script_path() .. "Mission/" -Include.ProgramPath = "Scripts/Moose/Moose/" - -env.info( "Include.MissionPath = " .. Include.MissionPath) -env.info( "Include.ProgramPath = " .. Include.ProgramPath) -Include.Files = {} +Include.Path = function() + local str = debug.getinfo(2, "S").source + return str:match("(.*/)"):sub(1,-2):gsub("\\","/") +end Include.File = function( IncludeFile ) if not Include.Files[ IncludeFile ] then @@ -39,6 +30,14 @@ Include.File = function( IncludeFile ) end end +Include.ProgramPath = "Scripts/Moose/Moose/" +Include.MissionPath = Include.Path() + +env.info( "Include.ProgramPath = " .. Include.ProgramPath) +env.info( "Include.MissionPath = " .. Include.MissionPath) + +Include.Files = {} + Include.File( "Database" ) env.info("Loaded MOOSE Include Engine") \ No newline at end of file diff --git a/Loaders/Moose_Load_Embedded.lua b/Loaders/Moose_Load_Embedded.lua new file mode 100644 index 000000000..4314a929d --- /dev/null +++ b/Loaders/Moose_Load_Embedded.lua @@ -0,0 +1,23 @@ + +local base = _G +env.info("Loading MOOSE " .. base.timer.getAbsTime() ) + +Include = {} + +Include.Path = function() + local str = debug.getinfo(2, "S").source + return str:match("(.*/)"):sub(1,-2):gsub("\\","/") +end + +Include.File = function( IncludeFile ) +end + +Include.ProgramPath = "Scripts/Moose/Moose/" +Include.MissionPath = Include.Path() + +env.info( "Include.ProgramPath = " .. Include.ProgramPath) +env.info( "Include.MissionPath = " .. Include.MissionPath) + +Include.Files = {} + +env.info("Loaded MOOSE Include Engine") \ No newline at end of file diff --git a/Loaders/Moose_Test.lua b/Loaders/Moose_Test.lua new file mode 100644 index 000000000..fc6979ea9 --- /dev/null +++ b/Loaders/Moose_Test.lua @@ -0,0 +1,159 @@ + +local base = _G + +local MOOSE_Version = "0.1.1.1" + +env.info("Loading MOOSE " .. base.timer.getAbsTime() ) + +function script_path() + local str = debug.getinfo(2, "S").source + return str:match("(.*/)"):sub(1,-2):gsub("\\","/") +end + + +Include = {} + +Include.ProgramPath = "Scripts/Moose/Moose/" +Include.MissionPath = script_path() + +env.info( "Include.ProgramPath = " .. Include.ProgramPath) +env.info( "Include.MissionPath = " .. Include.MissionPath) +Include.Files = {} + +Include.FileIn = function(fileName, table) +-- env.info( fileName ) + local chunk, errMsg = base.loadfile(fileName) + if chunk ~= nil then + env.info( "chunk assigned " ) + env.info( Include.oneLineSerialize( chunk ) ) + base.setfenv(chunk, table) + chunk() + if table.MOOSE_Version then + env.info( table.MOOSE_Version ) + end + return chunk + else + return nil, errMsg + end +end + +Include.MisFiles = {} + +Include.FileName = function( num ) + local hexstr = '0123456789ABCDEF' + local s = '' + while num > 0 do + local mod = math.fmod(num, 16) + s = string.sub(hexstr, mod+1, mod+1) .. s + num = math.floor(num / 16) + end + if s == '' then s = '0' end +-- env.info( string.format( "~mis" .. "%8s", "00000000" .. s ) ) + return string.format( "~mis" .. "%s", string.sub( "00000000" .. s, -8 ) ) +end + +Include.ScanFiles = function() + + local i = 0 + while i <= 32767 do + local FileName = Include.FileName( i ) + local FileChunk = {} + local FileChunk = Include.FileIn( Include.MissionPath .. FileName, FileChunk ) + if FileChunk then + end + i = i + 1 + end +end + + +Include.File = function( IncludeFile ) + if not Include.Files[ IncludeFile ] then + Include.Files[IncludeFile] = IncludeFile + env.info( "Include:" .. IncludeFile .. " from " .. Include.ProgramPath ) + local f = base.loadfile( Include.ProgramPath .. IncludeFile .. ".lua" ) + if f == nil then + env.info( "Include:" .. IncludeFile .. " from " .. Include.MissionPath ) + local f = base.loadfile( Include.MissionPath .. IncludeFile .. ".lua" ) + if f == nil then + error ("Could not load MOOSE file " .. IncludeFile .. ".lua" ) + else + env.info( "Include:" .. IncludeFile .. " loaded from " .. Include.MissionPath ) + return f() + end + else + env.info( "Include:" .. IncludeFile .. " loaded from " .. Include.ProgramPath ) + return f() + end + end +end + +--porting in Slmod's "safestring" basic serialize +Include.basicSerialize = function(s) + if s == nil then + return "\"\"" + else + if ((type(s) == 'number') or (type(s) == 'boolean') or (type(s) == 'function') or (type(s) == 'table') or (type(s) == 'userdata') ) then + return tostring(s) + elseif type(s) == 'string' then + s = string.format('%q', s) + return s + end + end +end + +-- porting in Slmod's serialize_slmod2 +Include.oneLineSerialize = function(tbl) -- serialization of a table all on a single line, no comments, made to replace old get_table_string function + if type(tbl) == 'table' then --function only works for tables! + + local tbl_str = {} + + tbl_str[#tbl_str + 1] = '{' + + for ind,val in pairs(tbl) do -- serialize its fields + if type(ind) == "number" then + tbl_str[#tbl_str + 1] = '[' + tbl_str[#tbl_str + 1] = tostring(ind) + tbl_str[#tbl_str + 1] = ']=' + else --must be a string + tbl_str[#tbl_str + 1] = '[' + tbl_str[#tbl_str + 1] = Include.basicSerialize(ind) + tbl_str[#tbl_str + 1] = ']=' + end + + if ((type(val) == 'number') or (type(val) == 'boolean')) then + tbl_str[#tbl_str + 1] = tostring(val) + tbl_str[#tbl_str + 1] = ',' + elseif type(val) == 'string' then + tbl_str[#tbl_str + 1] = Include.basicSerialize(val) + tbl_str[#tbl_str + 1] = ',' + elseif type(val) == 'nil' then -- won't ever happen, right? + tbl_str[#tbl_str + 1] = 'nil,' + elseif type(val) == 'table' then + if ind == "__index" then + tbl_str[#tbl_str + 1] = "__index" + tbl_str[#tbl_str + 1] = ',' --I think this is right, I just added it + else + tbl_str[#tbl_str + 1] = Include.oneLineSerialize(val) + tbl_str[#tbl_str + 1] = ',' --I think this is right, I just added it + end + elseif type(val) == 'function' then + tbl_str[#tbl_str + 1] = "function " .. tostring(ind) + tbl_str[#tbl_str + 1] = ',' --I think this is right, I just added it + else + env.info('unable to serialize value type ' .. Include.basicSerialize(type(val)) .. ' at index ' .. tostring(ind)) + env.info( debug.traceback() ) + end + + end + tbl_str[#tbl_str + 1] = '}' + return table.concat(tbl_str) + else + return tostring(tbl) + end +end + +Include.ScanFiles( ) + +Include.File( "Database" ) + +env.info("Loaded MOOSE Include Engine") \ No newline at end of file diff --git a/Moose/Base.lua b/Moose/Base.lua index 59edff66e..dc4029ff0 100644 --- a/Moose/Base.lua +++ b/Moose/Base.lua @@ -7,9 +7,9 @@ Include.File( "Routines" ) BASE = { ClassName = "BASE", + TraceOn = false, ClassID = 0, Events = {} - } --- The base constructor. This is the top top class of all classed defined within the MOOSE. @@ -188,3 +188,22 @@ function BASE:onEvent(event) end +-- Trace section + + +function BASE:T( Arguments ) + + if BASE.TraceOn then + + local DebugInfo = debug.getinfo( 2, "nl" ) + + local Function = "function" + if DebugInfo.name then + Function = DebugInfo.name + end + + local Line = DebugInfo.currentline + + env.info( string.format( "%6d/%1s:%20s.%s\(%s\)" , Line, "T", self.ClassName, Function .. routines.utils.oneLineSerialize( Arguments ) ) ) + end +end diff --git a/Moose/ClientBug.lua b/Moose/ClientBug.lua deleted file mode 100644 index 12fc34df5..000000000 --- a/Moose/ClientBug.lua +++ /dev/null @@ -1,50 +0,0 @@ ---- Bug Client Activation Multiplayer Classes --- @classmod CLIENTBUG - -Include.File( "Routines" ) -Include.File( "Base" ) - - -CLIENTBUG = { - ClassName = "CLIENTBUG", -} - -function CLIENTBUG:New( ) -trace.f( self.ClassName ) - - -- Arrange meta tables - local self = BASE:Inherit( self, BASE:New() ) - - self.ActiveClients = {} - - self.ClientBugWorkaround = routines.scheduleFunction( self._ClientBugWorkaround, { self }, timer.getTime() + 1, 0.1 ) - - return self -end - -function CLIENTBUG:_ClientBugWorkaround() - - -- Get the units of the players - local CoalitionsData = { AlivePlayersRed = coalition.getPlayers( coalition.side.RED ), AlivePlayersBlue = coalition.getPlayers( coalition.side.BLUE ) } - - for CoalitionId, CoalitionData in pairs( CoalitionsData ) do - trace.i( self.ClassName, CoalitionData ) - - for UnitId, UnitData in pairs( CoalitionData ) do - trace.i( self.ClassName, UnitData ) - - if UnitData and UnitData:isExist() then - - local UnitSkill = _Database.Units[UnitData:getName()].Template.skill - trace.i( self.ClassName, "UnitSkill = " .. UnitSkill ) - - if UnitSkill == "Client" then - - -- Generate birth event - self:CreateEventBirth( 0, UnitData, UnitData:getName(), 0, 0 ) - end - end - end - end - -end diff --git a/Moose/Mission.lua b/Moose/Mission.lua index 62a9f277e..fdd78404f 100644 --- a/Moose/Mission.lua +++ b/Moose/Mission.lua @@ -31,12 +31,11 @@ MISSION = { function MISSION:Meta() -trace.f(self.ClassName) - -- Arrange meta tables - local Child = BASE:Inherit( self, BASE:New() ) -trace.r( self.ClassName, "", { Child } ) - return Child + local self = BASE:Inherit( self, BASE:New() ) + self:T() + + return self end --- This is the main MISSION declaration method. Each Mission is like the master or a Mission orchestration between, Clients, Tasks, Stages etc. @@ -56,8 +55,9 @@ end -- local Mission = MISSIONSCHEDULER.AddMission( 'NATO Sling Load', 'Operational', 'Fly to the cargo pickup zone at Dzegvi or Kaspi, and sling the cargo to Soganlug airbase.', 'NATO' ) -- local Mission = MISSIONSCHEDULER.AddMission( 'Rescue secret agent', 'Tactical', 'In order to be in full control of the situation, we need you to rescue a secret agent from the woods behind enemy lines. Avoid the Russian defenses and rescue the agent. Keep south until Khasuri, and keep your eyes open for any SAM presence. The agent is located at waypoint 4 on your kneeboard.', 'NATO' ) function MISSION:New( MissionName, MissionPriority, MissionBriefing, MissionCoalition ) -trace.f(self.ClassName, { MissionName, MissionPriority, MissionBriefing, MissionCoalition } ) + self = MISSION:Meta() + self:T({ MissionName, MissionPriority, MissionBriefing, MissionCoalition }) local Valid = true @@ -73,20 +73,19 @@ trace.f(self.ClassName, { MissionName, MissionPriority, MissionBriefing, Mission self.MissionCoalition = MissionCoalition end -trace.r( self.ClassName, "" ) return self end --- Returns if a Mission has completed. -- @treturn bool function MISSION:IsCompleted() -trace.f(self.ClassName) + self:T() return self.MissionStatus == "ACCOMPLISHED" end --- Set a Mission to completed. function MISSION:Completed() -trace.f(self.ClassName) + self:T() self.MissionStatus = "ACCOMPLISHED" self:StatusToClients() end @@ -94,13 +93,13 @@ end --- Returns if a Mission is ongoing. -- treturn bool function MISSION:IsOngoing() -trace.f(self.ClassName) + self:T() return self.MissionStatus == "ONGOING" end --- Set a Mission to ongoing. function MISSION:Ongoing() -trace.f(self.ClassName) + self:T() self.MissionStatus = "ONGOING" --self:StatusToClients() end @@ -108,13 +107,13 @@ end --- Returns if a Mission is pending. -- treturn bool function MISSION:IsPending() -trace.f(self.ClassName) + self:T() return self.MissionStatus == "PENDING" end --- Set a Mission to pending. function MISSION:Pending() -trace.f(self.ClassName) + self:T() self.MissionStatus = "PENDING" self:StatusToClients() end @@ -122,31 +121,31 @@ end --- Returns if a Mission has failed. -- treturn bool function MISSION:IsFailed() -trace.f(self.ClassName) + self:T() return self.MissionStatus == "FAILED" end --- Set a Mission to failed. function MISSION:Failed() -trace.f(self.ClassName) + self:T() self.MissionStatus = "FAILED" self:StatusToClients() end --- Send the status of the MISSION to all Clients. function MISSION:StatusToClients() -trace.f(self.ClassName) + self:T() if self.MissionReportFlash then for ClientID, Client in pairs( self._Clients ) do Client:Message( self.MissionCoalition .. ' "' .. self.Name .. '": ' .. self.MissionStatus .. '! ( ' .. self.MissionPriority .. ' mission ) ', 10, self.Name .. '/Status', "Mission Command: Mission Status") end end -trace.e() end --- Handles the reporting. After certain time intervals, a MISSION report MESSAGE will be shown to All Players. function MISSION:ReportTrigger() -trace.f(self.ClassName) + self:T() + if self.MissionReportShow == true then self.MissionReportShow = false trace.r( "MISSION", "1", { true } ) @@ -171,7 +170,8 @@ end --- Report the status of all MISSIONs to all active Clients. function MISSION:ReportToAll() -trace.f(self.ClassName) + self:T() + local AlivePlayers = '' for ClientID, Client in pairs( self._Clients ) do if Client:ClientGroup() then @@ -192,7 +192,6 @@ trace.f(self.ClassName) TaskText = TaskText .. " - Task " .. TaskID .. ": " .. TaskData.Name .. ": " .. TaskData:GetGoalProgress() .. "\n" end MESSAGE:New( self.MissionCoalition .. ' "' .. self.Name .. '": ' .. self.MissionStatus .. ' ( ' .. self.MissionPriority .. ' mission )' .. AlivePlayers .. "\n" .. TaskText:gsub("\n$",""), "Mission Command: Mission Report", 10, self.Name .. '/Status'):ToAll() -trace.e() end @@ -233,16 +232,15 @@ end -- local Mission = MISSIONSCHEDULER.AddMission( 'NATO Transport Troops', 'Operational', 'Transport 3 groups of air defense engineers from our barracks "Gold" and "Titan" to each patriot battery control center to activate our air defenses.', 'NATO' ) -- Mission:AddGoalFunction( DeployPatriotTroopsGoal ) function MISSION:AddGoalFunction( GoalFunction ) -trace.f(self.ClassName) + self:T() self.GoalFunction = GoalFunction -trace.e() end --- Show the briefing of the MISSION to the CLIENT. -- @tparam CLIENT Client to show briefing to. -- @treturn CLIENT function MISSION:ShowBriefing( Client ) -trace.f(self.ClassName, { Client.ClientName } ) + self:T( { Client.ClientName } ) if not Client.ClientBriefingShown then Client.ClientBriefingShown = true @@ -266,7 +264,7 @@ end -- Mission:AddClient( CLIENT:New( 'US UH-1H*HOT-Deploy Troops 2', 'Transport 3 groups of air defense engineers from our barracks "Gold" and "Titan" to each patriot battery control center to activate our air defenses.' ):Transport() ) -- Mission:AddClient( CLIENT:New( 'US UH-1H*RAMP-Deploy Troops 4', 'Transport 3 groups of air defense engineers from our barracks "Gold" and "Titan" to each patriot battery control center to activate our air defenses.' ):Transport() ) function MISSION:AddClient( Client ) -trace.f(self.ClassName, { Client } ) + self:T( { Client } ) local Valid = true @@ -285,8 +283,7 @@ end -- -- Seach for Client "Bomber" within the Mission. -- local BomberClient = Mission:FindClient( "Bomber" ) function MISSION:FindClient( ClientName ) -trace.f(self.ClassName) -trace.r( "", "", { self._Clients[ClientName] } ) + self:T( { self._Clients[ClientName] } ) return self._Clients[ClientName] end @@ -317,13 +314,12 @@ end -- Mission:AddTask( DeployTask, 2 ) function MISSION:AddTask( Task, TaskNumber ) -trace.f(self.ClassName) + self:T() self._Tasks[TaskNumber] = Task self._Tasks[TaskNumber]:EnableEvents() self._Tasks[TaskNumber].ID = TaskNumber -trace.r( self.ClassName, "" ) return Task end @@ -335,7 +331,7 @@ trace.r( self.ClassName, "" ) -- Task2 = Mission:GetTask( 2 ) function MISSION:GetTask( TaskNumber ) -trace.f(self.ClassName) + self:T() local Valid = true @@ -359,7 +355,7 @@ end -- Tasks = Mission:GetTasks() -- env.info( "Task 2 Completion = " .. Tasks[2]:GetGoalPercentage() .. "%" ) function MISSION:GetTasks() -trace.f(self.ClassName) + self:T() return self._Tasks end @@ -367,7 +363,7 @@ end --- Add Cargo to the mission... Cargo functionality needs to be reworked a bit, so this is still under construction. I need to make a CARGO Class... SpawnCargo = {} function MISSION:AddCargo( Cargos ) -trace.f(self.ClassName, { Cargos } ) + self:T( { Cargos } ) if type( Cargos ) == "table" then for CargoID, Cargo in pairs( Cargos ) do diff --git a/Moose/SlingLoadHookTask.lua b/Moose/SlingLoadHookTask.lua deleted file mode 100644 index 3248d4f95..000000000 --- a/Moose/SlingLoadHookTask.lua +++ /dev/null @@ -1,39 +0,0 @@ ---- A SLINGLOADHOOKTASK will orchestrate the sling-load hook activity to slingload a CARGO from a specific landing zone(s). --- @classmod SLINGLOADHOOKTASK - -Include.File("Task") - -SLINGLOADHOOKTASK = { - ClassName = "SLINGLOADHOOKTASK", - GoalVerb = "Hook and Sling Cargo" -} - ---- Creates a new SLINGLOADHOOKTASK. --- @tparam table{string,...}|string LandingZones Table or name of the zone(s) where Cargo is to be loaded. --- @tparam table{string,...)|string CargoPrefixes is the name or prefix of the name of the Cargo objects defined within the DCS ME. --- @treturn SLINGLOADHOOKTASK -function SLINGLOADHOOKTASK:New( LandingZones, CargoPrefixes ) -trace.f(self.ClassName) - - local self = BASE:Inherit( self, TASK:New() ) - - self.Name = 'Hook and Sling Cargo' - self.TaskBriefing = "Task: Hook" - - if type( LandingZones ) == "table" then - self.LandingZones = LandingZones - else - self.LandingZones = { LandingZones } - end - - if type( CargoPrefixes ) == "table" then - self.CargoPrefixes = CargoPrefixes - else - self.CargoPrefixes = { CargoPrefixes } - end - - self.Stages = { STAGEBRIEF:New(), STAGESTART:New(), STAGEROUTE:New(), STAGE_SLINGLOAD_HOOK:New(), STAGEDONE:New() } - self:SetStage( 1 ) - - return self -end diff --git a/Moose/SlingLoadUnHookTask.lua b/Moose/SlingLoadUnHookTask.lua deleted file mode 100644 index 6ac3bd131..000000000 --- a/Moose/SlingLoadUnHookTask.lua +++ /dev/null @@ -1,38 +0,0 @@ ---- A SLINGLOADUNHOOKTASK will orchestrate the sling-load unhook activity to (sling)load a CARGO and deploy it in a specific landing zone(s). --- @classmod SLINGLOADUNHOOKTASK - -Include.File("Task") - -SLINGLOADUNHOOKTASK = { - ClassName = "SLINGLOADUNHOOKTASK", - GoalVerb = "Sling and UnHook Cargo" -} - ---- Creates a new SLINGLOADUNHOOKTASK. --- @tparam table{string,...}|string LandingZones Table or name of the zone(s) where Cargo is to be loaded. --- @tparam table{string,...}|string CargoPrefixes is the name or prefix of the name of the Cargo objects defined within the DCS ME. -function SLINGLOADUNHOOKTASK:New( LandingZones, CargoPrefixes ) -trace.f(self.ClassName) - - local self = BASE:Inherit( self, TASK:New() ) - - self.Name = 'Sling and Unhook Cargo' - self.TaskBriefing = "Task: UnHook" - - if type( LandingZones ) == "table" then - self.LandingZones = LandingZones - else - self.LandingZones = { LandingZones } - end - - if type( CargoPrefixes ) == "table" then - self.CargoPrefixes = CargoPrefixes - else - self.CargoPrefixes = { CargoPrefixes } - end - - self.Stages = { STAGEBRIEF:New(), STAGESTART:New(), STAGEROUTE:New(), STAGE_SLINGLOAD_UNHOOK:New(), STAGEDONE:New() } - self:SetStage( 1 ) - - return self -end diff --git a/Moose/Spawn.lua b/Moose/Spawn.lua index 5b9157f99..0fdd5d521 100644 --- a/Moose/Spawn.lua +++ b/Moose/Spawn.lua @@ -2,6 +2,8 @@ -- @classmod SPAWN -- @author Flightcontrol +MOOSE_Version = "0.1.1.1" + Include.File( "Routines" ) Include.File( "Base" ) Include.File( "Database" )