diff --git a/Moose Development/Moose/Core/Base.lua b/Moose Development/Moose/Core/Base.lua index 9ceb850bb..ac045f4ed 100644 --- a/Moose Development/Moose/Core/Base.lua +++ b/Moose Development/Moose/Core/Base.lua @@ -127,6 +127,24 @@ function BASE:_Destructor() self:EventRemoveAll() end +function BASE:_SetDestructor() + + local proxy = newproxy(true) + local proxyMeta = getmetatable(proxy) + + proxyMeta.__gc = function () + -- env.info("In __gc for " .. Child:GetClassNameAndID() ) + if self._Destructor then + self:_Destructor() + end + end + + -- keep the userdata from newproxy reachable until the object + -- table is about to be garbage-collected - then the __gc hook + -- will be invoked and the destructor called + rawset( self, '__proxy', proxy ) + +end --- This is the worker method to inherit from a parent class. -- @param #BASE self @@ -141,21 +159,7 @@ function BASE:Inherit( Child, Parent ) setmetatable( Child, Parent ) Child.__index = Child - local proxy = newproxy(true) - local proxyMeta = getmetatable(proxy) - - proxyMeta.__gc = function () - -- env.info("In __gc for " .. Child:GetClassNameAndID() ) - if Child._Destructor then - Child:_Destructor() - end - end - - -- keep the userdata from newproxy reachable until the object - -- table is about to be garbage-collected - then the __gc hook - -- will be invoked and the destructor called - rawset(Child, '__proxy', proxy) - + Child:_SetDestructor() end --self:T( 'Inherited from ' .. Parent.ClassName ) return Child diff --git a/Moose Development/Moose/Core/StateMachine.lua b/Moose Development/Moose/Core/StateMachine.lua index 1344d8c03..9c89f6d7f 100644 --- a/Moose Development/Moose/Core/StateMachine.lua +++ b/Moose Development/Moose/Core/StateMachine.lua @@ -98,6 +98,8 @@ function STATEMACHINE:AddProcess( From, Event, Process, ReturnEvents ) sub.event = "Start" sub.ReturnEvents = ReturnEvents + -- Make the reference table weak. + setmetatable( self.options.subs, { __mode = "v" } ) self.options.subs[Event] = sub self:_submap( self.subs, sub, nil ) @@ -137,13 +139,16 @@ function STATEMACHINE:_submap( subs, sub, name ) self:E( { sub = sub, name = name } ) subs[sub.FromParent] = subs[sub.FromParent] or {} subs[sub.FromParent][sub.EventParent] = subs[sub.FromParent][sub.EventParent] or {} - local Index = #subs[sub.FromParent][sub.EventParent] + 1 - subs[sub.FromParent][sub.EventParent][Index] = {} - subs[sub.FromParent][sub.EventParent][Index].fsm = sub.fsm - subs[sub.FromParent][sub.EventParent][Index].event = sub.event - subs[sub.FromParent][sub.EventParent][Index].ReturnEvents = sub.ReturnEvents or {} -- these events need to be given to find the correct continue event ... if none given, the processing will stop. - subs[sub.FromParent][sub.EventParent][Index].name = name - subs[sub.FromParent][sub.EventParent][Index].fsmparent = self + + -- Make the reference table weak. + setmetatable( subs[sub.FromParent][sub.EventParent], { __mode = "k" } ) + + subs[sub.FromParent][sub.EventParent][sub] = {} + subs[sub.FromParent][sub.EventParent][sub].fsm = sub.fsm + subs[sub.FromParent][sub.EventParent][sub].event = sub.event + subs[sub.FromParent][sub.EventParent][sub].ReturnEvents = sub.ReturnEvents or {} -- these events need to be given to find the correct continue event ... if none given, the processing will stop. + subs[sub.FromParent][sub.EventParent][sub].name = name + subs[sub.FromParent][sub.EventParent][sub].fsmparent = self end diff --git a/Moose Development/Moose/Process/Account.lua b/Moose Development/Moose/Process/Account.lua index cd2b94eb3..804b41fd9 100644 --- a/Moose Development/Moose/Process/Account.lua +++ b/Moose Development/Moose/Process/Account.lua @@ -201,7 +201,7 @@ do -- PROCESS_ACCOUNT_DEADS function PROCESS_ACCOUNT_DEADS:_Destructor() self:E("_Destructor") - self:RemoveEventsAll() + self:EventRemoveAll() end diff --git a/Moose Development/Moose/Process/Smoke.lua b/Moose Development/Moose/Process/Smoke.lua index 69e926efb..62805b9e4 100644 --- a/Moose Development/Moose/Process/Smoke.lua +++ b/Moose Development/Moose/Process/Smoke.lua @@ -144,12 +144,12 @@ do -- PROCESS_SMOKE_TARGETS_ZONE ClassName = "PROCESS_SMOKE_TARGETS_ZONE", } - function PROCESS_SMOKE_TARGETS_ZONE:_Destructor() - self:E("_Destructor") - - self.Menu:Remove() - self:EventRemoveAll() - end +-- function PROCESS_SMOKE_TARGETS_ZONE:_Destructor() +-- self:E("_Destructor") +-- +-- self.Menu:Remove() +-- self:EventRemoveAll() +-- end --- Creates a new target smoking state machine. The process will request from the menu if it accepts the task, if not, the unit is removed from the simulator. -- @param #PROCESS_SMOKE_TARGETS_ZONE self diff --git a/Moose Development/Moose/Tasking/Task.lua b/Moose Development/Moose/Tasking/Task.lua index 006f74aea..e8de40bd1 100644 --- a/Moose Development/Moose/Tasking/Task.lua +++ b/Moose Development/Moose/Tasking/Task.lua @@ -170,6 +170,11 @@ function TASK_BASE:AssignToUnit( TaskUnit ) for FsmSubID, FsmSub in pairs( FsmUnit:GetSubs() ) do self:E( { "Sub ID", FsmSub.fsm:GetClassNameAndID(), FsmSubID } ) FsmSub.fsm:Assign( self, TaskUnit ) + --FsmSub.fsm:_SetDestructor() + + + --FsmSub.fsm = nil + --collectgarbage() end @@ -190,6 +195,8 @@ function TASK_BASE:AssignToUnit( TaskUnit ) FsmUnit:SetInitialState( "Planned" ) FsmUnit:Accept() -- Each Task needs to start with an Accept event to start the flow. + + return self end diff --git a/Moose Development/Moose/Tasking/Task_A2G.lua b/Moose Development/Moose/Tasking/Task_A2G.lua index 8dad3d9cf..066d19b5c 100644 --- a/Moose Development/Moose/Tasking/Task_A2G.lua +++ b/Moose Development/Moose/Tasking/Task_A2G.lua @@ -44,114 +44,41 @@ do -- TASK_A2G self.TargetSetUnit = TargetSetUnit self.TargetZone = TargetZone self.FACUnit = FACUnit - - self:SetProcessTemplate( "PROCESS_ASSIGN", PROCESS_ASSIGN_ACCEPT:New( self.TaskBriefing ) ) - self:SetProcessTemplate( "PROCESS_ROUTE", PROCESS_ROUTE_ZONE:New( self.TargetZone ) ) - self:SetProcessTemplate( "PROCESS_ACCOUNT", PROCESS_ACCOUNT_DEADS:New( self.TargetSetUnit, "A2G" ) ) - local ProcessSmoke = self:AddProcess( TaskUnit, PROCESS_SMOKE_TARGETS_ZONE:New( self, TaskUnit, self.TargetSetUnit, self.TargetZone ) ) - local ProcessJTAC = self:AddProcess( TaskUnit, PROCESS_JTAC:New( self, TaskUnit, self.TargetSetUnit, self.FACUnit ) ) + local Fsm = self:GetFsmTemplate() - _EVENTDISPATCHER:OnPlayerLeaveUnit( self._EventPlayerLeaveUnit, self ) - _EVENTDISPATCHER:OnDead( self._EventDead, self ) - _EVENTDISPATCHER:OnCrash( self._EventDead, self ) - _EVENTDISPATCHER:OnPilotDead( self._EventDead, self ) + Fsm:AddProcess( "Planned", "Accept", PROCESS_ASSIGN_ACCEPT:New( "Attack the Area" ), { Assigned = "Route", Rejected = "Eject" } ) + Fsm:AddProcess( "Assigned", "Route", PROCESS_ROUTE_ZONE:New( self.TargetZone ), { Arrived = "Update" } ) + Fsm:AddAction ( "Rejected", "Eject", "Planned" ) + Fsm:AddAction ( "Arrived", "Update", "Updated" ) + Fsm:AddProcess( "Updated", "Account", PROCESS_ACCOUNT_DEADS:New( self.TargetSetUnit, "Attack" ), { Accounted = "Success" } ) + Fsm:AddProcess( "Updated", "Smoke", PROCESS_SMOKE_TARGETS_ZONE:New( self.TargetSetUnit, self.TargetZone ) ) + --Fsm:AddProcess( "Updated", "JTAC", PROCESS_JTAC:New( self, TaskUnit, self.TargetSetUnit, self.FACUnit ) ) + Fsm:AddAction ( "Accounted", "Success", "Success" ) + Fsm:AddAction ( "Failed", "Fail", "Failed" ) + + function Fsm:onenterUpdated( TaskUnit ) + self:E( { self } ) + self:Account() + self:Smoke() + end + + + + --_EVENTDISPATCHER:OnPlayerLeaveUnit( self._EventPlayerLeaveUnit, self ) + --_EVENTDISPATCHER:OnDead( self._EventDead, self ) + --_EVENTDISPATCHER:OnCrash( self._EventDead, self ) + --_EVENTDISPATCHER:OnPilotDead( self._EventDead, self ) return self end - --- Removes a TASK_A2G. - -- @param #TASK_A2G self - -- @return #nil - function TASK_A2G:CleanUp() - - self:GetParent( self ):CleanUp() - - return nil - end - - - --- Assign the @{Task} to a @{Unit}. - -- @param #TASK_A2G self - -- @param Unit#UNIT TaskUnit - -- @return #TASK_A2G self - function TASK_A2G:AssignToUnit( TaskUnit ) - self:F( TaskUnit:GetName() ) - - local ProcessAssign = self:AssignProcess( TaskUnit, "PROCESS_ASSIGN" ) - local ProcessRoute = self:AssignProcess( TaskUnit, "PROCESS_ROUTE" ) - local ProcessDestroy = self:AssignProcess( TaskUnit, "PROCESS_ACCOUNT" ) - --local ProcessSmoke = self:AddProcess( TaskUnit, PROCESS_SMOKE_TARGETS_ZONE:New( self, TaskUnit, self.TargetSetUnit, self.TargetZone ) ) - --local ProcessJTAC = self:AddProcess( TaskUnit, PROCESS_JTAC:New( self, TaskUnit, self.TargetSetUnit, self.FACUnit ) ) - - local Process = self:AddStateMachine( TaskUnit, STATEMACHINE_TASK:New( self, TaskUnit, { - initial = 'None', - events = { - { name = 'Next', from = 'None', to = 'Planned' }, - { name = 'Next', from = 'Planned', to = 'Assigned' }, - { name = 'Reject', from = 'Planned', to = 'Rejected' }, - { name = 'Next', from = 'Assigned', to = 'Success' }, - { name = 'Fail', from = 'Assigned', to = 'Failed' }, - { name = 'Fail', from = 'Arrived', to = 'Failed' } - }, - callbacks = { - onNext = self.OnNext, - onRemove = self.OnRemove, - }, - subs = { - Assign = { onstateparent = 'Planned', oneventparent = 'Next', fsm = ProcessAssign.Fsm, event = 'Start', returnevents = { 'Next', 'Reject' } }, - Route = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessRoute.Fsm, event = 'Start' }, - Destroy = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessDestroy.Fsm, event = 'Start', returnevents = { 'Next' } }, - Smoke = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessSmoke.Fsm, event = 'Start', }, - JTAC = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessJTAC.Fsm, event = 'Start', }, - } - } ) ) - - ProcessRoute:AddScore( "Failed", "failed to destroy a ground unit", -100 ) - ProcessDestroy:AddScore( "Destroy", "destroyed a ground unit", 25 ) - ProcessDestroy:AddScore( "Failed", "failed to destroy a ground unit", -100 ) - - Process:Next() - - return self - end - - --- StateMachine callback function for a TASK - -- @param #TASK_A2G self - -- @param StateMachine#STATEMACHINE_TASK Fsm - -- @param #string Event - -- @param #string From - -- @param #string To - -- @param Event#EVENTDATA Event - function TASK_A2G:OnNext( Fsm, Event, From, To, Event ) - - self:SetState( self, "State", To ) - - end - --- @param #TASK_A2G self function TASK_A2G:GetPlannedMenuText() return self:GetStateString() .. " - " .. self:GetTaskName() .. " ( " .. self.TargetSetUnit:GetUnitTypesText() .. " )" end - - --- @param #TASK_A2G self - function TASK_A2G:_Schedule() - self:F2() - - self.TaskScheduler = SCHEDULER:New( self, _Scheduler, {}, 15, 15 ) - return self end - - - --- @param #TASK_A2G self - function TASK_A2G._Scheduler() - self:F2() - - return true - end - -end diff --git a/Moose Development/Moose/Tasking/Task_SEAD.lua b/Moose Development/Moose/Tasking/Task_SEAD.lua index bd75b717f..57fda8f21 100644 --- a/Moose Development/Moose/Tasking/Task_SEAD.lua +++ b/Moose Development/Moose/Tasking/Task_SEAD.lua @@ -45,80 +45,31 @@ do -- TASK_SEAD self.TargetSetUnit = TargetSetUnit self.TargetZone = TargetZone - self:SetProcessTemplate( "ASSIGN", PROCESS_ASSIGN_ACCEPT:New( self.TaskBriefing ) ) - self:SetProcessTemplate( "ROUTE", PROCESS_ROUTE_ZONE:New( self.TargetZone ) ) - self:SetProcessTemplate( "ACCOUNT", PROCESS_ACCOUNT_DEADS:New( self.TargetSetUnit, "SEAD" ) ) - self:SetProcessTemplate( "SMOKE", PROCESS_SMOKE_TARGETS_ZONE:New( self.TargetSetUnit, self.TargetZone ) ) + local Fsm = self:GetFsmTemplate() + + Fsm:AddProcess( "Planned", "Accept", "Planned", PROCESS_ASSIGN_ACCEPT:New( self.TaskBriefing ), { Assigned = "Route", Rejected = "Eject" } ) + Fsm:AddProcess( "Assigned", "Route", PROCESS_ROUTE_ZONE:New( self.TargetZone ), { Arrived = "Update" } ) + Fsm:AddAction ( "Rejected", "Eject", "Planned" ) + Fsm:AddAction ( "Arrived", "Update", "Updated" ) + Fsm:AddProcess( "Updated", "Account", PROCESS_ACCOUNT_DEADS:New( self.TargetSetUnit, "SEAD" ), { Accounted = "Success" } ) + Fsm:AddProcess( "Updated", "Smoke", PROCESS_SMOKE_TARGETS_ZONE:New( self.TargetSetUnit, self.TargetZone ) ) + Fsm:AddAction ( "Accounted", "Success", "Success" ) + Fsm:AddAction ( "Failed", "Fail", "Failed" ) - _EVENTDISPATCHER:OnPlayerLeaveUnit( self._EventPlayerLeaveUnit, self ) - _EVENTDISPATCHER:OnDead( self._EventDead, self ) - _EVENTDISPATCHER:OnCrash( self._EventDead, self ) - _EVENTDISPATCHER:OnPilotDead( self._EventDead, self ) + function Fsm:onenterUpdated( TaskUnit ) + self:E( { self } ) + self:Account() + self:Smoke() + end + +-- _EVENTDISPATCHER:OnPlayerLeaveUnit( self._EventPlayerLeaveUnit, self ) +-- _EVENTDISPATCHER:OnDead( self._EventDead, self ) +-- _EVENTDISPATCHER:OnCrash( self._EventDead, self ) +-- _EVENTDISPATCHER:OnPilotDead( self._EventDead, self ) return self end - - --- Removes a TASK_SEAD. - -- @param #TASK_SEAD self - -- @return #nil - function TASK_SEAD:CleanUp() - - self:GetParent(self):CleanUp() - - return nil - end - - - --- Assign the @{Task} to a @{Unit}. - -- @param #TASK_SEAD self - -- @param Unit#UNIT TaskUnit - -- @return #TASK_SEAD self - function TASK_SEAD:AssignToUnit( TaskUnit ) - self:F( TaskUnit:GetName() ) - - local ProcessAssign = self:AssignProcess( TaskUnit, "ASSIGN" ) - local ProcessRoute = self:AssignProcess( TaskUnit, "ROUTE" ) - local ProcessAccount = self:AssignProcess( TaskUnit, "ACCOUNT" ) - local ProcessSmoke = self:AssignProcess( TaskUnit, "SMOKE" ) - - local FSMT = { - initial = 'None', - events = { - { name = 'Start', from = 'None', to = 'Planned' }, - { name = 'Next', from = 'Planned', to = 'Assigned' }, - { name = 'Reject', from = 'Planned', to = 'Rejected' }, - { name = 'Next', from = 'Assigned', to = 'Success' }, - { name = 'Fail', from = 'Assigned', to = 'Failed' }, - { name = 'Fail', from = 'Arrived', to = 'Failed' } - }, - subs = { - Assign = { onstateparent = 'Planned', oneventparent = 'Next', fsm = ProcessAssign, event = 'Start', returnevents = { 'Next', 'Reject' } }, - Route = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessRoute, event = 'Start' }, - Sead = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessAccount, event = 'Start', returnevents = { 'Next' } }, - Smoke = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessSmoke, event = 'Start', } - } - } - - local Process = self:AddStateMachine( TaskUnit, STATEMACHINE_TASK:New( FSMT, self, TaskUnit ) ) - - Process:Next() - - return self - end - - --- StateMachine callback function for a TASK - -- @param #TASK_SEAD self - -- @param StateMachine#STATEMACHINE_TASK Fsm - -- @param #string Event - -- @param #string From - -- @param #string To - -- @param Event#EVENTDATA Event - function TASK_SEAD:onafterNext( Fsm, Event, From, To ) - - self:SetState( self, "State", To ) - - end - + --- @param #TASK_SEAD self function TASK_SEAD:GetPlannedMenuText() return self:GetStateString() .. " - " .. self:GetTaskName() .. " ( " .. self.TargetSetUnit:GetUnitTypesText() .. " )" diff --git a/Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua b/Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua index cfe4aebcd..78c52f14b 100644 --- a/Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua +++ b/Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua @@ -1,5 +1,5 @@ env.info( '*** MOOSE DYNAMIC INCLUDE START *** ' ) -env.info( 'Moose Generation Timestamp: 20161102_0903' ) +env.info( 'Moose Generation Timestamp: 20161123_1801' ) local base = _G diff --git a/Moose Mission Setup/Moose.lua b/Moose Mission Setup/Moose.lua index cfe4aebcd..78c52f14b 100644 --- a/Moose Mission Setup/Moose.lua +++ b/Moose Mission Setup/Moose.lua @@ -1,5 +1,5 @@ env.info( '*** MOOSE DYNAMIC INCLUDE START *** ' ) -env.info( 'Moose Generation Timestamp: 20161102_0903' ) +env.info( 'Moose Generation Timestamp: 20161123_1801' ) local base = _G diff --git a/Moose Test Missions/Moose_Test_Tasking/Moose_Test_Detection_Dispatcher/Moose_Test_Detection_Dispatcher.miz b/Moose Test Missions/Moose_Test_Tasking/Moose_Test_Detection_Dispatcher/Moose_Test_Detection_Dispatcher.miz index 99722364c..2cb89bdf8 100644 Binary files a/Moose Test Missions/Moose_Test_Tasking/Moose_Test_Detection_Dispatcher/Moose_Test_Detection_Dispatcher.miz and b/Moose Test Missions/Moose_Test_Tasking/Moose_Test_Detection_Dispatcher/Moose_Test_Detection_Dispatcher.miz differ diff --git a/Moose Test Missions/Moose_Test_Tasking/Moose_Test_Task_SEAD/Moose_Test_Task_SEAD.lua b/Moose Test Missions/Moose_Test_Tasking/Moose_Test_Task_SEAD/Moose_Test_Task_SEAD.lua index 1aa1cf8bb..8fadd29c7 100644 --- a/Moose Test Missions/Moose_Test_Tasking/Moose_Test_Task_SEAD/Moose_Test_Task_SEAD.lua +++ b/Moose Test Missions/Moose_Test_Tasking/Moose_Test_Task_SEAD/Moose_Test_Task_SEAD.lua @@ -1,6 +1,13 @@ env.info( "Lua Version = " .. _VERSION ) +-- Test Garbage control of one declared PROCESS. +do + local Process = PROCESS_ASSIGN_ACCEPT:New( "SEAD the Area" ) +end + +collectgarbage() + local Mission = MISSION:New( 'SEAD Targets', "Strategic", "SEAD the enemy", coalition.side.RED ) local Scoring = SCORING:New( "SEAD" ) diff --git a/Moose Test Missions/Moose_Test_Tasking/Moose_Test_Task_SEAD/Moose_Test_Task_SEAD.miz b/Moose Test Missions/Moose_Test_Tasking/Moose_Test_Task_SEAD/Moose_Test_Task_SEAD.miz index eec018697..3e3ad8037 100644 Binary files a/Moose Test Missions/Moose_Test_Tasking/Moose_Test_Task_SEAD/Moose_Test_Task_SEAD.miz and b/Moose Test Missions/Moose_Test_Tasking/Moose_Test_Task_SEAD/Moose_Test_Task_SEAD.miz differ