From 9b1e2548d1c2ba3f82d2356d25921efadb588118 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Sun, 14 Jun 2020 21:40:47 +0200 Subject: [PATCH] Attempts to create custom block types It can load certain assets (a Cube from a sample) but fails because of missing shaders My own Cube doesn't even get that far --- GamecraftModdingAPI/Blocks/CustomBlock.cs | 159 ++++++++++++++++++ .../Tests/GamecraftModdingAPIPluginTest.cs | 19 +++ 2 files changed, 178 insertions(+) create mode 100644 GamecraftModdingAPI/Blocks/CustomBlock.cs diff --git a/GamecraftModdingAPI/Blocks/CustomBlock.cs b/GamecraftModdingAPI/Blocks/CustomBlock.cs new file mode 100644 index 0000000..9801e40 --- /dev/null +++ b/GamecraftModdingAPI/Blocks/CustomBlock.cs @@ -0,0 +1,159 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Reflection.Emit; +using System.Text.Formatting; +using DataLoader; +using GamecraftModdingAPI.Utility; +using GPUInstancer; +using HarmonyLib; +using RobocraftX.Common; +using RobocraftX.Schedulers; +using Svelto.Tasks; +using Svelto.Tasks.ExtraLean; +using UnityEngine; +using UnityEngine.AddressableAssets; + +namespace GamecraftModdingAPI.Blocks +{ + public class CustomBlock + { + private static ushort nextID = 500; + public static void RegisterCustomBlock(string path) + { + var prefabData = new List(); + //category ID: + //0 - regular + //1 - joint + //2 - controller + uint prefabId = PrefabsID.FetchNewPrefabID(PrefabsID.GenerateDBID(0, nextID++)); + prefabData.Add(new PrefabData() + { + prefabName = path, + prefabId = prefabId + }); + var loadTask = Addressables.LoadAssetAsync(path); + AccessTools.Method("RobocraftX.Common.ECSGPUIResourceManager:RegisterPrefab") + .Invoke(ECSGPUIResourceManager.Instance, new object[] {prefabId, loadTask.Result, 1}); + } + + [HarmonyPatch] + public static class Patch + { + /*public static IEnumerable Transpiler(IEnumerable instructions) + { + var list = new List(instructions); + try + { + *int index = -1; + CodeInstruction loadTask = null; + for (var i = 0; i < list.Count - 1; i++) + { + if (list[i].opcode == OpCodes.Ldfld + && ((string) list[i].operand).Contains("renderingWorld") + && list[i + 1].opcode == OpCodes.Brfalse_S) + index = i - 1; //It loads 'this' first + if (list[i].opcode == OpCodes.Ldflda + && ((string) list[i].operand).Contains("loadTask")) + loadTask = new CodeInstruction(list[i]); + }* + + var array = new[] + { + //Set Yield.It to be returned (current) + new CodeInstruction(OpCodes.Ldarg_0), // this + new CodeInstruction(OpCodes.Ldsfld, + typeof(Yield).GetField("It", BindingFlags.Public | BindingFlags.Static)), + new CodeInstruction(OpCodes.Stfld, "object RobocraftX.Common.ECSResourceManagerUtility/'d__0'::'<>2__current'"), + + //Set which yield return we're at (state) + new CodeInstruction(OpCodes.Ldarg_0), // this + new CodeInstruction(OpCodes.Ldc_I4_1), + //new CodeInstruction(OpCodes.Call, ((Action)AddInfo).Method) + }; + list.InsertRange(index, array); + * + IL_00ad: ldarg.0 // this + IL_00ae: ldsfld class [Svelto.Tasks]Svelto.Tasks.Yield [Svelto.Tasks]Svelto.Tasks.Yield::It + IL_00b3: stfld object RobocraftX.Common.ECSResourceManagerUtility/'d__0'::'<>2__current' + + IL_0072: ldarg.0 // this + IL_0073: ldnull + IL_0074: stfld object RobocraftX.Common.ECSResourceManagerUtility/'d__0'::'<>2__current' + IL_0079: ldarg.0 // this + IL_007a: ldc.i4.2 + IL_007b: stfld object RobocraftX.Common.ECSResourceManagerUtility/'d__0'::'<>1__state' + IL_0080: ldc.i4.1 + IL_0081: ret + * + yield break; + } + catch (Exception e) + { + Logging.LogWarning("Failed to inject AddInfo method for the debug display!\n" + e); + } + }*/ + + public static void Prefix(ref Dictionary blocks) + { + /*foreach (var block in blocks.Values.Cast()) + { + Console.WriteLine("Block info: " + block); + }*/ + + /*var res = Addressables.LoadContentCatalogAsync("customCatalog.json"); + while (!res.IsDone) yield return Yield.It;*/ + + blocks.Add("modded_ConsoleBlock", new CubeListData + { + cubeType = CubeType.Block, + cubeCategory = CubeCategory.ConsoleBlock, + inventoryCategory = InventoryCategory.Logic, + ID = 500, + Path = "Assets/Cube.prefab", //Index out of range exception: Asset failed to load (wrong path) + SpriteName = "CTR_CommandBlock", + CubeNameKey = "strConsoleBlock", + SelectableFaces = new[] {0, 1, 2, 3, 4, 5}, + GridScale = new[] {1, 1, 1}, + Mass = 1, + JointBreakAngle = 1 + }); + } + + public static MethodBase TargetMethod() + { //General block registration + return AccessTools.Method("RobocraftX.Blocks.BlocksCompositionRoot:RegisterPartPrefabs"); + } + } + + [HarmonyPatch] + public static class GOPatch + { + public static void Prefix(uint prefabID, GameObject gameObject) + { + Console.WriteLine("ID: " + prefabID + " - Name: " + gameObject.name); + if (gameObject.name == "Cube") + ECSGPUIResourceManager.Instance.RegisterRuntimePrefabs( + new[] {new PrefabData {prefabId = 500, prefabName = "Assets/Cube.prefab"}}, + new List {gameObject}, 1).Complete(); + } + + public static MethodBase TargetMethod() + { + return AccessTools.Method("RobocraftX.Common.ECSGPUIResourceManager:RegisterPrefab", + new[] {typeof(uint), typeof(GameObject), typeof(uint)}); + } + } + + public static IEnumerator Prep() + { + Console.WriteLine("Loading custom catalog..."); + var res = Addressables.LoadContentCatalogAsync("customCatalog.json"); + while (!res.IsDone) yield return Yield.It; + Console.WriteLine("Loaded custom catalog: " + res.Result.LocatorId); + Addressables.AddResourceLocator(res.Result); + } + } +} \ No newline at end of file diff --git a/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs b/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs index dc07e1e..c4077d0 100644 --- a/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs +++ b/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs @@ -13,6 +13,9 @@ using RobocraftX.Common; using RobocraftX.SimulationModeState; using RobocraftX.FrontEnd; using Unity.Mathematics; +using RobocraftX.Schedulers; +using Svelto.Tasks.ExtraLean; +using uREPL; using GamecraftModdingAPI.Commands; using GamecraftModdingAPI.Events; @@ -283,6 +286,22 @@ namespace GamecraftModdingAPI.Tests { Logging.Log("Compatible GamecraftScripting detected"); } + + CommandBuilder.Builder("enableCompletions") + .Action(() => + { + var p = Window.selected.main.parameters; + p.useCommandCompletion = true; + p.useMonoCompletion = true; + p.useGlobalClassCompletion = true; + Log.Output("Submitted: " + Window.selected.submittedCode); + }) + .Build(); + /*JObject o1 = JObject.Parse(File.ReadAllText(@"Gamecraft_Data\StreamingAssets\aa\Windows\catalog.json")); + JObject o2 = JObject.Parse(File.ReadAllText(@"customCatalog.json")); + o1.Merge(o2, new JsonMergeSettings {MergeArrayHandling = MergeArrayHandling.Union}); + File.WriteAllText(@"Gamecraft_Data\StreamingAssets\aa\Windows\catalog.json", o1.ToString());*/ + CustomBlock.Prep().RunOn(ExtraLean.UIScheduler); } private string modsString;