using System; using System.Reflection; using Gamecraft.Blocks.BlockGroups; using Gamecraft.GUI.Blueprints; using GamecraftModdingAPI.Engines; using GamecraftModdingAPI.Utility; using HarmonyLib; using RobocraftX.Blocks; using RobocraftX.Common; using RobocraftX.CR.MachineEditing.BoxSelect; using RobocraftX.CR.MachineEditing.BoxSelect.ClipboardOperations; using Svelto.DataStructures; using Svelto.ECS; using Svelto.ECS.DataStructures; using Svelto.ECS.EntityStructs; using Svelto.ECS.Serialization; using Unity.Collections; using Unity.Mathematics; using UnityEngine; namespace GamecraftModdingAPI.Blocks { public class BlueprintEngine : IApiEngine { private readonly MethodInfo getBlocksFromGroup = AccessTools.Method("RobocraftX.CR.MachineEditing.PlaceBlockUtility:GetBlocksSharingBlockgroup"); private readonly NativeDynamicArray selectedBlocksInGroup = new NativeDynamicArray(); private readonly NativeHashSet removedConnections = new NativeHashSet(); private static readonly Type PlaceBlueprintUtilityType = AccessTools.TypeByName("RobocraftX.CR.MachineEditing.PlaceBlueprintUtility"); private static readonly FieldInfo LocalBlockMap = AccessTools.DeclaredField(PlaceBlueprintUtilityType, "_localBlockMap"); private static readonly MethodInfo BuildBlock = AccessTools.Method(PlaceBlueprintUtilityType, "BuildBlock"); private static readonly MethodInfo BuildWires = AccessTools.Method(PlaceBlueprintUtilityType, "BuildWires"); private static NativeEntityRemove nativeRemove; private static MachineGraphConnectionEntityFactory connectionFactory; private static IEntityFunctions entityFunctions; private static ClipboardSerializationDataResourceManager clipboardManager; private static IEntitySerialization entitySerialization; private static IEntityFactory entityFactory; private static FasterList globalBlockMap; public void Ready() { } public EntitiesDB entitiesDB { get; set; } public void Dispose() { } public Block[] GetBlocksFromGroup(EGID blockID) { var list = new FasterList(); object blockPos = null, blockRot = null; getBlocksFromGroup.Invoke(null, new[] {blockID, selectedBlocksInGroup, entitiesDB, blockPos, blockRot}); for (uint i = 0; i < selectedBlocksInGroup.Count(); i++) list.Add(new Block(selectedBlocksInGroup.Get(i))); selectedBlocksInGroup.FastClear(); return list.ToArray(); } public void RemoveBlockGroup(int id) { BlockGroupUtility.RemoveAllBlocksInBlockGroup(id, entitiesDB, removedConnections, nativeRemove, connectionFactory, default).Complete(); } public void SelectBlueprint(uint resourceID) { BlueprintUtil.SelectBlueprint(null, new BlueprintInventoryItemEntityStruct { blueprintResourceId = resourceID, }); } public uint CreateBlueprint() { uint index = clipboardManager.AllocateSerializationData(); return index; } public void ReplaceBlueprint(uint playerID, uint blueprintID, Block[] selected, float3 pos, quaternion rot) { var blockIDs = new EGID[selected.Length]; for (var i = 0; i < selected.Length; i++) { var block = selected[i]; blockIDs[i] = block.Id; } var serializationData = clipboardManager.GetSerializationData(blueprintID); SelectionSerializationUtility.ClearClipboard(playerID, entitiesDB, entityFunctions, serializationData.blueprintData); if (selected.Length == 0) return; //ref BlockGroupTransformEntityComponent groupTransform = ref EntityNativeDBExtensions.QueryEntity(entitiesDb, (uint) local1.currentBlockGroup, BlockGroupExclusiveGroups.BlockGroupEntityGroup); //ref ColliderAabb collider = ref EntityNativeDBExtensions.QueryEntity(entitiesDB, (uint) groupID, BlockGroupExclusiveGroups.BlockGroupEntityGroup); //float3 bottomOffset = PlaceBlockUtility.GetBottomOffset(collider); //var rootPosition = math.mul(groupTransform.blockGroupGridRotation, bottomOffset) + groupTransform.blockGroupGridPosition; //var rootRotation = groupTransform.blockGroupGridRotation; if (math.all(pos == default)) pos = selected[0].Position; if (math.all(rot.value == default)) rot = Quaternion.Euler(selected[0].Rotation); clipboardManager.SetGhostSerialized(blueprintID, false); SelectionSerializationUtility.CopySelectionToClipboard(playerID, entitiesDB, serializationData.blueprintData, entitySerialization, entityFactory, blockIDs, (uint) blockIDs.Length, pos, rot); } public Block[] PlaceBlueprintBlocks(uint blueprintID, uint playerID, float3 pos, float3 rot) { //RobocraftX.CR.MachineEditing.PlaceBlueprintUtility.PlaceBlocksFromSerialisedData var serializationData = clipboardManager.GetSerializationData(blueprintID); var blueprintData = serializationData.blueprintData; blueprintData.dataPos = 0U; uint selectionSize; PositionEntityStruct selectionPosition; RotationEntityStruct selectionRotation; uint version; BoxSelectSerializationUtilities.ReadClipboardHeader(blueprintData, out selectionSize, out selectionPosition, out selectionRotation, out version); ((FasterList) LocalBlockMap.GetValue(null)).Clear(); if (version <= 1U) { uint groupsCount; BoxSelectSerializationUtilities.ReadBlockGroupData(blueprintData, out groupsCount); for (int index = 0; (long) index < (long) groupsCount; ++index) { int nextFilterId = BlockGroupUtility.NextFilterId; entitySerialization.DeserializeNewEntity(new EGID((uint) nextFilterId, BlockGroupExclusiveGroups.BlockGroupEntityGroup), blueprintData, 1); } } int nextFilterId1 = BlockGroupUtility.NextFilterId; entityFactory.BuildEntity(new EGID((uint) nextFilterId1, BlockGroupExclusiveGroups.BlockGroupEntityGroup)).Init(new BlockGroupTransformEntityComponent { blockGroupGridPosition = selectionPosition.position, blockGroupGridRotation = selectionRotation.rotation }); var frot = Quaternion.Euler(rot); var grid = new GridRotationStruct {position = pos, rotation = frot}; var poss = new PositionEntityStruct {position = pos}; var rots = new RotationEntityStruct {rotation = frot}; for (int index = 0; (long) index < (long) selectionSize; ++index) BuildBlock.Invoke(null, new object[] { playerID, grid, poss, rots, selectionPosition, selectionRotation, blueprintData, entitiesDB, entitySerialization, nextFilterId1 }); /* uint playerId, in GridRotationStruct ghostParentGrid, in PositionEntityStruct ghostParentPosition, in RotationEntityStruct ghostParentRotation, in PositionEntityStruct selectionPosition, in RotationEntityStruct selectionRotation, ISerializationData serializationData, EntitiesDB entitiesDb, IEntitySerialization entitySerialization, int blockGroupId */ if (globalBlockMap == null) globalBlockMap = FullGameFields._deserialisedBlockMap; var placedBlocks = (FasterList) LocalBlockMap.GetValue(null); globalBlockMap.Clear(); globalBlockMap.AddRange(placedBlocks); BuildWires.Invoke(null, new object[] {playerID, blueprintData, entitySerialization, entitiesDB, entityFactory}); var blocks = new Block[placedBlocks.count]; for (int i = 0; i < blocks.Length; i++) blocks[i] = new Block(placedBlocks[i]); return blocks; } public void InitBlueprint(uint blueprintID) { clipboardManager.IncrementRefCount(blueprintID); } public void DisposeBlueprint(uint blueprintID) { clipboardManager.DecrementRefCount(blueprintID); } public string Name { get; } = "GamecraftModdingAPIBlueprintGameEngine"; public bool isRemovable { get; } [HarmonyPatch] private static class RemoveEnginePatch { public static void Prefix(IEntityFunctions entityFunctions, MachineGraphConnectionEntityFactory machineGraphConnectionEntityFactory) { nativeRemove = entityFunctions.ToNativeRemove("GCAPI" + nameof(BlueprintEngine)); connectionFactory = machineGraphConnectionEntityFactory; BlueprintEngine.entityFunctions = entityFunctions; } public static MethodBase TargetMethod() { return AccessTools.Constructor(AccessTools.TypeByName("RobocraftX.CR.MachineEditing.RemoveBlockEngine")); } } [HarmonyPatch] private static class SelectEnginePatch { public static void Prefix(ClipboardSerializationDataResourceManager clipboardSerializationDataResourceManager, IEntitySerialization entitySerialization, IEntityFactory entityFactory) { clipboardManager = clipboardSerializationDataResourceManager; BlueprintEngine.entitySerialization = entitySerialization; BlueprintEngine.entityFactory = entityFactory; } public static MethodBase TargetMethod() { return AccessTools.Constructor(AccessTools.TypeByName("RobocraftX.CR.MachineEditing.SelectBlockEngine")); } } } }