2020-11-10 18:28:36 +00:00
|
|
|
|
using System;
|
2020-11-12 01:39:58 +00:00
|
|
|
|
using System.Collections.Generic;
|
2020-11-10 18:28:36 +00:00
|
|
|
|
using System.Reflection;
|
2020-11-10 15:37:20 +00:00
|
|
|
|
using Gamecraft.Blocks.BlockGroups;
|
|
|
|
|
using Gamecraft.GUI.Blueprints;
|
|
|
|
|
using GamecraftModdingAPI.Engines;
|
2020-11-10 18:28:36 +00:00
|
|
|
|
using GamecraftModdingAPI.Utility;
|
2020-11-10 15:37:20 +00:00
|
|
|
|
using HarmonyLib;
|
|
|
|
|
using RobocraftX.Blocks;
|
2020-11-10 18:28:36 +00:00
|
|
|
|
using RobocraftX.Common;
|
|
|
|
|
using RobocraftX.CR.MachineEditing.BoxSelect;
|
|
|
|
|
using RobocraftX.CR.MachineEditing.BoxSelect.ClipboardOperations;
|
2020-11-10 15:37:20 +00:00
|
|
|
|
using Svelto.DataStructures;
|
|
|
|
|
using Svelto.ECS;
|
|
|
|
|
using Svelto.ECS.DataStructures;
|
2020-11-10 18:28:36 +00:00
|
|
|
|
using Svelto.ECS.EntityStructs;
|
|
|
|
|
using Svelto.ECS.Serialization;
|
2020-11-10 15:37:20 +00:00
|
|
|
|
using Unity.Collections;
|
2020-11-10 18:28:36 +00:00
|
|
|
|
using Unity.Mathematics;
|
|
|
|
|
using UnityEngine;
|
2020-11-10 22:08:27 +00:00
|
|
|
|
using Allocator = Svelto.Common.Allocator;
|
2020-11-10 15:37:20 +00:00
|
|
|
|
|
|
|
|
|
namespace GamecraftModdingAPI.Blocks
|
|
|
|
|
{
|
2020-11-12 01:39:58 +00:00
|
|
|
|
public class BlueprintEngine : IFactoryEngine
|
2020-11-10 15:37:20 +00:00
|
|
|
|
{
|
|
|
|
|
private readonly MethodInfo getBlocksFromGroup =
|
|
|
|
|
AccessTools.Method("RobocraftX.CR.MachineEditing.PlaceBlockUtility:GetBlocksSharingBlockgroup");
|
2020-11-10 22:08:27 +00:00
|
|
|
|
|
|
|
|
|
private NativeDynamicArray selectedBlocksInGroup;
|
|
|
|
|
private NativeHashSet<ulong> removedConnections = new NativeHashSet<ulong>();
|
2020-11-10 15:37:20 +00:00
|
|
|
|
|
2020-11-10 18:28:36 +00:00
|
|
|
|
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");
|
2020-11-14 01:52:16 +00:00
|
|
|
|
private static readonly Type SerializeGhostBlueprintType =
|
|
|
|
|
AccessTools.TypeByName("RobocraftX.CR.MachineEditing.BoxSelect.SerializeGhostChildrenOnAddEngine");
|
|
|
|
|
private static readonly MethodInfo SerializeGhostBlueprint =
|
|
|
|
|
AccessTools.Method(SerializeGhostBlueprintType, "SerializeClipboardGhostEntities");
|
2020-11-10 18:28:36 +00:00
|
|
|
|
|
2020-11-10 15:37:20 +00:00
|
|
|
|
private static NativeEntityRemove nativeRemove;
|
|
|
|
|
private static MachineGraphConnectionEntityFactory connectionFactory;
|
2020-11-10 18:28:36 +00:00
|
|
|
|
private static IEntityFunctions entityFunctions;
|
|
|
|
|
private static ClipboardSerializationDataResourceManager clipboardManager;
|
|
|
|
|
private static IEntitySerialization entitySerialization;
|
|
|
|
|
private static IEntityFactory entityFactory;
|
|
|
|
|
private static FasterList<EGID> globalBlockMap;
|
2020-11-14 01:52:16 +00:00
|
|
|
|
private static object SerializeGhostBlueprintInstance;
|
|
|
|
|
private static GhostChildEntityFactory BuildGhostBlueprintFactory;
|
2020-11-10 15:37:20 +00:00
|
|
|
|
|
|
|
|
|
public void Ready()
|
|
|
|
|
{
|
2020-11-10 22:08:27 +00:00
|
|
|
|
selectedBlocksInGroup = NativeDynamicArray.Alloc<EGID>(Allocator.Persistent);
|
2020-11-10 15:37:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public EntitiesDB entitiesDB { get; set; }
|
|
|
|
|
public void Dispose()
|
|
|
|
|
{
|
2020-11-10 22:08:27 +00:00
|
|
|
|
selectedBlocksInGroup.Dispose();
|
2020-11-10 15:37:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-11-10 22:08:27 +00:00
|
|
|
|
public Block[] GetBlocksFromGroup(EGID blockID, out float3 pos, out quaternion rot)
|
2020-11-10 15:37:20 +00:00
|
|
|
|
{
|
2020-11-10 22:08:27 +00:00
|
|
|
|
var blockPos = default(float3);
|
|
|
|
|
var blockRot = default(quaternion);
|
|
|
|
|
var parameters = new object[] {blockID, selectedBlocksInGroup, entitiesDB, blockPos, blockRot};
|
|
|
|
|
getBlocksFromGroup.Invoke(null, parameters);
|
|
|
|
|
pos = (float3) parameters[3];
|
|
|
|
|
rot = (quaternion) parameters[4];
|
|
|
|
|
int count = selectedBlocksInGroup.Count<EGID>();
|
|
|
|
|
var ret = new Block[count];
|
|
|
|
|
for (uint i = 0; i < count; i++)
|
|
|
|
|
ret[i] = new Block(selectedBlocksInGroup.Get<EGID>(i));
|
2020-11-10 15:37:20 +00:00
|
|
|
|
selectedBlocksInGroup.FastClear();
|
2020-11-10 22:08:27 +00:00
|
|
|
|
return ret;
|
2020-11-10 15:37:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void RemoveBlockGroup(int id)
|
|
|
|
|
{
|
|
|
|
|
BlockGroupUtility.RemoveAllBlocksInBlockGroup(id, entitiesDB, removedConnections, nativeRemove,
|
|
|
|
|
connectionFactory, default).Complete();
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-12 01:39:58 +00:00
|
|
|
|
public int CreateBlockGroup(float3 position, quaternion rotation)
|
2020-11-10 15:37:20 +00:00
|
|
|
|
{
|
2020-11-12 01:39:58 +00:00
|
|
|
|
int nextFilterId = BlockGroupUtility.NextFilterId;
|
|
|
|
|
Factory.BuildEntity<BlockGroupEntityDescriptor>((uint) nextFilterId,
|
|
|
|
|
BlockGroupExclusiveGroups.BlockGroupEntityGroup).Init(new BlockGroupTransformEntityComponent
|
2020-11-10 15:37:20 +00:00
|
|
|
|
{
|
2020-11-12 01:39:58 +00:00
|
|
|
|
blockGroupGridRotation = rotation,
|
|
|
|
|
blockGroupGridPosition = position
|
2020-11-10 15:37:20 +00:00
|
|
|
|
});
|
2020-11-12 01:39:58 +00:00
|
|
|
|
return nextFilterId;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void SelectBlueprint(uint resourceID)
|
|
|
|
|
{
|
|
|
|
|
if (resourceID == uint.MaxValue)
|
|
|
|
|
BlueprintUtil.UnselectBlueprint(entitiesDB);
|
|
|
|
|
else
|
2020-11-13 20:35:53 +00:00
|
|
|
|
BlueprintUtil.SelectBlueprint(entitiesDB, resourceID, false, -1);
|
2020-11-10 15:37:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
2020-11-10 18:28:36 +00:00
|
|
|
|
public uint CreateBlueprint()
|
|
|
|
|
{
|
|
|
|
|
uint index = clipboardManager.AllocateSerializationData();
|
|
|
|
|
return index;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-12 01:39:58 +00:00
|
|
|
|
public void ReplaceBlueprint(uint playerID, uint blueprintID, ICollection<Block> selected, float3 pos, quaternion rot)
|
2020-11-10 18:28:36 +00:00
|
|
|
|
{
|
2020-11-12 01:39:58 +00:00
|
|
|
|
var blockIDs = new EGID[selected.Count];
|
|
|
|
|
using (var enumerator = selected.GetEnumerator())
|
2020-11-10 18:28:36 +00:00
|
|
|
|
{
|
2020-11-12 01:39:58 +00:00
|
|
|
|
for (var i = 0; enumerator.MoveNext(); i++)
|
|
|
|
|
{
|
|
|
|
|
var block = enumerator.Current;
|
|
|
|
|
blockIDs[i] = block.Id;
|
|
|
|
|
}
|
2020-11-10 18:28:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var serializationData = clipboardManager.GetSerializationData(blueprintID);
|
2020-11-13 20:35:53 +00:00
|
|
|
|
SelectionSerializationUtility.ClearClipboard(playerID, entitiesDB, entityFunctions, serializationData.blueprintData, -1);
|
2020-11-12 01:39:58 +00:00
|
|
|
|
if (selected.Count == 0)
|
2020-11-10 18:28:36 +00:00
|
|
|
|
return;
|
|
|
|
|
//ref BlockGroupTransformEntityComponent groupTransform = ref EntityNativeDBExtensions.QueryEntity<BlockGroupTransformEntityComponent>(entitiesDb, (uint) local1.currentBlockGroup, BlockGroupExclusiveGroups.BlockGroupEntityGroup);
|
|
|
|
|
//ref ColliderAabb collider = ref EntityNativeDBExtensions.QueryEntity<ColliderAabb>(entitiesDB, (uint) groupID, BlockGroupExclusiveGroups.BlockGroupEntityGroup);
|
|
|
|
|
//float3 bottomOffset = PlaceBlockUtility.GetBottomOffset(collider);
|
|
|
|
|
//var rootPosition = math.mul(groupTransform.blockGroupGridRotation, bottomOffset) + groupTransform.blockGroupGridPosition;
|
|
|
|
|
//var rootRotation = groupTransform.blockGroupGridRotation;
|
|
|
|
|
|
|
|
|
|
clipboardManager.SetGhostSerialized(blueprintID, false);
|
|
|
|
|
SelectionSerializationUtility.CopySelectionToClipboard(playerID, entitiesDB,
|
|
|
|
|
serializationData.blueprintData, entitySerialization, entityFactory, blockIDs,
|
2020-11-13 20:35:53 +00:00
|
|
|
|
(uint) blockIDs.Length, pos, rot, -1);
|
2020-11-14 01:52:16 +00:00
|
|
|
|
BuildGhostBlueprint(selected, pos, rot, playerID);
|
|
|
|
|
SerializeGhostBlueprint.Invoke(SerializeGhostBlueprintInstance, new object[] {playerID, blueprintID});
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void BuildGhostBlueprint(ICollection<Block> blocks, float3 pos, quaternion rot, uint playerID)
|
|
|
|
|
{
|
|
|
|
|
GhostChildUtility.ClearGhostChildren(playerID, entitiesDB, entityFunctions);
|
|
|
|
|
foreach (var block in blocks)
|
|
|
|
|
{
|
|
|
|
|
GhostChildUtility.BuildGhostChild(in playerID, block.Id, in pos, in rot, entitiesDB,
|
|
|
|
|
BuildGhostBlueprintFactory, false);
|
|
|
|
|
}
|
2020-11-10 18:28:36 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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<EGID>) 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<BlockGroupEntityDescriptor>(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,
|
2020-11-13 20:35:53 +00:00
|
|
|
|
entitySerialization, nextFilterId1
|
2020-11-10 18:28:36 +00:00
|
|
|
|
});
|
|
|
|
|
/*
|
|
|
|
|
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<EGID>) 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;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-14 17:29:48 +00:00
|
|
|
|
public void GetBlueprintInfo(uint blueprintID, out float3 pos, out quaternion rot, out uint selectionSize)
|
|
|
|
|
{
|
|
|
|
|
var serializationData = clipboardManager.GetSerializationData(blueprintID);
|
|
|
|
|
var blueprintData = serializationData.blueprintData;
|
|
|
|
|
blueprintData.dataPos = 0U;
|
|
|
|
|
BoxSelectSerializationUtilities.ReadClipboardHeader(blueprintData, out selectionSize, out var posst,
|
|
|
|
|
out var rotst, out _);
|
|
|
|
|
blueprintData.dataPos = 0U; //Just to be sure, it gets reset when it's read anyway
|
|
|
|
|
pos = posst.position;
|
|
|
|
|
rot = rotst.rotation;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-10 18:28:36 +00:00
|
|
|
|
public void InitBlueprint(uint blueprintID)
|
|
|
|
|
{
|
|
|
|
|
clipboardManager.IncrementRefCount(blueprintID);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void DisposeBlueprint(uint blueprintID)
|
|
|
|
|
{
|
|
|
|
|
clipboardManager.DecrementRefCount(blueprintID);
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-10 15:37:20 +00:00
|
|
|
|
public string Name { get; } = "GamecraftModdingAPIBlueprintGameEngine";
|
2020-11-12 01:39:58 +00:00
|
|
|
|
public bool isRemovable { get; } = false;
|
2020-11-10 15:37:20 +00:00
|
|
|
|
|
|
|
|
|
[HarmonyPatch]
|
|
|
|
|
private static class RemoveEnginePatch
|
|
|
|
|
{
|
|
|
|
|
public static void Prefix(IEntityFunctions entityFunctions,
|
|
|
|
|
MachineGraphConnectionEntityFactory machineGraphConnectionEntityFactory)
|
|
|
|
|
{
|
|
|
|
|
nativeRemove = entityFunctions.ToNativeRemove<BlockEntityDescriptor>("GCAPI" + nameof(BlueprintEngine));
|
|
|
|
|
connectionFactory = machineGraphConnectionEntityFactory;
|
2020-11-10 18:28:36 +00:00
|
|
|
|
BlueprintEngine.entityFunctions = entityFunctions;
|
2020-11-10 15:37:20 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static MethodBase TargetMethod()
|
|
|
|
|
{
|
2020-11-10 22:08:27 +00:00
|
|
|
|
return AccessTools.GetDeclaredConstructors(AccessTools.TypeByName("RobocraftX.CR.MachineEditing.RemoveBlockEngine"))[0];
|
2020-11-10 15:37:20 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2020-11-10 18:28:36 +00:00
|
|
|
|
|
|
|
|
|
[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()
|
|
|
|
|
{
|
2020-11-10 22:08:27 +00:00
|
|
|
|
return AccessTools.GetDeclaredConstructors(AccessTools.TypeByName("RobocraftX.CR.MachineEditing.SelectBlockEngine"))[0];
|
2020-11-10 18:28:36 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2020-11-12 01:39:58 +00:00
|
|
|
|
|
2020-11-14 01:52:16 +00:00
|
|
|
|
[HarmonyPatch]
|
|
|
|
|
private static class SerializeGhostBlueprintPatch
|
|
|
|
|
{
|
|
|
|
|
public static void Postfix(object __instance)
|
|
|
|
|
{
|
|
|
|
|
SerializeGhostBlueprintInstance = __instance;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static MethodBase TargetMethod()
|
|
|
|
|
{
|
|
|
|
|
return AccessTools.GetDeclaredConstructors(SerializeGhostBlueprintType)[0];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[HarmonyPatch]
|
|
|
|
|
private static class BuildGhostBlueprintPatch
|
|
|
|
|
{
|
|
|
|
|
public static void Postfix(GhostChildEntityFactory ghostChildEntityFactory)
|
|
|
|
|
{
|
|
|
|
|
BuildGhostBlueprintFactory = ghostChildEntityFactory;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static MethodBase TargetMethod()
|
2020-11-14 17:29:48 +00:00
|
|
|
|
{RobocraftX.CR.MachineEditing.BuildGhostChildForMultiblockPickEngine
|
2020-11-14 01:52:16 +00:00
|
|
|
|
return AccessTools.GetDeclaredConstructors(AccessTools.TypeByName("RobocraftX.CR.MachineEditing.BuildGhostChildForMultiblockPickEngine"))[0];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-12 01:39:58 +00:00
|
|
|
|
public IEntityFactory Factory { get; set; }
|
2020-11-10 15:37:20 +00:00
|
|
|
|
}
|
|
|
|
|
}
|