diff --git a/TechbloxModdingAPI/App/AppCallbacksTest.cs b/TechbloxModdingAPI/App/AppCallbacksTest.cs index c1e184b..52cbc27 100644 --- a/TechbloxModdingAPI/App/AppCallbacksTest.cs +++ b/TechbloxModdingAPI/App/AppCallbacksTest.cs @@ -20,8 +20,8 @@ namespace TechbloxModdingAPI.App Game.Exit += Assert.CallsBack("GameExit"); Game.Simulate += Assert.CallsBack("GameSimulate"); Game.Edit += Assert.CallsBack("GameEdit"); - Client.EnterMenu += Assert.CallsBack("MenuEnter"); - Client.ExitMenu += Assert.CallsBack("MenuExit"); + /*Client.EnterMenu += Assert.CallsBack("MenuEnter"); + Client.ExitMenu += Assert.CallsBack("MenuExit");*/ } [APITestCase(TestType.Game)] diff --git a/TechbloxModdingAPI/App/ClientAlertTest.cs b/TechbloxModdingAPI/App/ClientAlertTest.cs index 278a826..bb77dcc 100644 --- a/TechbloxModdingAPI/App/ClientAlertTest.cs +++ b/TechbloxModdingAPI/App/ClientAlertTest.cs @@ -2,7 +2,7 @@ using System; using HarmonyLib; using RobocraftX.Services; - +using TechbloxModdingAPI.Client.App; using TechbloxModdingAPI.Tests; namespace TechbloxModdingAPI.App @@ -42,25 +42,25 @@ namespace TechbloxModdingAPI.App [APITestCase(TestType.Menu)] public static void TestPopUp2() { - Client.Instance.PromptUser(popup2); + Popup.PromptUser(popup2); } [APITestCase(TestType.Menu)] public static void TestPopUp1() { - Client.Instance.PromptUser(popup1); + Popup.PromptUser(popup1); } [APITestCase(TestType.Menu)] public static void TestPopUpClose1() { - Client.Instance.CloseCurrentPrompt(); + Popup.CloseCurrentPrompt(); } [APITestCase(TestType.Menu)] public static void TestPopUpClose2() { - Client.Instance.CloseCurrentPrompt(); + Popup.CloseCurrentPrompt(); } } #endif diff --git a/TechbloxModdingAPI/App/Game.cs b/TechbloxModdingAPI/App/Game.cs index 977586d..ae760b0 100644 --- a/TechbloxModdingAPI/App/Game.cs +++ b/TechbloxModdingAPI/App/Game.cs @@ -7,6 +7,7 @@ using Svelto.ECS; using Techblox.GameSelection; using TechbloxModdingAPI.Blocks; +using TechbloxModdingAPI.Common.Engines; using TechbloxModdingAPI.Tasks; using TechbloxModdingAPI.Utility; @@ -481,10 +482,10 @@ namespace TechbloxModdingAPI.App internal static void Init() { - GameEngineManager.AddGameEngine(gameEngine); - GameEngineManager.AddGameEngine(debugOverlayEngine); - GameEngineManager.AddGameEngine(buildSimEventEngine); - MenuEngineManager.AddMenuEngine(menuEngine); + EngineManager.AddEngine(gameEngine, ApiEngineType.Build, ApiEngineType.PlayClient, ApiEngineType.PlayServer); + EngineManager.AddEngine(debugOverlayEngine, ApiEngineType.Build, ApiEngineType.PlayClient, ApiEngineType.PlayServer); + EngineManager.AddEngine(buildSimEventEngine, ApiEngineType.Build, ApiEngineType.PlayClient, ApiEngineType.PlayServer); + EngineManager.AddEngine(menuEngine, ApiEngineType.Menu); } } } diff --git a/TechbloxModdingAPI/Block.cs b/TechbloxModdingAPI/Block.cs index f135247..291f8d6 100644 --- a/TechbloxModdingAPI/Block.cs +++ b/TechbloxModdingAPI/Block.cs @@ -14,6 +14,8 @@ using RobocraftX.Rendering; using Techblox.BlockLabelsServer; using TechbloxModdingAPI.Blocks; using TechbloxModdingAPI.Blocks.Engines; +using TechbloxModdingAPI.Client.App; +using TechbloxModdingAPI.Common.Engines; using TechbloxModdingAPI.Tests; using TechbloxModdingAPI.Utility; @@ -48,7 +50,7 @@ namespace TechbloxModdingAPI /// The placed block or null if failed public static Block PlaceNew(BlockIDs block, float3 position, bool autoWire = false, Player player = null) { - if (PlacementEngine.IsInGame && GameState.IsBuildMode()) + if (PlacementEngine.IsInGame && GameClient.IsBuildMode) { var initializer = PlacementEngine.PlaceBlock(block, position, player, autoWire); var egid = initializer.EGID; @@ -346,7 +348,7 @@ namespace TechbloxModdingAPI get { if (blockGroup != null) return blockGroup; - if (!GameState.IsBuildMode()) return null; // Breaks in simulation + if (!GameClient.IsBuildMode) return null; // Breaks in simulation var bgec = BlockEngine.GetBlockInfo(this); return blockGroup = bgec.currentBlockGroup == -1 ? null @@ -484,15 +486,15 @@ namespace TechbloxModdingAPI public static void Init() { - GameEngineManager.AddGameEngine(PlacementEngine); - GameEngineManager.AddGameEngine(MovementEngine); - GameEngineManager.AddGameEngine(RotationEngine); - GameEngineManager.AddGameEngine(RemovalEngine); - GameEngineManager.AddGameEngine(BlockEngine); - GameEngineManager.AddGameEngine(BlockEventsEngine); - GameEngineManager.AddGameEngine(ScalingEngine); - GameEngineManager.AddGameEngine(SignalEngine); - GameEngineManager.AddGameEngine(BlockCloneEngine); + EngineManager.AddEngine(PlacementEngine, ApiEngineType.Build); + EngineManager.AddEngine(MovementEngine, ApiEngineType.Build); + EngineManager.AddEngine(RotationEngine, ApiEngineType.Build); + EngineManager.AddEngine(RemovalEngine, ApiEngineType.Build); + EngineManager.AddEngine(BlockEngine, ApiEngineType.Build, ApiEngineType.PlayServer, ApiEngineType.PlayClient); + EngineManager.AddEngine(BlockEventsEngine, ApiEngineType.Build); + EngineManager.AddEngine(ScalingEngine, ApiEngineType.Build); + EngineManager.AddEngine(SignalEngine, ApiEngineType.Build); + EngineManager.AddEngine(BlockCloneEngine, ApiEngineType.Build); Wire.signalEngine = SignalEngine; // requires same functionality, no need to duplicate the engine } } diff --git a/TechbloxModdingAPI/BlockGroup.cs b/TechbloxModdingAPI/BlockGroup.cs index cbb4a58..0629c6b 100644 --- a/TechbloxModdingAPI/BlockGroup.cs +++ b/TechbloxModdingAPI/BlockGroup.cs @@ -9,6 +9,7 @@ using UnityEngine; using TechbloxModdingAPI.Blocks; using TechbloxModdingAPI.Blocks.Engines; +using TechbloxModdingAPI.Common.Engines; using TechbloxModdingAPI.Utility; namespace TechbloxModdingAPI @@ -149,7 +150,7 @@ namespace TechbloxModdingAPI internal static void Init() { - GameEngineManager.AddGameEngine(_engine); + EngineManager.AddEngine(_engine, ApiEngineType.Build); } public IEnumerator GetEnumerator() => blocks.GetEnumerator(); diff --git a/TechbloxModdingAPI/Blocks/Engine.cs b/TechbloxModdingAPI/Blocks/Engine.cs index e3d7ade..32f42ba 100644 --- a/TechbloxModdingAPI/Blocks/Engine.cs +++ b/TechbloxModdingAPI/Blocks/Engine.cs @@ -23,18 +23,18 @@ namespace TechbloxModdingAPI.Blocks { } - /*/// - TODO: Internal struct access + /// /// Gets or sets the Engine's On property. May not be saved. /// public bool On { get { - return BlockEngine.GetBlockInfo(this).engineOn; + return ((bool)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "engineOn"))); } set { - BlockEngine.GetBlockInfo(this).engineOn = value; + BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "engineOn", value); } } @@ -45,11 +45,11 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this).currentGear; + return ((int)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "currentGear"))); } set { - BlockEngine.GetBlockInfo(this).currentGear = value; + BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "currentGear", value); } } @@ -60,11 +60,11 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this).gearChangeCountdown; + return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "gearChangeCountdown"))); } set { - BlockEngine.GetBlockInfo(this).gearChangeCountdown = value; + BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "gearChangeCountdown", value); } } @@ -75,11 +75,11 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this).currentRpmAV; + return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "currentRpmAV"))); } set { - BlockEngine.GetBlockInfo(this).currentRpmAV = value; + BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "currentRpmAV", value); } } @@ -90,11 +90,11 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this).currentRpmLV; + return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "currentRpmLV"))); } set { - BlockEngine.GetBlockInfo(this).currentRpmLV = value; + BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "currentRpmLV", value); } } @@ -105,11 +105,11 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this).targetRpmAV; + return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "targetRpmAV"))); } set { - BlockEngine.GetBlockInfo(this).targetRpmAV = value; + BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "targetRpmAV", value); } } @@ -120,11 +120,11 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this).targetRpmLV; + return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "targetRpmLV"))); } set { - BlockEngine.GetBlockInfo(this).targetRpmLV = value; + BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "targetRpmLV", value); } } @@ -135,11 +135,11 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this).currentTorque; + return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "currentTorque"))); } set { - BlockEngine.GetBlockInfo(this).currentTorque = value; + BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "currentTorque", value); } } @@ -150,11 +150,11 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this).totalWheelVelocityAV; + return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "totalWheelVelocityAV"))); } set { - BlockEngine.GetBlockInfo(this).totalWheelVelocityAV = value; + BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "totalWheelVelocityAV", value); } } @@ -165,11 +165,11 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this).totalWheelVelocityLV; + return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "totalWheelVelocityLV"))); } set { - BlockEngine.GetBlockInfo(this).totalWheelVelocityLV = value; + BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "totalWheelVelocityLV", value); } } @@ -180,11 +180,11 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this).totalWheelCount; + return ((int)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "totalWheelCount"))); } set { - BlockEngine.GetBlockInfo(this).totalWheelCount = value; + BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "totalWheelCount", value); } } @@ -195,11 +195,11 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this).lastGearUpInput; + return ((bool)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "lastGearUpInput"))); } set { - BlockEngine.GetBlockInfo(this).lastGearUpInput = value; + BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "lastGearUpInput", value); } } @@ -210,11 +210,11 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this).lastGearDownInput; + return ((bool)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "lastGearDownInput"))); } set { - BlockEngine.GetBlockInfo(this).lastGearDownInput = value; + BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "lastGearDownInput", value); } } @@ -225,11 +225,11 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this).manualToAutoGearCoolOffCounter; + return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "manualToAutoGearCoolOffCounter"))); } set { - BlockEngine.GetBlockInfo(this).manualToAutoGearCoolOffCounter = value; + BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "manualToAutoGearCoolOffCounter", value); } } @@ -240,11 +240,11 @@ namespace TechbloxModdingAPI.Blocks { get { - return BlockEngine.GetBlockInfo(this).load; + return ((float)(BlockEngine.GetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "load"))); } set { - BlockEngine.GetBlockInfo(this).load = value; + BlockEngine.SetBlockInfo(this, HarmonyLib.AccessTools.TypeByName("Techblox.EngineBlock.EngineBlockComponent"), "load", value); } } @@ -324,13 +324,17 @@ namespace TechbloxModdingAPI.Blocks } /// - /// Gets the Engine's GearDownRpms property. May not be saved. + /// Gets or sets the Engine's GearDownRpms property. May not be saved. /// - public float[] GearDownRpms + public Svelto.ECS.DataStructures.NativeDynamicArray GearDownRpms { get { - return BlockEngine.GetBlockInfo(this).gearDownRpms.ToManagedArray(); + return BlockEngine.GetBlockInfo(this).gearDownRpms; + } + set + { + BlockEngine.GetBlockInfo(this).gearDownRpms = value; } } @@ -377,6 +381,21 @@ namespace TechbloxModdingAPI.Blocks { BlockEngine.GetBlockInfo(this).manualToAutoGearCoolOffTime = value; } - }*/ + } + + /// + /// Gets or sets the Engine's EngineBlockDataId property. May not be saved. + /// + public int EngineBlockDataId + { + get + { + return BlockEngine.GetBlockInfo(this).engineBlockDataId; + } + set + { + BlockEngine.GetBlockInfo(this).engineBlockDataId = value; + } + } } } diff --git a/TechbloxModdingAPI/Client/App/GameClient.cs b/TechbloxModdingAPI/Client/App/GameClient.cs index 85d3dc9..b878c64 100644 --- a/TechbloxModdingAPI/Client/App/GameClient.cs +++ b/TechbloxModdingAPI/Client/App/GameClient.cs @@ -1,4 +1,7 @@ using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Svelto.Tasks; using TechbloxModdingAPI.Client.Game; using TechbloxModdingAPI.Common.Engines; using TechbloxModdingAPI.Utility; @@ -26,6 +29,11 @@ public static class GameClient private static GameState _currentState; + public static bool IsBuildMode => + CurrentState is GameState.InMachineEditor or GameState.InWorldEditor; + + public static bool IsSimulationMode => + CurrentState is GameState.InTestMode or GameState.InWorldTestMode or GameState.InOnlineMatch; /// /// An event that fires whenever the game's state changes @@ -62,10 +70,39 @@ public static class GameClient public static void EnterBuildMode(ClientEnvironment environment, ClientMachine machine) { + if (CurrentState == GameState.InMenu) + throw new InvalidOperationException($"Can only enter test mode from build mode! Current mode: {CurrentState}"); var env = new ClientEnvironment("GAMEID_Road_Track"); // TODO: The options are hardcoded _engine.EnterBuildMode(env, machine); } + public static IEnumerator EnterTestMode() + { + if (!IsBuildMode) + throw new InvalidOperationException($"Can only enter test mode from build mode! Current mode: {CurrentState}"); + // TODO + //return Task.CompletedTask; + yield break; + } + + public static IEnumerator ExitSimulationMode() + { // TODO: Separate these based on the current game state? + if (!IsSimulationMode) + throw new InvalidOperationException($"Can only exit test mode when in it! Current mode: {CurrentState}"); + // TODO + //return Task.CompletedTask; + yield break; + } + + public static IEnumerator ExitBuildMode() + { + if (!IsBuildMode) + throw new InvalidOperationException($"Can only exit test mode when in it! Current mode: {CurrentState}"); + // TODO + //return Task.CompletedTask; + yield break; + } + public static void Init() { EngineManager.AddEngine(_engine, ApiEngineType.Menu); diff --git a/TechbloxModdingAPI/Client/App/GameState.cs b/TechbloxModdingAPI/Client/App/GameState.cs index d11c3ef..28d8fae 100644 --- a/TechbloxModdingAPI/Client/App/GameState.cs +++ b/TechbloxModdingAPI/Client/App/GameState.cs @@ -2,10 +2,32 @@ namespace TechbloxModdingAPI.Client.App; public enum GameState { + /// + /// In the environment/game selection menu. + /// InMenu, + /// + /// In machine editor mode in a selected environment. + /// InMachineEditor, + /// + /// In world editor mode. + /// InWorldEditor, + /// + /// In test mode in a selected environment. + /// InTestMode, - InMatch, + /// + /// In world test mode. + /// + InWorldTestMode, + /// + /// In an online match as a client. + /// + InOnlineMatch, + /// + /// The loading screen is active or otherwise transitioning between modes. + /// Loading } \ No newline at end of file diff --git a/TechbloxModdingAPI/Common/Engines/EnginePatches.cs b/TechbloxModdingAPI/Common/Engines/EnginePatches.cs index 3358672..753ca21 100644 --- a/TechbloxModdingAPI/Common/Engines/EnginePatches.cs +++ b/TechbloxModdingAPI/Common/Engines/EnginePatches.cs @@ -18,7 +18,7 @@ namespace TechbloxModdingAPI.Common.Engines { Client.App.GameClient.CurrentState = GameState.InMachineEditor; // TODO: World editor // register all game engines, including deterministic - GameEngineManager.RegisterEngines(stateSyncReg); + EngineManager.RegisterEngines(stateSyncReg, stateSyncReg.enginesRoot, ApiEngineType.Build); // register command engines CommandManager.RegisterEngines(stateSyncReg.enginesRoot); } @@ -35,7 +35,7 @@ namespace TechbloxModdingAPI.Common.Engines public static void Postfix(StateSyncRegistrationHelper stateSyncReg) { Client.App.GameClient.CurrentState = GameState.InTestMode; // TODO: Client/server - GameEngineManager.RegisterEngines(stateSyncReg); + EngineManager.RegisterEngines(stateSyncReg, stateSyncReg.enginesRoot, ApiEngineType.PlayClient); // TODO: Client/server CommandManager.RegisterEngines(stateSyncReg.enginesRoot); } @@ -89,7 +89,7 @@ namespace TechbloxModdingAPI.Common.Engines { Client.App.GameClient.CurrentState = GameState.InMenu; // TODO: Loaded states // register menu engines - MenuEngineManager.RegisterEngines(enginesRoot); + EngineManager.RegisterEngines(null, enginesRoot, ApiEngineType.Menu); } public static MethodBase TargetMethod() diff --git a/TechbloxModdingAPI/Common/Utils/AsyncUtils.cs b/TechbloxModdingAPI/Common/Utils/AsyncUtils.cs new file mode 100644 index 0000000..650f3f7 --- /dev/null +++ b/TechbloxModdingAPI/Common/Utils/AsyncUtils.cs @@ -0,0 +1,38 @@ +using System.Threading.Tasks; +using RobocraftX.Schedulers; +using Svelto.ECS; +using Techblox.Server.Schedulers; +using TechbloxModdingAPI.Common.Engines; +using TechbloxModdingAPI.Utility; + +namespace TechbloxModdingAPI.Common.Utils; + +public static class AsyncUtils +{ + private static AsyncUtilsEngine gameEngine = new(); + + /// + /// Waits for entity submission asynchronously. + /// Use after placing a block or otherwise creating things in the game to access their properties. + /// + public static async Task WaitForSubmission() + { + await gameEngine.WaitForSubmission(); + } + + public static async Task WaitForNextFrame() + { + await gameEngine.WaitForNextFrame(); + } + + public static void Setup(EnginesRoot enginesRoot, bool clientside) + { + gameEngine.Setup(enginesRoot, + clientside ? ClientExtraLean.UIScheduler : ServerExtraLean.DeterministicTimeRunningStepRunner); + } + + public static void Init() + { + EngineManager.AddEngine(gameEngine, ApiEngineType.Build, ApiEngineType.Menu, ApiEngineType.PlayClient, ApiEngineType.PlayServer); + } +} \ No newline at end of file diff --git a/TechbloxModdingAPI/Common/Utils/AsyncUtilsEngine.cs b/TechbloxModdingAPI/Common/Utils/AsyncUtilsEngine.cs new file mode 100644 index 0000000..2cb685b --- /dev/null +++ b/TechbloxModdingAPI/Common/Utils/AsyncUtilsEngine.cs @@ -0,0 +1,56 @@ +using System.Collections; +using System.Threading.Tasks; +using RobocraftX.Schedulers; +using Svelto.ECS; +using Svelto.Tasks; +using Svelto.Tasks.ExtraLean; + +namespace TechbloxModdingAPI.Common.Utils; + +public class AsyncUtilsEngine : IApiEngine +{ + private EnginesRoot _enginesRoot; + private IRunner> _runner; + private IEnumerator WaitForSubmissionInternal(TaskCompletionSource task) + { + var waitEnumerator = new WaitForSubmissionEnumerator(_enginesRoot.scheduler); + while (waitEnumerator.MoveNext()) + yield return null; + task.SetResult(null); + } + + private IEnumerator WaitForNextFrameInternal(TaskCompletionSource task) + { + yield return null; + task.SetResult(null); + } + + public Task WaitForSubmission() + { + var task = new TaskCompletionSource(); + WaitForSubmissionInternal(task).RunOn(_runner); + return task.Task; + } + + public Task WaitForNextFrame() + { + var task = new TaskCompletionSource(); + WaitForNextFrameInternal(task).RunOn(_runner); + return task.Task; + } + + public void Setup(EnginesRoot enginesRoot, IRunner> runner) + { // TODO: Different engines roots for different sides + _enginesRoot = enginesRoot; + _runner = runner; + } + + public void Ready() + { + } + + public EntitiesDB entitiesDB { get; set; } + public void Dispose() + { + } +} \ No newline at end of file diff --git a/TechbloxModdingAPI/Input/FakeInput.cs b/TechbloxModdingAPI/Input/FakeInput.cs index 9409f77..dd85288 100644 --- a/TechbloxModdingAPI/Input/FakeInput.cs +++ b/TechbloxModdingAPI/Input/FakeInput.cs @@ -1,6 +1,7 @@ using RobocraftX.Common.Input; using TechbloxModdingAPI.App; +using TechbloxModdingAPI.Common.Engines; using TechbloxModdingAPI.Utility; namespace TechbloxModdingAPI.Input @@ -138,8 +139,7 @@ namespace TechbloxModdingAPI.Input public static void Init() { - GameEngineManager.AddGameEngine(inputEngine); - MenuEngineManager.AddMenuEngine(inputEngine); + EngineManager.AddEngine(inputEngine, ApiEngineType.Build, ApiEngineType.Menu, ApiEngineType.PlayClient, ApiEngineType.PlayServer); } } } diff --git a/TechbloxModdingAPI/Main.cs b/TechbloxModdingAPI/Main.cs index 0ef6c03..3507053 100644 --- a/TechbloxModdingAPI/Main.cs +++ b/TechbloxModdingAPI/Main.cs @@ -56,9 +56,6 @@ namespace TechbloxModdingAPI try { - // init utility - Logging.MetaDebugLog($"Initializing Utility"); - Utility.GameState.Init(); // init block implementors Logging.MetaDebugLog($"Initializing Blocks"); // init input diff --git a/TechbloxModdingAPI/Persistence/SimpleEntitySerializer.cs b/TechbloxModdingAPI/Persistence/SimpleEntitySerializer.cs index 57f787a..7266045 100644 --- a/TechbloxModdingAPI/Persistence/SimpleEntitySerializer.cs +++ b/TechbloxModdingAPI/Persistence/SimpleEntitySerializer.cs @@ -1,6 +1,4 @@ -using System; - -using Svelto.ECS; +using Svelto.ECS; using Svelto.ECS.Serialization; using RobocraftX.Common; diff --git a/TechbloxModdingAPI/Player.cs b/TechbloxModdingAPI/Player.cs index b653133..c09b8f5 100644 --- a/TechbloxModdingAPI/Player.cs +++ b/TechbloxModdingAPI/Player.cs @@ -12,6 +12,8 @@ using Techblox.BuildingDrone; using Techblox.Camera; using Techblox.Character; using TechbloxModdingAPI.Blocks; +using TechbloxModdingAPI.Client.App; +using TechbloxModdingAPI.Common.Engines; using TechbloxModdingAPI.Players; using TechbloxModdingAPI.Utility; using UnityEngine; @@ -131,10 +133,10 @@ namespace TechbloxModdingAPI /// The rotation. public float3 Rotation { - get => ((Quaternion) (GameState.IsBuildMode() + get => ((Quaternion) (GameClient.IsBuildMode ? playerEngine.GetCameraStruct(Id).Get().rotation : playerEngine.GetCharacterStruct(Id).Get().rotation)).eulerAngles; - set => _ = GameState.IsBuildMode() + set => _ = GameClient.IsBuildMode ? playerEngine.GetCameraStruct(Id).Get().rotation = quaternion.Euler(value) : playerEngine.GetCharacterStruct(Id).Get().rotation = quaternion.Euler(value); } @@ -344,10 +346,10 @@ namespace TechbloxModdingAPI /// public bool Sprinting { - get => GameState.IsBuildMode() + get => GameClient.IsBuildMode ? playerEngine.GetCharacterStruct(Id).Get().sprinting : playerEngine.GetCharacterStruct(Id).Get().isSprinting; - set => _ = GameState.IsBuildMode() + set => _ = GameClient.IsBuildMode ? playerEngine.GetCharacterStruct(Id).Get().sprinting = value : playerEngine.GetCharacterStruct(Id).Get().isSprinting = value; } @@ -357,10 +359,10 @@ namespace TechbloxModdingAPI /// public float SpeedSetting { - get => GameState.IsBuildMode() + get => GameClient.IsBuildMode ? playerEngine.GetCharacterStruct(Id).Get().speed : playerEngine.GetCharacterStruct(Id).Get().moveSpeed; - set => _ = GameState.IsBuildMode() + set => _ = GameClient.IsBuildMode ? playerEngine.GetCharacterStruct(Id).Get().speed = value : playerEngine.GetCharacterStruct(Id).Get().moveSpeed = value; } @@ -370,10 +372,10 @@ namespace TechbloxModdingAPI /// public float SpeedSprintMultiplierSetting { - get => GameState.IsBuildMode() + get => GameClient.IsBuildMode ? playerEngine.GetCharacterStruct(Id).Get().speedSprintMultiplier : playerEngine.GetCharacterStruct(Id).Get().sprintSpeedMultiplier; - set => _ = GameState.IsBuildMode() + set => _ = GameClient.IsBuildMode ? playerEngine.GetCharacterStruct(Id).Get().speedSprintMultiplier = value : playerEngine.GetCharacterStruct(Id).Get().sprintSpeedMultiplier = value; } @@ -383,10 +385,10 @@ namespace TechbloxModdingAPI /// public float AccelerationSetting { - get => GameState.IsBuildMode() + get => GameClient.IsBuildMode ? playerEngine.GetCharacterStruct(Id).Get().acceleration : playerEngine.GetCharacterStruct(Id).Get().acceleration; - set => _ = GameState.IsBuildMode() + set => _ = GameClient.IsBuildMode ? playerEngine.GetCharacterStruct(Id).Get().acceleration = value : playerEngine.GetCharacterStruct(Id).Get().acceleration = value; } @@ -539,8 +541,9 @@ namespace TechbloxModdingAPI internal static void Init() { - Utility.GameEngineManager.AddGameEngine(playerEngine); - Utility.GameEngineManager.AddGameEngine(playerEventsEngine); + // TODO: Separate build mode, client and server into separate classes + EngineManager.AddEngine(playerEngine, ApiEngineType.Build, ApiEngineType.PlayClient, ApiEngineType.PlayServer); + EngineManager.AddEngine(playerEventsEngine, ApiEngineType.Build, ApiEngineType.PlayClient, ApiEngineType.PlayServer); } } } diff --git a/TechbloxModdingAPI/Players/PlayerEngine.cs b/TechbloxModdingAPI/Players/PlayerEngine.cs index 615916a..5065296 100644 --- a/TechbloxModdingAPI/Players/PlayerEngine.cs +++ b/TechbloxModdingAPI/Players/PlayerEngine.cs @@ -16,6 +16,7 @@ using Techblox.Camera; using Unity.Mathematics; using Techblox.BuildingDrone; using Techblox.Character; +using TechbloxModdingAPI.Client.App; using TechbloxModdingAPI.Common.Engines; using TechbloxModdingAPI.Input; using TechbloxModdingAPI.Utility; @@ -129,7 +130,7 @@ namespace TechbloxModdingAPI.Players public OptionalRef GetCharacterStruct(uint playerId, out ExclusiveGroupStruct group) where T : unmanaged, IEntityComponent { group = default; - if (GameState.IsBuildMode()) + if (GameClient.IsBuildMode) return entitiesDB.QueryEntityOptional(new EGID(playerId, LocalBuildingDrone.BuildGroup)); var characterGroups = CharacterExclusiveGroups.AllCharacters; diff --git a/TechbloxModdingAPI/Tests/TestRoot.cs b/TechbloxModdingAPI/Tests/TestRoot.cs index 4b3c4dd..9b116a4 100644 --- a/TechbloxModdingAPI/Tests/TestRoot.cs +++ b/TechbloxModdingAPI/Tests/TestRoot.cs @@ -9,6 +9,7 @@ using Svelto.Tasks.Lean; using Svelto.Tasks.Enumerators; using Svelto.Tasks.Lean.Unity; using TechbloxModdingAPI.Client.App; +using TechbloxModdingAPI.Client.Game; using UnityEngine; using TechbloxModdingAPI.Tasks; @@ -155,7 +156,7 @@ namespace TechbloxModdingAPI.Tests yield return Yield.It; try { - GameClient.Machines[0].EnterGame(); + GameClient.EnterBuildMode(new ClientEnvironment("GAMEID_Road_Track"), GameClient.Machines[0]); } catch (Exception e) { @@ -170,7 +171,6 @@ namespace TechbloxModdingAPI.Tests private static IEnumerator GameTests() { yield return Yield.It; - Game currentGame = Game.CurrentGame(); // in-game tests yield return new WaitForSecondsEnumerator(5).Continue(); // wait for game to finish loading var testTypesToRun = new[] @@ -225,13 +225,9 @@ namespace TechbloxModdingAPI.Tests if (index + 1 < testTypesToRun.Length) //Don't toggle on the last test { - bool running = currentGame.IsTimeRunning; - currentGame.ToggleTimeMode(); - while (running ? !currentGame.IsTimeStopped : !currentGame.IsTimeRunning) - { - Logging.MetaLog($"Waiting for time to {(running?"stop":"start")}..."); - yield return new WaitForSecondsEnumerator(1).Continue(); - } + bool running = GameClient.IsSimulationMode; + if (running) yield return GameClient.EnterTestMode().Continue(); + else yield return GameClient.ExitSimulationMode().Continue(); } yield return new WaitForSecondsEnumerator(5).Continue(); @@ -244,7 +240,7 @@ namespace TechbloxModdingAPI.Tests { Logging.MetaLog("Returning to main menu"); yield return Yield.It; - Game.CurrentGame().ExitGame(); + yield return GameClient.ExitSimulationMode().Continue(); } private static IEnumerator TearDown() diff --git a/TechbloxModdingAPI/Utility/GameEngineManager.cs b/TechbloxModdingAPI/Utility/GameEngineManager.cs deleted file mode 100644 index 428a2c5..0000000 --- a/TechbloxModdingAPI/Utility/GameEngineManager.cs +++ /dev/null @@ -1,82 +0,0 @@ -using System.Collections.Generic; -using System.Linq; - -using RobocraftX.StateSync; -using Svelto.ECS; -using TechbloxModdingAPI.Common; -using TechbloxModdingAPI.Common.Engines; - -namespace TechbloxModdingAPI.Utility -{ - /// - /// Keeps track of custom game-modifying engines - /// - public static class GameEngineManager - { - private static Dictionary _gameEngines = new(); - - private static EnginesRoot _lastEngineRoot; - - public static void AddGameEngine(IApiEngine engine) - { - _gameEngines[engine.Name] = engine; - if (_lastEngineRoot != null) - { - Logging.MetaDebugLog($"Registering Game IApiEngine {engine.Name}"); - _lastEngineRoot.AddEngine(engine); - if (engine is IFactoryEngine factoryEngine) - factoryEngine.Factory = _lastEngineRoot.GenerateEntityFactory(); - if (engine is IFunEngine funEngine) - funEngine.Functions = _lastEngineRoot.GenerateEntityFunctions(); - } - } - - public static bool ExistsGameEngine(string name) - { - return _gameEngines.ContainsKey(name); - } - - public static bool ExistsGameEngine(IApiEngine engine) - { - return ExistsGameEngine(engine.Name); - } - - public static IApiEngine GetGameEngine(string name) - { - return _gameEngines[name]; - } - - public static string[] GetGameEngineNames() - { - return _gameEngines.Keys.ToArray(); - } - - public static void RemoveGameEngine(string name) - { - if (_gameEngines[name].isRemovable) - { - _gameEngines.Remove(name); - } - } - - public static void RegisterEngines(StateSyncRegistrationHelper helper) - { - var enginesRoot = helper.enginesRoot; - _lastEngineRoot = enginesRoot; - IEntityFactory factory = enginesRoot.GenerateEntityFactory(); - IEntityFunctions functions = enginesRoot.GenerateEntityFunctions(); - foreach (var key in _gameEngines.Keys) - { - Logging.MetaDebugLog($"Registering Game IApiEngine {_gameEngines[key].Name}"); - if (_gameEngines[key] is IDeterministicEngine detEngine) - helper.AddDeterministicEngine(detEngine); - else - enginesRoot.AddEngine(_gameEngines[key]); - if (_gameEngines[key] is IFactoryEngine factEngine) - factEngine.Factory = factory; - if (_gameEngines[key] is IFunEngine funEngine) - funEngine.Functions = functions; - } - } - } -} diff --git a/TechbloxModdingAPI/Utility/GameState.cs b/TechbloxModdingAPI/Utility/GameState.cs deleted file mode 100644 index cd0a8ca..0000000 --- a/TechbloxModdingAPI/Utility/GameState.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace TechbloxModdingAPI.Utility -{ - /// - /// Utility to get the state of the current Techblox game - /// - public static class GameState - { - private static GameStateEngine gameEngine = new(); - - /// - /// Is the game in edit mode? - /// - /// Whether the game is in build mode - public static bool IsBuildMode() - { - return gameEngine.IsBuildMode(); - } - - /// - /// Is the game in simulation mode? - /// - /// Whether the game is in simulation mode - public static bool IsSimulationMode() - { - return gameEngine.IsSimulationMode(); - } - - /// - /// Is a game loaded? - /// - /// Whether Techblox has a game open (false = Main Menu) - public static bool IsInGame() - { - return gameEngine.IsInGame; - } - - public static void Init() - { - GameEngineManager.AddGameEngine(gameEngine); - } - } -} diff --git a/TechbloxModdingAPI/Utility/MenuEngineManager.cs b/TechbloxModdingAPI/Utility/MenuEngineManager.cs deleted file mode 100644 index 9887e79..0000000 --- a/TechbloxModdingAPI/Utility/MenuEngineManager.cs +++ /dev/null @@ -1,75 +0,0 @@ -using System.Collections.Generic; -using System.Linq; -using Svelto.ECS; -using TechbloxModdingAPI.Common; -using TechbloxModdingAPI.Common.Engines; - -namespace TechbloxModdingAPI.Utility -{ - /// - /// Keeps track of custom menu-modifying engines - /// - public static class MenuEngineManager - { - private static Dictionary _menuEngines = new(); - - private static EnginesRoot _lastEngineRoot; - - // menu engine management - public static void AddMenuEngine(IApiEngine engine) - { - _menuEngines[engine.Name] = engine; - if (_lastEngineRoot != null) - { - Logging.MetaDebugLog($"Registering Menu IApiEngine {engine.Name}"); - _lastEngineRoot.AddEngine(engine); - if (engine is IFactoryEngine factoryEngine) - factoryEngine.Factory = _lastEngineRoot.GenerateEntityFactory(); - if (engine is IFunEngine funEngine) - funEngine.Functions = _lastEngineRoot.GenerateEntityFunctions(); - } - } - - public static bool ExistsMenuEngine(string name) - { - return _menuEngines.ContainsKey(name); - } - - public static bool ExistsMenuEngine(IApiEngine engine) - { - return ExistsMenuEngine(engine.Name); - } - - public static IApiEngine GetMenuEngine(string name) - { - return _menuEngines[name]; - } - - public static string[] GetMenuEngineNames() - { - return _menuEngines.Keys.ToArray(); - } - - public static void RemoveMenuEngine(string name) - { - if (_menuEngines[name].isRemovable) - { - _menuEngines.Remove(name); - } - } - - public static void RegisterEngines(EnginesRoot enginesRoot) - { - _lastEngineRoot = enginesRoot; - IEntityFactory factory = enginesRoot.GenerateEntityFactory(); - IEntityFunctions functions = enginesRoot.GenerateEntityFunctions(); - foreach (var key in _menuEngines.Keys) - { - Logging.MetaDebugLog($"Registering Menu IApiEngine {_menuEngines[key].Name}"); - enginesRoot.AddEngine(_menuEngines[key]); - if (_menuEngines[key] is IFactoryEngine factEngine) factEngine.Factory = factory; - if(_menuEngines[key] is IFunEngine funEngine) funEngine.Functions = functions; - } - } - } -}