using System; using System.Collections.Generic; using System.Reflection; using Gamecraft.Wires; using GamecraftModdingAPI.Engines; using HarmonyLib; using RobocraftX.Blocks; using RobocraftX.Character; using RobocraftX.Common; using RobocraftX.Common.Players; using Svelto.DataStructures; using Svelto.ECS; namespace GamecraftModdingAPI.Blocks { public class BlockCloneEngine : IApiEngine { private static Type copyEngineType = AccessTools.TypeByName("Gamecraft.GUI.Tweaks.Engines.CopyTweaksOnPickEngine"); private static Type copyWireEngineType = AccessTools.TypeByName("Gamecraft.Wires.WireConnectionCopyOnPickEngine"); private static Type createWireEngineType = AccessTools.TypeByName("RobocraftX.GUI.Wires.WireConnectionCreateOnPlaceEngine"); private MethodBase copyFromBlock = AccessTools.Method(copyEngineType, "CopyTweaksFromBlock"); private MethodBase copyToBlock = AccessTools.Method(copyEngineType, "ApplyTweaksToPlacedBlock"); private MethodBase copyWireFromBlock = AccessTools.Method(copyWireEngineType, "CopyWireInputsAndOutputs"); private MethodBase copyWireToBlock = AccessTools.Method(createWireEngineType, "PlaceWiresOnPlaceNewCube"); public void Ready() { } public EntitiesDB entitiesDB { get; set; } public void Dispose() { } public void CopyBlockStats(EGID sourceID, EGID targetID) { var allCharacters = (LocalFasterReadOnlyList) CharacterExclusiveGroups.AllCharacters; foreach (var ((pickedBlockColl, count), _) in entitiesDB.QueryEntities(allCharacters)) { for (int i = 0; i < count; ++i) { ref PickedBlockExtraDataStruct pickedBlock = ref pickedBlockColl[i]; var oldStruct = pickedBlock; pickedBlock.pickedBlockEntityID = sourceID; pickedBlock.placedBlockEntityID = targetID; pickedBlock.placedBlockTweaksCopied = false; pickedBlock.placedBlockTweaksMustCopy = true; if (entitiesDB.Exists(pickedBlock.pickedBlockEntityID) && entitiesDB.Exists(pickedBlock.placedBlockEntityID)) { copyFromBlock.Invoke(Patch.copyEngine, new object[] {pickedBlock.ID, pickedBlock}); uint playerID = Player.LocalPlayer.Id; var parameters = new object[] {playerID, pickedBlock}; copyWireFromBlock.Invoke(Patch.copyWireEngine, parameters); pickedBlock = (PickedBlockExtraDataStruct) parameters[1]; //ref arg copyToBlock.Invoke(Patch.copyEngine, new object[] {pickedBlock.ID, pickedBlock}); ExclusiveGroupStruct group = WiresExclusiveGroups.WIRES_COPY_GROUP + playerID; copyWireToBlock.Invoke(Patch.createWireEngine, new object[] {group, pickedBlock.ID}); pickedBlock.placedBlockTweaksMustCopy = false; pickedBlock.placedBlockTweaksCopied = false; } pickedBlock = oldStruct; //Make sure to not interfere with the game - Although that might not be the case with the wire copying } } } [HarmonyPatch] private static class Patch { public static object copyEngine; public static object copyWireEngine; public static object createWireEngine; public static void Postfix(object __instance) { if (__instance.GetType() == copyEngineType) copyEngine = __instance; else if (__instance.GetType() == copyWireEngineType) copyWireEngine = __instance; else if (__instance.GetType() == createWireEngineType) createWireEngine = __instance; } public static IEnumerable TargetMethods() { return new[] { AccessTools.GetDeclaredConstructors(copyEngineType)[0], AccessTools.GetDeclaredConstructors(copyWireEngineType)[0], AccessTools.GetDeclaredConstructors(createWireEngineType)[0] }; } } public string Name { get; } = "GamecraftModdingAPIBlockCloneGameEngine"; public bool isRemovable { get; } = false; } }