From 5dff88d7032eaa637db7995ae7c0cda102a326d6 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Mon, 21 Aug 2023 23:59:29 +0200 Subject: [PATCH] Switch from IPA to BepInEx - Removed a bunch of test code - Preparing for 3.0 --- Automation/gen_csproj.py | 2 +- CodeGenerator/CodeGenerator.csproj | 2 +- TechbloxModdingAPI/Main.cs | 2 +- TechbloxModdingAPI/TechbloxModdingAPI.csproj | 50 +- .../Tests/TechbloxModdingAPIPluginTest.cs | 436 +++--------------- TechbloxModdingAPI/Utility/Dependency.cs | 46 +- 6 files changed, 92 insertions(+), 446 deletions(-) diff --git a/Automation/gen_csproj.py b/Automation/gen_csproj.py index fc854b8..0c88372 100755 --- a/Automation/gen_csproj.py +++ b/Automation/gen_csproj.py @@ -41,7 +41,7 @@ if __name__ == "__main__": args = parser.parse_args() print("Building Assembly references") - asmXml = buildReferencesXml("../ref/Techblox_Data/Managed") + asmXml = buildReferencesXml("../ref_TB/Techblox_Data/Managed") # print(asmXml) with open("../TechbloxModdingAPI/TechbloxModdingAPI.csproj", "r") as xmlFile: diff --git a/CodeGenerator/CodeGenerator.csproj b/CodeGenerator/CodeGenerator.csproj index 766eefc..6952a6f 100644 --- a/CodeGenerator/CodeGenerator.csproj +++ b/CodeGenerator/CodeGenerator.csproj @@ -19,7 +19,7 @@ DEBUG;TEST;TRACE - + diff --git a/TechbloxModdingAPI/Main.cs b/TechbloxModdingAPI/Main.cs index 554debe..de38cc6 100644 --- a/TechbloxModdingAPI/Main.cs +++ b/TechbloxModdingAPI/Main.cs @@ -104,7 +104,7 @@ namespace TechbloxModdingAPI } Scheduler.Dispose(); var currentAssembly = Assembly.GetExecutingAssembly(); - harmony.UnpatchAll(currentAssembly.GetName().Name); + harmony.UnpatchSelf(); harmony = null; Logging.MetaLog($"{currentAssembly.GetName().Name} v{currentAssembly.GetName().Version} shutdown"); } diff --git a/TechbloxModdingAPI/TechbloxModdingAPI.csproj b/TechbloxModdingAPI/TechbloxModdingAPI.csproj index 2138283..5f6e410 100644 --- a/TechbloxModdingAPI/TechbloxModdingAPI.csproj +++ b/TechbloxModdingAPI/TechbloxModdingAPI.csproj @@ -1,40 +1,33 @@ - + + netstandard2.1 - true - 2.3.0 + TechbloxModdingAPI + An object-oriented API for Techblox mods. + 3.0.0 Exmods GNU General Public Licence 3+ https://git.exmods.org/modtainers/GamecraftModdingAPI en-CA true - 9 - - - - - - - DEBUG;TEST;TRACE + latest + - + + + + + + + + + - - - - - ..\ref_TB\Techblox_Data\Managed\IllusionInjector.dll - ..\..\ref_TB\Techblox_Data\Managed\IllusionInjector.dll - - - ..\ref_TB\Techblox_Data\Managed\IllusionPlugin.dll - ..\..\ref_TB\Techblox_Data\Managed\IllusionPlugin.dll - ..\ref_TB\Techblox_Data\Managed\Accessibility.dll ..\..\ref_TB\Techblox_Data\Managed\Accessibility.dll @@ -51,6 +44,10 @@ ..\ref_TB\Techblox_Data\Managed\Assembly-CSharp.dll ..\..\ref_TB\Techblox_Data\Managed\Assembly-CSharp.dll + + ..\ref_TB\Techblox_Data\Managed\Assembly-Csharp.dll + ..\..\ref_TB\Techblox_Data\Managed\Assembly-Csharp.dll + ..\ref_TB\Techblox_Data\Managed\AWSSDK.Core.dll ..\..\ref_TB\Techblox_Data\Managed\AWSSDK.Core.dll @@ -1584,9 +1581,12 @@ ..\..\ref_TB\Techblox_Data\Managed\ZFBrowser.dll + + + - + - \ No newline at end of file + diff --git a/TechbloxModdingAPI/Tests/TechbloxModdingAPIPluginTest.cs b/TechbloxModdingAPI/Tests/TechbloxModdingAPIPluginTest.cs index 32ed3e5..1f9c5f9 100644 --- a/TechbloxModdingAPI/Tests/TechbloxModdingAPIPluginTest.cs +++ b/TechbloxModdingAPI/Tests/TechbloxModdingAPIPluginTest.cs @@ -1,406 +1,84 @@ using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; using System.Reflection; using System.Text; -using System.Text.RegularExpressions; -using DataLoader; -using TechbloxModdingAPI.App; +using BepInEx; +using BepInEx.Bootstrap; using HarmonyLib; -using IllusionInjector; -// test using RobocraftX.FrontEnd; -using ServiceLayer; -using Unity.Mathematics; -using UnityEngine; -using Svelto.Tasks; -using Svelto.Tasks.Lean; -using TechbloxModdingAPI.Blocks; +using TechbloxModdingAPI.App; using TechbloxModdingAPI.Commands; -using TechbloxModdingAPI.Players; -using TechbloxModdingAPI.Tasks; -using TechbloxModdingAPI.Utility; namespace TechbloxModdingAPI.Tests { -#if DEBUG - // unused by design - /// - /// Modding API implemented as a standalone IPA Plugin. - /// Ideally, TechbloxModdingAPI should be loaded by another mod; not itself - /// - class TechbloxModdingAPIPluginTest : IllusionPlugin.IEnhancedPlugin + #if DEBUG // The API should be loaded by other plugins, but it can be used by itself for testing + [BepInPlugin("org.exmods.TechbloxModdingAPIPluginTest", PluginInfo.PLUGIN_NAME, PluginInfo.PLUGIN_VERSION)] + [BepInProcess("Techblox.exe")] + public class TechbloxModdingAPIPluginTest : BaseUnityPlugin { - - private static Harmony harmony { get; set; } - - public override string Name { get; } = Assembly.GetExecutingAssembly().GetName().Name; - - public override string Version { get; } = Assembly.GetExecutingAssembly().GetName().Version.ToString(); - - public string HarmonyID { get; } = "org.git.exmods.modtainers.techbloxmoddingapi"; - - public override void OnApplicationQuit() + private void Awake() { - Main.Shutdown(); - } - - public override void OnApplicationStart() - { - FileLog.Reset(); - Harmony.DEBUG = true; - Main.Init(); - Logging.MetaDebugLog($"Version group id {ApiExclusiveGroups.versionGroup}"); - // disable background music - 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 - - // debug/test handlers - Client.EnterMenu += (sender, args) => throw new Exception("Test handler always throws an exception!"); - Client.EnterMenu += (sender, args) => Console.WriteLine("EnterMenu handler after erroring handler"); - Game.Enter += (s, a) => - { - Player.LocalPlayer.SeatEntered += (sender, args) => - Console.WriteLine($"Player {Player.LocalPlayer} entered seat {args.Seat}"); - Player.LocalPlayer.SeatExited += (sender, args) => - Console.WriteLine($"Player {Player.LocalPlayer} exited seat {args.Seat}"); - }; - - // debug/test commands - if (Dependency.Hell("ExtraCommands")) - { - CommandBuilder.Builder() - .Name("Exit") - .Description("Close Techblox 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(); - - CommandBuilder.Builder() - .Name("MoveLastBlock") - .Description("Move the most-recently-placed block, and any connected blocks by the given offset") - .Action((float x, float y, float z) => - { - if (GameState.IsBuildMode()) - foreach (var block in Block.GetLastPlacedBlock().GetConnectedCubes()) - block.Position += new Unity.Mathematics.float3(x, y, z); - else - Logging.CommandLogError("Blocks can only be moved in Build mode!"); - }).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.Cube, new float3(x, y, z)); - Logging.CommandLog("Block placed with type: " + block.Type); - }) - .Build(); - - CommandBuilder.Builder() - .Name("PlaceAluminiumLots") - .Description("Place a lot of blocks of aluminium at the given coordinates") - .Action((float x, float y, float z) => - { - Logging.CommandLog("Starting..."); - var sw = Stopwatch.StartNew(); - for (int i = 0; i < 100; i++) - for (int j = 0; j < 100; j++) - Block.PlaceNew(BlockIDs.Cube, new float3(x + i, y, z + j)); - sw.Stop(); - Logging.CommandLog("Finished in " + sw.ElapsedMilliseconds + "ms"); - }) - .Build(); - - Block b = null; - CommandBuilder.Builder("moveBlockInSim", "Run in build mode first while looking at a block, then in sim to move it up") - .Action(() => - { - if (b == null) - { - b = new Player(PlayerType.Local).GetBlockLookedAt(); - Logging.CommandLog("Block saved: " + b); - } - else - Logging.CommandLog("Block moved to: " + (b.GetSimBody().Position += new float3(0, 2, 0))); - }).Build(); - - CommandBuilder.Builder("Error", "Throw an error to make sure SimpleCustomCommandEngine's wrapper catches it.") - .Action(() => { throw new Exception("Error Command always throws an error"); }) - .Build(); - - CommandBuilder.Builder("ColorBlock", - "Change color of the block looked at if there's any.") - .Action(str => - { - if (!Enum.TryParse(str, out BlockColors color)) - { - Logging.CommandLog("Color " + str + " not found! Interpreting as 4 color values."); - var s = str.Split(' '); - new Player(PlayerType.Local).GetBlockLookedAt().CustomColor = new float4(float.Parse(s[0]), - float.Parse(s[1]), float.Parse(s[2]), float.Parse(s[3])); - return; - } - - new Player(PlayerType.Local).GetBlockLookedAt().Color = color; - Logging.CommandLog("Colored block to " + color); - - }).Build(); - - CommandBuilder.Builder("MoveBlockByID", "Gets a block based on its object identifier and teleports it up.") - .Action(ch => - { - foreach (var body in SimBody.GetFromObjectID(ch)) - { - Logging.CommandLog("SimBody: " + body); - body.Position += new float3(0, 10, 0); - foreach (var bodyConnectedBody in body.GetConnectedBodies()) - { - Logging.CommandLog("Moving " + bodyConnectedBody); - bodyConnectedBody.Position += new float3(0, 10, 0); - } - } - }).Build(); - - CommandBuilder.Builder("TestChunkHealth", "Sets the chunk looked at to the given health.") - .Action((float val, float max) => - { - var body = new Player(PlayerType.Local).GetSimBodyLookedAt(); - if (body == null) return; - body.CurrentHealth = val; - body.InitialHealth = max; - Logging.CommandLog("Health set to: " + val); - }).Build(); - - CommandBuilder.Builder("placeBlockGroup", "Places some blocks in a group") - .Action((float x, float y, float z) => - { - var pos = new float3(x, y, z); - var group = BlockGroup.Create(new Block(BlockIDs.Cube, pos) {Color = BlockColors.Aqua}); - new Block(BlockIDs.Cube, pos += new float3(1, 0, 0)) - {Color = BlockColors.Blue, BlockGroup = group}; - new Block(BlockIDs.Cube, pos += new float3(1, 0, 0)) - {Color = BlockColors.Green, BlockGroup = group}; - new Block(BlockIDs.Cube, pos + new float3(1, 0, 0)) - {Color = BlockColors.Lime, BlockGroup = group}; - }).Build(); - - CommandBuilder.Builder("placeCustomBlock", "Places a custom block, needs a custom catalog and assets.") - .Action((float x, float y, float z) => - { - Logging.CommandLog("Block placed: " + - Block.PlaceNew((BlockIDs) 500, new float3(0, 0, 0))); - }).Build(); - - CommandBuilder.Builder("toggleTimeMode", "Enters or exits simulation.") - .Action((float x, float y, float z) => - { - Game.CurrentGame().ToggleTimeMode(); - }).Build(); - - CommandBuilder.Builder("testColorBlock", "Tests coloring a block to default color") - .Action(() => Player.LocalPlayer.GetBlockLookedAt().Color = BlockColors.Default).Build(); - CommandBuilder.Builder("testMaterialBlock", "Tests materialing a block to default material") - .Action(() => Player.LocalPlayer.GetBlockLookedAt().Material = BlockMaterial.Default).Build(); - CommandBuilder.Builder("testGameName", "Tests changing the game name") - .Action(() => Game.CurrentGame().Name = "Test").Build(); - CommandBuilder.Builder("makeBlockStatic", "Makes a block you look at static") - .Action(() => Player.LocalPlayer.GetBlockLookedAt().Static = true).Build(); - - Game.AddPersistentDebugInfo("InstalledMods", InstalledMods); - /*Block.Placed += (sender, args) => - Logging.MetaDebugLog("Placed block " + args.Block); - Block.Removed += (sender, args) => - Logging.MetaDebugLog("Removed block " + args.Block);*/ - } - - // dependency test - if (Dependency.Hell("TechbloxScripting", new Version("0.0.1.0"))) - { - Logging.LogWarning("You're in TechbloxScripting dependency hell"); - } - else - { - Logging.Log("Compatible TechbloxScripting detected"); - } - // Interface test - /*Group uiGroup = new Group(new Rect(20, 20, 200, 500), "TechbloxModdingAPI_UITestGroup", true); - var button = new Button("TEST"); - button.OnClick += (b, __) => { Logging.MetaDebugLog($"Click on {((Interface.IMGUI.Button)b).Name}");}; - var button2 = new Button("TEST2"); - button2.OnClick += (b, __) => { Logging.MetaDebugLog($"Click on {((Interface.IMGUI.Button)b).Name}");}; - Text uiText = new Text("", multiline: true); - uiText.OnEdit += (t, txt) => { Logging.MetaDebugLog($"Text in {((Text)t).Name} is now '{txt}'"); }; - Label uiLabel = new Label("Label!"); - Image uiImg = new Image(name:"Behold this texture!"); - uiImg.Enabled = false; - uiGroup.AddElement(button); - uiGroup.AddElement(button2); - uiGroup.AddElement(uiText); - uiGroup.AddElement(uiLabel); - uiGroup.AddElement(uiImg);*/ - - /*Addressables.LoadAssetAsync("Assets/Art/Textures/UI/FrontEndMap/RCX_Blue_Background_5k.jpg") - .Completed += - handle => - { - uiImg.Texture = handle.Result; - uiImg.Enabled = true; - Logging.MetaDebugLog($"Got blue bg asset {handle.Result}"); - };*/ - - /*((FasterList)AccessTools.Property(typeof(GuiInputMap), "GuiInputsButtonDown").GetValue(null)) - .Add(new GuiInputMap.GuiInputMapElement(RewiredConsts.Action.ToggleCommandLine, GuiIn))*/ - - /*Game.Enter += (sender, e) => + Main.Init(); + Client.EnterMenu += (sender, args) => throw new Exception("Test handler always throws an exception!"); + Client.EnterMenu += (sender, args) => Console.WriteLine("EnterMenu handler after erroring handler"); + Game.Enter += (s, a) => { - ushort lastKey = ushort.MaxValue; - foreach (var kv in FullGameFields._dataDb.GetValues() - .OrderBy(kv=>ushort.Parse(kv.Key))) - { - var data = (CubeListData) kv.Value; - ushort currentKey = ushort.Parse(kv.Key); - var toReplace = new Dictionary - { - {"Scalable", ""}, {"Qtr", "Quarter"}, {"RNeg", "Rounded Negative"}, - {"Neg", "Negative"}, {"Tetra", "Tetrahedron"}, - {"RWedge", "Rounded Wedge"}, {"RTetra", "Rounded Tetrahedron"} - }; - string name = LocalizationService.Localize(data.CubeNameKey).Split(' ').Select(str => - str.Length > 0 ? char.ToUpper(str[0]) + str.Substring(1) : str).Aggregate((a, b) => a + b) - .Replace("-", ""); - foreach (var rkv in toReplace) - { - name = Regex.Replace(name, rkv.Key + "([A-Z]|$)", rkv.Value + "$1"); - } - Console.WriteLine($"{name}{(currentKey != lastKey + 1 ? $" = {currentKey}" : "")},"); - lastKey = currentKey; - } + Player.LocalPlayer.SeatEntered += (sender, args) => + Console.WriteLine($"Player {Player.LocalPlayer} entered seat {args.Seat}"); + Player.LocalPlayer.SeatExited += (sender, args) => + Console.WriteLine($"Player {Player.LocalPlayer} exited seat {args.Seat}"); }; - Game.Enter += (sender, e) => - { - ushort lastKey = ushort.MaxValue; - Console.WriteLine("Materials:\n" + FullGameFields._dataDb.GetValues() - .OrderBy(kv => ushort.Parse(kv.Key)) - .Select(kv => - { - ushort currentKey = ushort.Parse(kv.Key); - string result = $"{((MaterialPropertiesData)kv.Value).Name}{(currentKey != lastKey + 1 ? $" = {kv.Key}" : "")},"; - lastKey = currentKey; - return result; - }) - .Aggregate((a, b) => a + "\n" + b)); - };*/ - - CommandBuilder.Builder("takeScreenshot", "Enables the screenshot taker") - .Action(() => - { - Game.CurrentGame().EnableScreenshotTaker(); - }).Build(); - - CommandBuilder.Builder("testPositionDefault", "Tests the Block.Position property's default value.") - .Action(() => - { - IEnumerator Loop() - { - for (int i = 0; i < 2; i++) - { - Console.WriteLine("A"); - var block = Block.PlaceNew(BlockIDs.Cube, 1); - Console.WriteLine("B"); - while (!block.Exists) - yield return Yield.It; - Console.WriteLine("C"); - block.Remove(); - Console.WriteLine("D"); - while (block.Exists) - yield return Yield.It; - Console.WriteLine("E - Pos: " + block.Position); - block.Position = 4; - Console.WriteLine("F - Pos: " + block.Position); - } - } - - Loop().RunOn(Scheduler.leanRunner); - }).Build(); - - CommandBuilder.Builder("importAssetBundle") - .Action(() => - { - Logging.CommandLog("Importing asset bundle..."); - var ab = AssetBundle.LoadFromFile( - @"filepath"); - Logging.CommandLog("Imported asset bundle: " + ab); - var assets = ab.LoadAllAssets(); - Logging.CommandLog("Loaded " + assets.Length + " assets"); - foreach (var asset in assets) - { - Logging.CommandLog(asset); - } - }).Build(); - - bool shouldTestGhostBlock = false; - CommandBuilder.Builder("testGhostBlock") - .Action(() => - { - if (shouldTestGhostBlock) - { - shouldTestGhostBlock = false; - Logging.CommandLog("Test disabled"); - } - - shouldTestGhostBlock = true; - Scheduler.Schedule(new Repeatable(() => - { - var ghostBlock = Player.LocalPlayer.GetGhostBlock(); - if (ghostBlock == null) return; - ghostBlock.Position = Player.LocalPlayer.Position + 2; - ghostBlock.Color = new BlockColor(BlockColors.Lime); - }, () => shouldTestGhostBlock)); - Logging.CommandLog("Test enabled"); - }).Build(); - Game.Enter += (sender, args) => - Console.WriteLine( - $"Current game selection data: {FullGameFields._gameSelectionData.gameMode} - {FullGameFields._gameSelectionData.saveType}"); + CommandBuilder.Builder() + .Name("Exit") + .Description("Close Techblox 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(); + + Game.AddPersistentDebugInfo("InstalledMods", InstalledMods); + + // Plugin startup logic + Logger.LogInfo($"Plugin {PluginInfo.PLUGIN_GUID} is loaded!"); + #if TEST TestRoot.RunTests(); #endif - } + } - private string modsString; + private void OnDestroy() + { + Main.Shutdown(); + } + + private string modsString; private string InstalledMods() { - if (modsString != null) return modsString; - StringBuilder sb = new StringBuilder("Installed mods:"); - foreach (var plugin in PluginManager.Plugins) - sb.Append("\n" + plugin.Name + " - " + plugin.Version); - return modsString = sb.ToString(); + if (modsString != null) return modsString; + StringBuilder sb = new StringBuilder("Installed mods:"); + foreach (var (_, plugin) in Chainloader.PluginInfos) + sb.Append("\n" + plugin.Metadata.Name + " - " + plugin.Metadata.Version); + return modsString = sb.ToString(); } + } - [HarmonyPatch] - public class MinimumSpecsPatch + [HarmonyPatch] + public class MinimumSpecsPatch + { + public static bool Prefix(ref bool __result) { - public static bool Prefix(ref bool __result) - { - __result = true; - return false; - } + __result = true; + return false; + } - public static MethodInfo TargetMethod() - { - return ((Func) MinimumSpecsCheck.CheckRequirementsMet).Method; - } + public static MethodInfo TargetMethod() + { + return ((Func) MinimumSpecsCheck.CheckRequirementsMet).Method; } } -#endif + #endif } diff --git a/TechbloxModdingAPI/Utility/Dependency.cs b/TechbloxModdingAPI/Utility/Dependency.cs index 3f33277..b160ac9 100644 --- a/TechbloxModdingAPI/Utility/Dependency.cs +++ b/TechbloxModdingAPI/Utility/Dependency.cs @@ -1,7 +1,5 @@ using System; - -using IllusionInjector; -using IllusionPlugin; +using BepInEx.Bootstrap; namespace TechbloxModdingAPI.Utility { @@ -15,11 +13,11 @@ namespace TechbloxModdingAPI.Utility /// /// The plugin. /// The plugin's name. - public static IPlugin GetPlugin(string name) + public static BepInEx.PluginInfo GetPlugin(string name) { - foreach(IPlugin plugin in PluginManager.Plugins) + foreach(var plugin in Chainloader.PluginInfos.Values) { - if (plugin.Name == name) + if (plugin.Metadata.Name == name) { return plugin; } @@ -35,45 +33,15 @@ namespace TechbloxModdingAPI.Utility /// The plugin's name. public static Version GetPluginVersion(string name) { - IPlugin plugin = GetPlugin(name); + var plugin = GetPlugin(name); if (plugin != null) { try { - return new Version(plugin.Version); - } catch (Exception e) when ( - e is ArgumentException - || e is ArgumentNullException - || e is ArgumentOutOfRangeException - || e is FormatException - || e is OverflowException) {} + return plugin.Metadata.Version; + } catch (Exception e) when (e is ArgumentException or FormatException or OverflowException) {} return plugin.GetType().Assembly.GetName().Version; } return null; } - - // (I'm leaving the auto-generated version) - // - // Hell the specified name and version. - // - // The hell. - // Name. - // Version. - /// - /// Detect if you're in dependency hell with respect to the plugin. - /// ie Check if the plugin doesn't exist or is out of date. - /// When version is null, this only checks if the plugin exists. - /// The version is retrieved using GetPluginVersion(string name). - /// - /// Are you in dependency hell? - /// The plugin's name' - /// The target version. - public static bool Hell(string name, Version version = null) - { - Version pluginVersion = GetPluginVersion(name); - if (version == null) { - return pluginVersion == null; - } - return (pluginVersion == null || pluginVersion < version); - } } }