TechbloxModdingAPI/GamecraftModdingAPI/Blocks/BlueprintEngine.cs
NorbiPeti f30dcd251f Displaying blueprint before placing, enums, ToString()s
Added support for getting the player's current building mode (build, color, config, blueprint)
Added support for getting the current game's mode (building, playing, prefab etc.)
2020-11-14 02:52:16 +01:00

290 lines
No EOL
13 KiB
C#

using System;
using System.Collections.Generic;
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;
using Allocator = Svelto.Common.Allocator;
namespace GamecraftModdingAPI.Blocks
{
public class BlueprintEngine : IFactoryEngine
{
private readonly MethodInfo getBlocksFromGroup =
AccessTools.Method("RobocraftX.CR.MachineEditing.PlaceBlockUtility:GetBlocksSharingBlockgroup");
private NativeDynamicArray selectedBlocksInGroup;
private NativeHashSet<ulong> removedConnections = new NativeHashSet<ulong>();
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 readonly Type SerializeGhostBlueprintType =
AccessTools.TypeByName("RobocraftX.CR.MachineEditing.BoxSelect.SerializeGhostChildrenOnAddEngine");
private static readonly MethodInfo SerializeGhostBlueprint =
AccessTools.Method(SerializeGhostBlueprintType, "SerializeClipboardGhostEntities");
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<EGID> globalBlockMap;
private static object SerializeGhostBlueprintInstance;
private static GhostChildEntityFactory BuildGhostBlueprintFactory;
public void Ready()
{
selectedBlocksInGroup = NativeDynamicArray.Alloc<EGID>(Allocator.Persistent);
}
public EntitiesDB entitiesDB { get; set; }
public void Dispose()
{
selectedBlocksInGroup.Dispose();
}
public Block[] GetBlocksFromGroup(EGID blockID, out float3 pos, out quaternion rot)
{
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));
selectedBlocksInGroup.FastClear();
return ret;
}
public void RemoveBlockGroup(int id)
{
BlockGroupUtility.RemoveAllBlocksInBlockGroup(id, entitiesDB, removedConnections, nativeRemove,
connectionFactory, default).Complete();
}
public int CreateBlockGroup(float3 position, quaternion rotation)
{
int nextFilterId = BlockGroupUtility.NextFilterId;
Factory.BuildEntity<BlockGroupEntityDescriptor>((uint) nextFilterId,
BlockGroupExclusiveGroups.BlockGroupEntityGroup).Init(new BlockGroupTransformEntityComponent
{
blockGroupGridRotation = rotation,
blockGroupGridPosition = position
});
return nextFilterId;
}
public void SelectBlueprint(uint resourceID)
{
if (resourceID == uint.MaxValue)
BlueprintUtil.UnselectBlueprint(entitiesDB);
else
BlueprintUtil.SelectBlueprint(entitiesDB, resourceID, false, -1);
}
public uint CreateBlueprint()
{
uint index = clipboardManager.AllocateSerializationData();
return index;
}
public void ReplaceBlueprint(uint playerID, uint blueprintID, ICollection<Block> selected, float3 pos, quaternion rot)
{
var blockIDs = new EGID[selected.Count];
using (var enumerator = selected.GetEnumerator())
{
for (var i = 0; enumerator.MoveNext(); i++)
{
var block = enumerator.Current;
blockIDs[i] = block.Id;
}
}
var serializationData = clipboardManager.GetSerializationData(blueprintID);
SelectionSerializationUtility.ClearClipboard(playerID, entitiesDB, entityFunctions, serializationData.blueprintData, -1);
if (selected.Count == 0)
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,
(uint) blockIDs.Length, pos, rot, -1);
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);
}
}
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,
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<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;
}
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; } = false;
[HarmonyPatch]
private static class RemoveEnginePatch
{
public static void Prefix(IEntityFunctions entityFunctions,
MachineGraphConnectionEntityFactory machineGraphConnectionEntityFactory)
{
nativeRemove = entityFunctions.ToNativeRemove<BlockEntityDescriptor>("GCAPI" + nameof(BlueprintEngine));
connectionFactory = machineGraphConnectionEntityFactory;
BlueprintEngine.entityFunctions = entityFunctions;
}
public static MethodBase TargetMethod()
{
return AccessTools.GetDeclaredConstructors(AccessTools.TypeByName("RobocraftX.CR.MachineEditing.RemoveBlockEngine"))[0];
}
}
[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.GetDeclaredConstructors(AccessTools.TypeByName("RobocraftX.CR.MachineEditing.SelectBlockEngine"))[0];
}
}
[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()
{
return AccessTools.GetDeclaredConstructors(AccessTools.TypeByName("RobocraftX.CR.MachineEditing.BuildGhostChildForMultiblockPickEngine"))[0];
}
}
public IEntityFactory Factory { get; set; }
}
}