Add support for setting and placing blueprints
This commit is contained in:
parent
1a986056a1
commit
2179ba6386
3 changed files with 199 additions and 3 deletions
|
@ -1,13 +1,22 @@
|
||||||
using System.Reflection;
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
using Gamecraft.Blocks.BlockGroups;
|
using Gamecraft.Blocks.BlockGroups;
|
||||||
using Gamecraft.GUI.Blueprints;
|
using Gamecraft.GUI.Blueprints;
|
||||||
using GamecraftModdingAPI.Engines;
|
using GamecraftModdingAPI.Engines;
|
||||||
|
using GamecraftModdingAPI.Utility;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using RobocraftX.Blocks;
|
using RobocraftX.Blocks;
|
||||||
|
using RobocraftX.Common;
|
||||||
|
using RobocraftX.CR.MachineEditing.BoxSelect;
|
||||||
|
using RobocraftX.CR.MachineEditing.BoxSelect.ClipboardOperations;
|
||||||
using Svelto.DataStructures;
|
using Svelto.DataStructures;
|
||||||
using Svelto.ECS;
|
using Svelto.ECS;
|
||||||
using Svelto.ECS.DataStructures;
|
using Svelto.ECS.DataStructures;
|
||||||
|
using Svelto.ECS.EntityStructs;
|
||||||
|
using Svelto.ECS.Serialization;
|
||||||
using Unity.Collections;
|
using Unity.Collections;
|
||||||
|
using Unity.Mathematics;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
namespace GamecraftModdingAPI.Blocks
|
namespace GamecraftModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
|
@ -18,8 +27,20 @@ namespace GamecraftModdingAPI.Blocks
|
||||||
private readonly NativeDynamicArray selectedBlocksInGroup = new NativeDynamicArray();
|
private readonly NativeDynamicArray selectedBlocksInGroup = new NativeDynamicArray();
|
||||||
private readonly NativeHashSet<ulong> removedConnections = new NativeHashSet<ulong>();
|
private readonly 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 NativeEntityRemove nativeRemove;
|
private static NativeEntityRemove nativeRemove;
|
||||||
private static MachineGraphConnectionEntityFactory connectionFactory;
|
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;
|
||||||
|
|
||||||
public void Ready()
|
public void Ready()
|
||||||
{
|
{
|
||||||
|
@ -55,6 +76,109 @@ namespace GamecraftModdingAPI.Blocks
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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<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;
|
||||||
|
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<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,
|
||||||
|
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<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 string Name { get; } = "GamecraftModdingAPIBlueprintGameEngine";
|
||||||
public bool isRemovable { get; }
|
public bool isRemovable { get; }
|
||||||
|
|
||||||
|
@ -66,6 +190,7 @@ namespace GamecraftModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
nativeRemove = entityFunctions.ToNativeRemove<BlockEntityDescriptor>("GCAPI" + nameof(BlueprintEngine));
|
nativeRemove = entityFunctions.ToNativeRemove<BlockEntityDescriptor>("GCAPI" + nameof(BlueprintEngine));
|
||||||
connectionFactory = machineGraphConnectionEntityFactory;
|
connectionFactory = machineGraphConnectionEntityFactory;
|
||||||
|
BlueprintEngine.entityFunctions = entityFunctions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MethodBase TargetMethod()
|
public static MethodBase TargetMethod()
|
||||||
|
@ -73,5 +198,23 @@ namespace GamecraftModdingAPI.Blocks
|
||||||
return AccessTools.Constructor(AccessTools.TypeByName("RobocraftX.CR.MachineEditing.RemoveBlockEngine"));
|
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"));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,14 +1,21 @@
|
||||||
using Gamecraft.GUI.Blueprints;
|
using System;
|
||||||
|
using Unity.Mathematics;
|
||||||
|
|
||||||
namespace GamecraftModdingAPI
|
namespace GamecraftModdingAPI
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a blueprint in the inventory. When placed it becomes a block group.
|
/// Represents a blueprint in the inventory. When placed it becomes a block group.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class Blueprint
|
public class Blueprint : IDisposable
|
||||||
{
|
{
|
||||||
public uint Id { get; }
|
public uint Id { get; }
|
||||||
|
|
||||||
|
internal Blueprint(uint id)
|
||||||
|
{
|
||||||
|
Id = id;
|
||||||
|
BlockGroup._engine.InitBlueprint(id);
|
||||||
|
}
|
||||||
|
|
||||||
/*public static void SelectBlueprint(Blueprint blueprint)
|
/*public static void SelectBlueprint(Blueprint blueprint)
|
||||||
{
|
{
|
||||||
BlueprintUtil.SelectBlueprint(null, new BlueprintInventoryItemEntityStruct
|
BlueprintUtil.SelectBlueprint(null, new BlueprintInventoryItemEntityStruct
|
||||||
|
@ -16,5 +23,42 @@ namespace GamecraftModdingAPI
|
||||||
blueprintResourceId = blueprint.Id
|
blueprintResourceId = blueprint.Id
|
||||||
});
|
});
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new, empty blueprint. It will be deleted on disposal unless the game holds a reference to it.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A blueprint that doesn't have any blocks</returns>
|
||||||
|
public static Blueprint Create()
|
||||||
|
{
|
||||||
|
return new Blueprint(BlockGroup._engine.CreateBlueprint());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the blocks that the blueprint contains.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="blocks">The array of blocks to use</param>
|
||||||
|
/// <param name="position">The anchor position of the blueprint</param>
|
||||||
|
/// <param name="rotation">The rotation of the blueprint</param>
|
||||||
|
public void SetStoredBlocks(Block[] blocks, float3 position = default, float3 rotation = default)
|
||||||
|
{
|
||||||
|
BlockGroup._engine.ReplaceBlueprint(Player.LocalPlayer.Id, Id, blocks, position,
|
||||||
|
quaternion.Euler(rotation));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Places the blocks the blueprint contains at the specified position and rotation.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="position">The position of the blueprint</param>
|
||||||
|
/// <param name="rotation">The rotation of the blueprint</param>
|
||||||
|
/// <returns>An array of the placed blocks</returns>
|
||||||
|
public Block[] PlaceBlocks(float3 position, float3 rotation)
|
||||||
|
{
|
||||||
|
return BlockGroup._engine.PlaceBlueprintBlocks(Id, Player.LocalPlayer.Id, position, rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
BlockGroup._engine.DisposeBlueprint(Id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -12,6 +12,7 @@ using RobocraftX.GUI;
|
||||||
using RobocraftX.Multiplayer;
|
using RobocraftX.Multiplayer;
|
||||||
using RobocraftX.Rendering;
|
using RobocraftX.Rendering;
|
||||||
using Svelto.Context;
|
using Svelto.Context;
|
||||||
|
using Svelto.DataStructures;
|
||||||
using Svelto.ECS;
|
using Svelto.ECS;
|
||||||
using Svelto.ECS.Schedulers.Unity;
|
using Svelto.ECS.Schedulers.Unity;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
@ -159,6 +160,14 @@ namespace GamecraftModdingAPI.Utility
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static FasterList<EGID> _deserialisedBlockMap
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (FasterList<EGID>) fgcr?.Field("_deserialisedBlockMap").GetValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static Traverse fgcr;
|
private static Traverse fgcr;
|
||||||
|
|
||||||
public static void Init(FullGameCompositionRoot instance)
|
public static void Init(FullGameCompositionRoot instance)
|
||||||
|
|
Loading…
Reference in a new issue