diff --git a/GamecraftModdingAPI.sln b/GamecraftModdingAPI.sln
index ff9fc7f..6482776 100644
--- a/GamecraftModdingAPI.sln
+++ b/GamecraftModdingAPI.sln
@@ -9,12 +9,15 @@ Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
+ Test|Any CPU = Test|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7FD5A7D8-4F3E-426A-B07D-7DC70442A4DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7FD5A7D8-4F3E-426A-B07D-7DC70442A4DF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7FD5A7D8-4F3E-426A-B07D-7DC70442A4DF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7FD5A7D8-4F3E-426A-B07D-7DC70442A4DF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7FD5A7D8-4F3E-426A-B07D-7DC70442A4DF}.Test|Any CPU.ActiveCfg = Test|Any CPU
+ {7FD5A7D8-4F3E-426A-B07D-7DC70442A4DF}.Test|Any CPU.Build.0 = Test|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/GamecraftModdingAPI/GamecraftModdingAPI.csproj b/GamecraftModdingAPI/GamecraftModdingAPI.csproj
index 0fdbcfd..c78272a 100644
--- a/GamecraftModdingAPI/GamecraftModdingAPI.csproj
+++ b/GamecraftModdingAPI/GamecraftModdingAPI.csproj
@@ -1,5 +1,4 @@
-
-
+
net472
true
@@ -14,19 +13,403 @@
+
+ DEBUG;TEST;TRACE
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Analytics.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Assembly-CSharp-firstpass.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Assembly-CSharp.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Authentication.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\BlockEntityFactory.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Blocks.HUDFeedbackBlocks.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\ClusterToWireConversion.Mock.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\CommandLine.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\DataLoader.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\DDNA.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\FMOD.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\FullGame.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Gamecraft.AudioBlocks.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Gamecraft.Blocks.ConsoleBlock.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Gamecraft.Blocks.DamagingSurfaceBlock.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Gamecraft.Blocks.GenericPhysicsBlocks.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Gamecraft.Blocks.LogicBlock.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\GameCraft.Blocks.ProjectileBlock.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Gamecraft.Blocks.TimerBlock.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Gamecraft.CharacterVulnerability.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Gamecraft.CharacterVulnerabilityGui.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Gamecraft.Effects.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.ConsoleBlock.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.GraphicsScreen.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.HUDFeedbackBlocks.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.Tweaks.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.Wires.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.Wires.Mockup.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Gamecraft.GUI.WorldSpaceGuis.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Gamecraft.Music.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Gamecraft.PerformanceWarnings.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Gamecraft.Tweaks.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Gamecraft.Tweaks.Mockup.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Gamecraft.VisualEffects.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Gamecraft.Wires.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Gamecraft.Wires.Input.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Gamecraft.Wires.Mockup.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\GameState.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\GPUInstancer.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Havok.Physics.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Havok.Physics.Hybrid.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\LZ4.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\MultiplayerNetworking.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\MultiplayerTest.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RCX.ScreenshotTaker.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftECS.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.AccountPreferences.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.Blocks.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.Blocks.Ghost.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.Blocks.Triggers.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.Building.BoxSelect.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.Building.Jobs.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.Character.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.ClusterToWireConversion.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.Common.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.ControlsScreen.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.Crosshair.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.FrontEnd.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.GUI.BlockLabel.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.GUI.DebugDisplay.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.GUI.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.GUI.RemoveBlock.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.GUI.ScaleGhost.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.GUIs.WorkshopPrefabs.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.Input.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.MachineEditor.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.MainGame.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.MainSimulation.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.MockCharacter.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.Multiplayer.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.Multiplayer.NetworkEntityStream.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.MultiplayerInput.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Robocraftx.ObjectIdBlocks.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.Party.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.PartyGui.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.Physics.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.PilotSeat.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.Player.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.Rendering.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.Rendering.Mock.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.SaveAndLoad.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.SaveGameDialog.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.Serializers.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.Services.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.SignalHandling.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX.StateSync.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX_SpawnPoints.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocraftX_TextBlock.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\RobocratX.SimulationCompositionRoot.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\StringFormatter.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Svelto.Common_3.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Svelto.ECS.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Svelto.Services.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Svelto.Tasks.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Unity.Addressables.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Unity.Build.SlimPlayerRuntime.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Unity.Burst.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Unity.Collections.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Unity.Deformations.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Unity.Entities.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Unity.Entities.Hybrid.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Unity.Jobs.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Unity.Mathematics.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Unity.Mathematics.Extensions.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Unity.Mathematics.Extensions.Hybrid.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Unity.Physics.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Unity.Physics.Hybrid.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Unity.Platforms.Common.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Unity.Postprocessing.Runtime.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Unity.Properties.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Unity.Properties.Reflection.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Unity.Properties.UI.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Unity.RenderPipeline.Universal.ShaderLibrary.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Unity.RenderPipelines.Core.Runtime.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Unity.RenderPipelines.Core.ShaderLibrary.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Unity.RenderPipelines.Universal.Runtime.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Unity.RenderPipelines.Universal.Shaders.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Unity.ResourceManager.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Unity.Scenes.Hybrid.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Unity.ScriptableBuildPipeline.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Unity.Serialization.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Unity.TextMeshPro.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Unity.Timeline.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Unity.Transforms.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\Unity.Transforms.Hybrid.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\UnityEngine.UI.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\uREPL.dll
+
+
+ ..\..\ref\Gamecraft_Data\Managed\VisualProfiler.dll
+
-
-
-
-
-
-
-
+
..\ref\Gamecraft_Data\Managed\IllusionInjector.dll
@@ -833,6 +1216,5 @@
..\..\ref\Gamecraft_Data\Managed\VisualProfiler.dll
-
-
-
+
+
\ No newline at end of file
diff --git a/GamecraftModdingAPI/Tests/APITestAttributes.cs b/GamecraftModdingAPI/Tests/APITestAttributes.cs
new file mode 100644
index 0000000..8506a56
--- /dev/null
+++ b/GamecraftModdingAPI/Tests/APITestAttributes.cs
@@ -0,0 +1,45 @@
+using System;
+namespace GamecraftModdingAPI.Tests
+{
+ public enum TestType
+ {
+ Menu,
+ Game,
+ SimulationMode,
+ EditMode,
+ }
+
+ [AttributeUsage(AttributeTargets.Class)]
+ public class APITestClassAttribute : Attribute
+ {
+ internal string Name;
+
+ public APITestClassAttribute(string name = "")
+ {
+ this.Name = name;
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Method)]
+ public class APITestCaseAttribute : Attribute
+ {
+ internal TestType TestType;
+
+ public APITestCaseAttribute(TestType testType)
+ {
+ this.TestType = testType;
+ }
+ }
+
+ [AttributeUsage(AttributeTargets.Method)]
+ public class APITestStartUpAttribute : Attribute
+ {
+
+ }
+
+ [AttributeUsage(AttributeTargets.Method)]
+ public class APITestTearDownAttribute : Attribute
+ {
+
+ }
+}
diff --git a/GamecraftModdingAPI/Tests/Assert.cs b/GamecraftModdingAPI/Tests/Assert.cs
new file mode 100644
index 0000000..fb03013
--- /dev/null
+++ b/GamecraftModdingAPI/Tests/Assert.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Concurrent;
+using System.IO;
+using System.Runtime.CompilerServices;
+
+namespace GamecraftModdingAPI.Tests
+{
+ public static class Assert
+ {
+ private static StreamWriter logFile = null;
+
+ private static ConcurrentDictionary callbacks = new ConcurrentDictionary();
+
+ private const string PASS = "SUCCESS: ";
+
+ private const string FAIL = "FAILURE: ";
+
+ private const string WARN = "WARNING: ";
+
+ private const string INFO = "DEBUG: ";
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void Log(string msg, string end = "\n")
+ {
+ if (logFile == null) openTestLog();
+ logFile.Write(msg + end);
+ logFile.Flush();
+ }
+
+ public static EventHandler CallsBack(string eventName, string eventMsg = null)
+ {
+ if (eventMsg == null) eventMsg = $"expected callback to {eventName} but it never occurred...";
+ callbacks[eventName] = eventMsg;
+
+ return (sender, args) =>
+ {
+ string value = null;
+ if (!callbacks.TryRemove(eventName, out value)) { Log(WARN + $"callback to {eventName} occurred again or a related error occurred... (Received '{args.ToString()}' from '{(sender == null ? (string)sender : sender.ToString())}')"); }
+ Log(PASS + $"callback to {eventName} occurred... (Received '{args.ToString()}' from '{(sender == null ? (string)sender : sender.ToString())}')");
+ TestRoot.TestsPassed = true;
+ };
+ }
+
+ internal static void CallsComplete()
+ {
+ foreach(string key in callbacks.Keys)
+ {
+ Log(FAIL + callbacks[key]);
+ TestRoot.TestsPassed = false;
+ }
+ }
+
+ internal static void CloseLog()
+ {
+ if (logFile != null) logFile.Close();
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ private static void openTestLog()
+ {
+ logFile = File.CreateText(TestRoot.ReportFile);
+ }
+ }
+}
diff --git a/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs b/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs
index dc07e1e..fa65ebb 100644
--- a/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs
+++ b/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs
@@ -48,11 +48,11 @@ namespace GamecraftModdingAPI.Tests
GamecraftModdingAPI.Main.Shutdown();
}
- public void OnApplicationStart()
- {
+ public void OnApplicationStart()
+ {
FileLog.Reset();
Harmony.DEBUG = true;
- GamecraftModdingAPI.Main.Init();
+ GamecraftModdingAPI.Main.Init();
Logging.MetaDebugLog($"Version group id {(uint)ApiExclusiveGroups.versionGroup}");
// in case Steam is not installed/running
// this will crash the game slightly later during startup
@@ -62,7 +62,7 @@ namespace GamecraftModdingAPI.Tests
// disable some Gamecraft analytics
//AnalyticsDisablerPatch.DisableAnalytics = true;
// disable background music
- Logging.MetaDebugLog("Audio Mixers: "+string.Join(",", AudioTools.GetMixers()));
+ Logging.MetaDebugLog("Audio Mixers: " + string.Join(",", AudioTools.GetMixers()));
//AudioTools.SetVolume(0.0f, "Music"); // The game now sets this from settings again after this is called :(
//Utility.VersionTracking.Enable();//(very) unstable
@@ -76,60 +76,68 @@ namespace GamecraftModdingAPI.Tests
HandlerBuilder.Builder("menuact API debug")
.Handle(EventType.Menu)
- .OnActivation(() => { Logging.Log("Menu Activated event!"); })
+ .OnActivation(() => { Logging.Log("Menu Activated event!"); })
.OnDestruction(() => { Logging.Log("Menu Destroyed event!"); })
.Build();
HandlerBuilder.Builder("menuswitch API debug")
- .Handle(EventType.MenuSwitchedTo)
- .OnActivation(() => { Logging.Log("Menu Switched To event!"); })
- .Build();
+ .Handle(EventType.MenuSwitchedTo)
+ .OnActivation(() => { Logging.Log("Menu Switched To event!"); })
+ .Build();
HandlerBuilder.Builder("gameact API debug")
- .Handle(EventType.Menu)
- .OnActivation(() => { Logging.Log("Game Activated event!"); })
- .OnDestruction(() => { Logging.Log("Game Destroyed event!"); })
- .Build();
+ .Handle(EventType.Menu)
+ .OnActivation(() => { Logging.Log("Game Activated event!"); })
+ .OnDestruction(() => { Logging.Log("Game Destroyed event!"); })
+ .Build();
HandlerBuilder.Builder("gamerel API debug")
- .Handle(EventType.GameReloaded)
- .OnActivation(() => { Logging.Log("Game Reloaded event!"); })
- .Build();
+ .Handle(EventType.GameReloaded)
+ .OnActivation(() => { Logging.Log("Game Reloaded event!"); })
+ .Build();
HandlerBuilder.Builder("gameswitch API debug")
- .Handle(EventType.GameSwitchedTo)
- .OnActivation(() => { Logging.Log("Game Switched To event!"); })
- .Build();
+ .Handle(EventType.GameSwitchedTo)
+ .OnActivation(() => { Logging.Log("Game Switched To event!"); })
+ .Build();
HandlerBuilder.Builder("simulationswitch API debug")
- .Handle(EventType.SimulationSwitchedTo)
- .OnActivation(() => { Logging.Log("Game Mode Simulation Switched To event!"); })
- .Build();
+ .Handle(EventType.SimulationSwitchedTo)
+ .OnActivation(() => { Logging.Log("Game Mode Simulation Switched To event!"); })
+ .Build();
HandlerBuilder.Builder("buildswitch API debug")
- .Handle(EventType.BuildSwitchedTo)
- .OnActivation(() => { Logging.Log("Game Mode Build Switched To event!"); })
- .Build();
+ .Handle(EventType.BuildSwitchedTo)
+ .OnActivation(() => { Logging.Log("Game Mode Build Switched To event!"); })
+ .Build();
HandlerBuilder.Builder("menu activated API error thrower test")
.Handle(EventType.Menu)
.OnActivation(() => { throw new Exception("Event Handler always throws an exception!"); })
.Build();
- // debug/test commands
+ /*HandlerBuilder.Builder("enter game from menu test")
+ .Handle(EventType.Menu)
+ .OnActivation(() =>
+ {
+ Tasks.Scheduler.Schedule(new Tasks.Repeatable(enterGame, shouldRetry, 0.2f));
+ })
+ .Build();*/
+
+ // debug/test commands
if (Dependency.Hell("ExtraCommands"))
{
CommandBuilder.Builder()
- .Name("Exit")
- .Description("Close Gamecraft immediately, without any prompts")
- .Action(() => { UnityEngine.Application.Quit(); })
- .Build();
-
+ .Name("Exit")
+ .Description("Close Gamecraft immediately, without any prompts")
+ .Action(() => { UnityEngine.Application.Quit(); })
+ .Build();
+
CommandBuilder.Builder()
- .Name("SetFOV")
- .Description("Set the player camera's field of view")
- .Action((float d) => { UnityEngine.Camera.main.fieldOfView = d; })
- .Build();
+ .Name("SetFOV")
+ .Description("Set the player camera's field of view")
+ .Action((float d) => { UnityEngine.Camera.main.fieldOfView = d; })
+ .Build();
CommandBuilder.Builder()
.Name("MoveLastBlock")
@@ -144,14 +152,14 @@ namespace GamecraftModdingAPI.Tests
}).Build();
CommandBuilder.Builder()
- .Name("PlaceAluminium")
- .Description("Place a block of aluminium at the given coordinates")
- .Action((float x, float y, float z) =>
- {
- var block = Block.PlaceNew(BlockIDs.AluminiumCube, new float3(x, y, z));
- Logging.CommandLog("Block placed with type: " + block.Type);
- })
- .Build();
+ .Name("PlaceAluminium")
+ .Description("Place a block of aluminium at the given coordinates")
+ .Action((float x, float y, float z) =>
+ {
+ var block = Block.PlaceNew(BlockIDs.AluminiumCube, new float3(x, y, z));
+ Logging.CommandLog("Block placed with type: " + block.Type);
+ })
+ .Build();
CommandBuilder.Builder()
.Name("PlaceAluminiumLots")
@@ -161,8 +169,8 @@ namespace GamecraftModdingAPI.Tests
Logging.CommandLog("Starting...");
var sw = Stopwatch.StartNew();
for (int i = 0; i < 100; i++)
- for (int j = 0; j < 100; j++)
- Block.PlaceNew(BlockIDs.AluminiumCube, new float3(x + i, y, z + j));
+ for (int j = 0; j < 100; j++)
+ Block.PlaceNew(BlockIDs.AluminiumCube, new float3(x + i, y, z + j));
//Block.Sync();
sw.Stop();
Logging.CommandLog("Finished in " + sw.ElapsedMilliseconds + "ms");
@@ -171,10 +179,10 @@ namespace GamecraftModdingAPI.Tests
//With Sync(): 1135ms
//Without Sync(): 134ms
//Async: 348 794ms, doesn't freeze game
- //Without Sync() but wait for submission: 530ms
- //With Sync() at the end: 380ms
+ //Without Sync() but wait for submission: 530ms
+ //With Sync() at the end: 380ms
- Block b = null;
+ Block b = null;
CommandBuilder.Builder("moveBlockInSim", "Run in build mode first while looking at a block, then in sim to move it up")
.Action(() =>
{
@@ -204,7 +212,7 @@ namespace GamecraftModdingAPI.Tests
return;
}
new Player(PlayerType.Local).GetBlockLookedAt().Color =
- new BlockColor {Color = color};
+ new BlockColor { Color = color };
Logging.CommandLog("Colored block to " + color);
}).Build();
@@ -230,7 +238,7 @@ namespace GamecraftModdingAPI.Tests
Block.Removed += (sender, args) =>
Logging.MetaDebugLog("Removed block " + args.Type + " with ID " + args.ID);
- /*
+ /*
CommandManager.AddCommand(new SimpleCustomCommandEngine((float d) => { UnityEngine.Camera.main.fieldOfView = d; },
"SetFOV", "Set the player camera's field of view"));
CommandManager.AddCommand(new SimpleCustomCommandEngine(
@@ -274,8 +282,8 @@ namespace GamecraftModdingAPI.Tests
*/
}
- // dependency test
- if (Dependency.Hell("GamecraftScripting", new Version("0.0.1.0")))
+ // dependency test
+ if (Dependency.Hell("GamecraftScripting", new Version("0.0.1.0")))
{
Logging.LogWarning("You're in GamecraftScripting dependency hell");
}
@@ -283,7 +291,11 @@ namespace GamecraftModdingAPI.Tests
{
Logging.Log("Compatible GamecraftScripting detected");
}
- }
+
+#if TEST
+ TestRoot.RunTests();
+#endif
+ }
private string modsString;
private string InstalledMods()
@@ -295,6 +307,40 @@ namespace GamecraftModdingAPI.Tests
return modsString = sb.ToString();
}
+ private bool retry = true;
+
+ private bool shouldRetry()
+ {
+ return retry;
+ }
+
+ private void enterGame()
+ {
+ App.Client app = new App.Client();
+ App.Game[] myGames = app.MyGames;
+ Logging.MetaDebugLog($"MyGames count {myGames.Length}");
+ if (myGames.Length != 0)
+ {
+ Logging.MetaDebugLog($"MyGames[0] EGID {myGames[0].EGID}");
+ retry = false;
+ try
+ {
+ //myGames[0].Description = "test msg pls ignore"; // make sure game exists first
+ Logging.MetaDebugLog($"Entering game {myGames[0].Name}");
+ myGames[0].EnterGame();
+ }
+ catch (Exception e)
+ {
+ Logging.MetaDebugLog($"Failed to enter game; exception: {e}");
+ retry = true;
+ }
+ }
+ else
+ {
+ Logging.MetaDebugLog("MyGames not populated yet :(");
+ }
+ }
+
public void OnFixedUpdate() { }
public void OnLateUpdate() { }
diff --git a/GamecraftModdingAPI/Tests/TestRoot.cs b/GamecraftModdingAPI/Tests/TestRoot.cs
new file mode 100644
index 0000000..167173f
--- /dev/null
+++ b/GamecraftModdingAPI/Tests/TestRoot.cs
@@ -0,0 +1,247 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Reflection;
+using System.Linq; // welcome to the dark side
+
+using Svelto.Tasks;
+using Svelto.Tasks.Lean;
+using Svelto.Tasks.Enumerators;
+using UnityEngine;
+
+using GamecraftModdingAPI.App;
+using GamecraftModdingAPI.Tasks;
+using GamecraftModdingAPI.Utility;
+
+namespace GamecraftModdingAPI.Tests
+{
+ public static class TestRoot
+ {
+ public static bool AutoShutdown = true;
+
+ public const string ReportFile = "GamecraftModdingAPI_tests.log";
+
+ private static bool _testsPassed = false;
+
+ private static uint _testsCount = 0;
+
+ private static uint _testsCountPassed = 0;
+
+ private static uint _testsCountFailed = 0;
+
+ private static string state = "StartingUp";
+
+ private static Stopwatch timer;
+
+ private static List testTypes = null;
+
+ public static bool TestsPassed
+ {
+ get => _testsPassed;
+ set
+ {
+ _testsPassed = _testsPassed && value;
+ _testsCount++;
+ if (value)
+ {
+ _testsCountPassed++;
+ }
+ else
+ {
+ _testsCountFailed++;
+ }
+ }
+ }
+
+ private static void StartUp()
+ {
+ // init
+ timer = Stopwatch.StartNew();
+ _testsPassed = true;
+ _testsCount = 0;
+ _testsCountPassed = 0;
+ _testsCountFailed = 0;
+ // flow control
+ Game.Enter += (sender, args) => { GameTests().RunOn(RobocraftX.Schedulers.Lean.EveryFrameStepRunner_RUNS_IN_TIME_STOPPED_AND_RUNNING); };
+ Game.Exit += (s, a) => state = "ReturningFromGame";
+ Client.EnterMenu += (sender, args) =>
+ {
+ if (state == "EnteringMenu")
+ {
+ MenuTests().RunOn(Scheduler.leanRunner);
+ state = "EnteringGame";
+ }
+ if (state == "ReturningFromGame")
+ {
+ TearDown().RunOn(Scheduler.leanRunner);
+ state = "ShuttingDown";
+ }
+ };
+ // init tests here
+ foreach (Type t in testTypes)
+ {
+ foreach (MethodBase m in t.GetMethods())
+ {
+ if (m.GetCustomAttribute() != null)
+ {
+ m.Invoke(null, new object[0]);
+ }
+ }
+ }
+ state = "EnteringMenu";
+ }
+
+ private static IEnumerator MenuTests()
+ {
+ yield return Yield.It;
+ // menu tests
+ foreach (Type t in testTypes)
+ {
+ foreach (MethodBase m in t.GetMethods())
+ {
+ APITestCaseAttribute a = m.GetCustomAttribute();
+ if (a != null && a.TestType == TestType.Menu)
+ {
+ m.Invoke(null, new object[0]);
+ yield return Yield.It;
+ }
+ }
+ }
+ // load game
+ yield return GoToGameTests().Continue();
+ }
+
+ private static IEnumerator GoToGameTests()
+ {
+ Client app = new Client();
+ int oldLength = 0;
+ while (app.MyGames.Length == 0 || oldLength != app.MyGames.Length)
+ {
+ oldLength = app.MyGames.Length;
+ yield return new WaitForSecondsEnumerator(1).Continue();
+ }
+ yield return Yield.It;
+ app.MyGames[0].EnterGame();
+ // returning from a new game without saving will hard lock GC (it's an invalid state)
+ //Game newGame = Game.NewGame();
+ //yield return new WaitForSecondsEnumerator(5).Continue(); // wait for sync
+ //newGame.EnterGame();
+ }
+
+ 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
+ foreach (Type t in testTypes)
+ {
+ foreach (MethodBase m in t.GetMethods())
+ {
+ APITestCaseAttribute a = m.GetCustomAttribute();
+ if (a != null && a.TestType == TestType.Game)
+ {
+ m.Invoke(null, new object[0]);
+ yield return Yield.It;
+ }
+ }
+ }
+ currentGame.ToggleTimeMode();
+ yield return new WaitForSecondsEnumerator(5).Continue();
+ // simulation tests
+ foreach (Type t in testTypes)
+ {
+ foreach (MethodBase m in t.GetMethods())
+ {
+ APITestCaseAttribute a = m.GetCustomAttribute();
+ if (a != null && a.TestType == TestType.SimulationMode)
+ {
+ m.Invoke(null, new object[0]);
+ yield return Yield.It;
+ }
+ }
+ }
+ currentGame.ToggleTimeMode();
+ yield return new WaitForSecondsEnumerator(5).Continue();
+ // build tests
+ foreach (Type t in testTypes)
+ {
+ foreach (MethodBase m in t.GetMethods())
+ {
+ APITestCaseAttribute a = m.GetCustomAttribute();
+ if (a != null && a.TestType == TestType.EditMode)
+ {
+ m.Invoke(null, new object[0]);
+ yield return Yield.It;
+ }
+ }
+ }
+ // exit game
+ yield return new WaitForSecondsEnumerator(5).Continue();
+ yield return ReturnToMenu().Continue();
+ }
+
+ private static IEnumerator ReturnToMenu()
+ {
+ Logging.MetaLog("Returning to main menu");
+ yield return Yield.It;
+ Game.CurrentGame().ExitGame();
+ }
+
+ private static IEnumerator TearDown()
+ {
+ yield return new WaitForSecondsEnumerator(5).Continue();
+ Logging.MetaLog("Tearing down test run");
+ // dispose tests here
+ foreach (Type t in testTypes)
+ {
+ foreach (MethodBase m in t.GetMethods())
+ {
+ if (m.GetCustomAttribute() != null)
+ {
+ m.Invoke(null, new object[0]);
+ yield return Yield.It;
+ }
+ }
+ }
+ // finish up
+ Assert.CallsComplete();
+ timer.Stop();
+ string verdict = _testsPassed ? "--- PASSED :) ---" : "--- FAILED :( ---";
+ Assert.Log($"VERDICT: {verdict} ({_testsCountPassed}/{_testsCountFailed}/{_testsCount} P/F/T in {timer.ElapsedMilliseconds}ms)");
+ yield return Yield.It;
+ // end game
+ Logging.MetaLog("Completed test run: " + verdict);
+ yield return Yield.It;
+ Assert.CloseLog();
+ if (AutoShutdown) Application.Quit();
+ }
+
+ private static void FindTests(Assembly asm)
+ {
+ testTypes = new List();
+ foreach (Type t in asm.GetTypes())
+ {
+ if (t.GetCustomAttribute() != null)
+ {
+ testTypes.Add(t);
+ }
+ }
+ }
+
+ public static void RunTests(Assembly asm = null)
+ {
+ if (asm == null) asm = Assembly.GetExecutingAssembly();
+ FindTests(asm);
+ Logging.MetaLog("Starting test run");
+ // log metadata
+ Assert.Log($"Unity {Application.unityVersion}");
+ Assert.Log($"Gamecraft {Application.version}");
+ Assert.Log($"GamecraftModdingAPI {Assembly.GetExecutingAssembly().GetName().Version}");
+ Assert.Log($"Testing {asm.GetName().Name} {asm.GetName().Version}");
+ Assert.Log($"START: --- {DateTime.Now.ToString()} --- ({testTypes.Count} tests classes detected)");
+ StartUp();
+ Logging.MetaLog("Test StartUp complete");
+ }
+ }
+}
diff --git a/GamecraftModdingAPI/Tests/TestTest.cs b/GamecraftModdingAPI/Tests/TestTest.cs
new file mode 100644
index 0000000..02eeda0
--- /dev/null
+++ b/GamecraftModdingAPI/Tests/TestTest.cs
@@ -0,0 +1,52 @@
+using System;
+
+using System.Reflection;
+
+using HarmonyLib;
+
+namespace GamecraftModdingAPI.Tests
+{
+#if TEST
+ ///
+ /// Test test test.
+ ///
+ [APITestClass]
+ public static class TestTest
+ {
+ public static event EventHandler StartUp;
+
+ public static event EventHandler Test;
+
+ public static event EventHandler TearDown;
+
+ [APITestStartUp]
+ public static void Init()
+ {
+ StartUp += Assert.CallsBack("TestStartUp");
+ Test += Assert.CallsBack("TestCase");
+ TearDown += Assert.CallsBack("TestTearDown");
+ StartUp(null, default(TestEventArgs));
+ }
+
+ [APITestCase(TestType.Menu)]
+ public static void RunTest()
+ {
+ Test(null, default(TestEventArgs));
+ }
+
+ [APITestTearDown]
+ public static void End()
+ {
+ TearDown(null, default(TestEventArgs));
+ }
+ }
+
+ public struct TestEventArgs
+ {
+ public override string ToString()
+ {
+ return "TestEventArgs{}";
+ }
+ }
+#endif
+}