From aa5050165f447389ba0120230954af13bbedf79a Mon Sep 17 00:00:00 2001 From: Nahuel Rocchetti Date: Fri, 28 Jun 2024 15:28:33 -0300 Subject: [PATCH] implement simulator loop --- Assets/Editor/OpenTS2/SimulatorEditor.cs | 38 ++++++++++++++++++ Assets/Editor/OpenTS2/SimulatorEditor.cs.meta | 11 +++++ Assets/Scripts/OpenTS2/Game/Simulator.cs | 40 +++++++++++++++++-- Assets/Scripts/OpenTS2/SimAntics/VM.cs | 11 ++++- Assets/Scripts/OpenTS2/SimAntics/VMEntity.cs | 7 ++++ 5 files changed, 102 insertions(+), 5 deletions(-) create mode 100644 Assets/Editor/OpenTS2/SimulatorEditor.cs create mode 100644 Assets/Editor/OpenTS2/SimulatorEditor.cs.meta diff --git a/Assets/Editor/OpenTS2/SimulatorEditor.cs b/Assets/Editor/OpenTS2/SimulatorEditor.cs new file mode 100644 index 00000000..c558004a --- /dev/null +++ b/Assets/Editor/OpenTS2/SimulatorEditor.cs @@ -0,0 +1,38 @@ +using OpenTS2.Game; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEditor; +using UnityEngine; + +namespace OpenTS2 +{ + [CustomEditor(typeof(Simulator))] + public class SimulatorEditor : Editor + { + public override void OnInspectorGUI() + { + DrawDefaultInspector(); + var simulator = target as Simulator; + var vm = simulator.VirtualMachine; + if (vm == null) return; + var entities = vm.Entities; + if (entities == null) return; + GUILayout.Label("Entities"); + GUILayout.BeginVertical("box"); + foreach(var entity in entities) + { + GUILayout.BeginVertical("box"); + GUILayout.Label($"{entity.ID} - {entity.ObjectDefinition.FileName}"); + GUILayout.EndVertical(); + if (GUILayout.Button("Kill")) + { + entity.Delete(); + } + } + GUILayout.EndVertical(); + } + } +} diff --git a/Assets/Editor/OpenTS2/SimulatorEditor.cs.meta b/Assets/Editor/OpenTS2/SimulatorEditor.cs.meta new file mode 100644 index 00000000..12edbf77 --- /dev/null +++ b/Assets/Editor/OpenTS2/SimulatorEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 21a864a17b7497444a19c57f9ca0677b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Scripts/OpenTS2/Game/Simulator.cs b/Assets/Scripts/OpenTS2/Game/Simulator.cs index a8019703..19b75678 100644 --- a/Assets/Scripts/OpenTS2/Game/Simulator.cs +++ b/Assets/Scripts/OpenTS2/Game/Simulator.cs @@ -16,6 +16,7 @@ public class Simulator : MonoBehaviour public VM VirtualMachine => _virtualMachine; private VM _virtualMachine; public Context SimulationContext = Context.Neighborhood; + public bool DeleteEntityOnError = true; public enum Context { Lot = 1, @@ -25,11 +26,13 @@ public enum Context /// Number of ticks to run per second. /// public int TickRate = 20; + private float _timer = 0f; private void Awake() { Instance = this; _virtualMachine = new VM(); + _virtualMachine.ExceptionHandler += HandleException; } private void Start() @@ -37,6 +40,15 @@ private void Start() CreateGlobalObjects(); } + private void Update() + { + var rateSecs = (float)1 / TickRate; + _timer += Time.deltaTime; + var timesToTick = Mathf.FloorToInt(_timer / rateSecs); + _virtualMachine.Tick(); + _timer -= timesToTick * rateSecs; + } + private void CreateGlobalObjects() { var objects = ObjectManager.Instance.Objects; @@ -53,20 +65,26 @@ private void CreateGlobalObjects() public VMEntity CreateObject(ObjectDefinitionAsset objectDefinition) { var entity = new VMEntity(objectDefinition); + _virtualMachine.AddEntity(entity); + try { - _virtualMachine.AddEntity(entity); - UpdateObjectData(entity); var initFunction = entity.ObjectDefinition.Functions.GetFunction(ObjectFunctionsAsset.FunctionNames.Init); if (initFunction.ActionTree != 0) entity.RunTreeImmediately(initFunction.ActionTree); + + var mainFunction = entity.ObjectDefinition.Functions.GetFunction(ObjectFunctionsAsset.FunctionNames.Main); + + if (mainFunction.ActionTree != 0) { + entity.PushTreeToThread(entity.MainThread, mainFunction.ActionTree); + } } - catch(SimAnticsException e) + catch(Exception e) { - HandleSimAnticsException(e); + HandleException(e, entity); } return entity; } @@ -77,9 +95,23 @@ void UpdateObjectData(VMEntity entity) entity.SetObjectData(VMObjectData.ObjectID, entity.ID); } + public void HandleException(Exception exception, VMEntity entity) + { + if (exception is SimAnticsException) + { + HandleSimAnticsException(exception as SimAnticsException); + return; + } + Debug.LogError($"Non-SimAntics exception caused by entity {entity.ID} - {entity.ObjectDefinition.FileName}\n{exception}"); + if (DeleteEntityOnError) + entity.Delete(); + } + public void HandleSimAnticsException(SimAnticsException exception) { Debug.LogError(exception.ToString()); + if (DeleteEntityOnError) + exception.StackFrame.Thread.Entity.Delete(); } public void Kill() diff --git a/Assets/Scripts/OpenTS2/SimAntics/VM.cs b/Assets/Scripts/OpenTS2/SimAntics/VM.cs index d4a67073..82efcde4 100644 --- a/Assets/Scripts/OpenTS2/SimAntics/VM.cs +++ b/Assets/Scripts/OpenTS2/SimAntics/VM.cs @@ -2,6 +2,7 @@ using OpenTS2.Common; using OpenTS2.Content; using OpenTS2.Files.Formats.DBPF; +using System; using System.Collections; using System.Collections.Generic; using System.Linq; @@ -18,6 +19,7 @@ public class VM public VMScheduler Scheduler = new VMScheduler(); public List Entities = new List(); public uint CurrentTick = 0; + public Action ExceptionHandler; private Dictionary _entitiesByID = new Dictionary(); @@ -66,7 +68,14 @@ public void Tick() Scheduler.OnBeginTick(this); foreach(var entity in Entities) { - entity.Tick(); + try + { + entity.Tick(); + } + catch(Exception e) + { + ExceptionHandler?.Invoke(e, entity); + } } Scheduler.OnEndTick(this); CurrentTick++; diff --git a/Assets/Scripts/OpenTS2/SimAntics/VMEntity.cs b/Assets/Scripts/OpenTS2/SimAntics/VMEntity.cs index 0396e98f..397e74b2 100644 --- a/Assets/Scripts/OpenTS2/SimAntics/VMEntity.cs +++ b/Assets/Scripts/OpenTS2/SimAntics/VMEntity.cs @@ -95,6 +95,13 @@ public BHAVAsset GetBHAV(ushort treeID) return VM.GetBHAV(treeID, groupid); } + public void PushTreeToThread(VMThread thread, ushort treeId) + { + var bhav = GetBHAV(treeId); + var stackFrame = new VMStackFrame(bhav, thread); + thread.Frames.Push(stackFrame); + } + public VMExitCode RunTreeImmediately(ushort treeID) { var thread = new VMThread(this);