Add support for setting and placing blueprints
This commit is contained in:
parent
4f8feaa24b
commit
1c4e2a0db2
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.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
|
||||
{
|
||||
|
@ -18,8 +27,20 @@ namespace GamecraftModdingAPI.Blocks
|
|||
private readonly NativeDynamicArray selectedBlocksInGroup = new NativeDynamicArray();
|
||||
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 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()
|
||||
{
|
||||
|
@ -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 bool isRemovable { get; }
|
||||
|
||||
|
@ -66,6 +190,7 @@ namespace GamecraftModdingAPI.Blocks
|
|||
{
|
||||
nativeRemove = entityFunctions.ToNativeRemove<BlockEntityDescriptor>("GCAPI" + nameof(BlueprintEngine));
|
||||
connectionFactory = machineGraphConnectionEntityFactory;
|
||||
BlueprintEngine.entityFunctions = entityFunctions;
|
||||
}
|
||||
|
||||
public static MethodBase TargetMethod()
|
||||
|
@ -73,5 +198,23 @@ namespace GamecraftModdingAPI.Blocks
|
|||
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
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a blueprint in the inventory. When placed it becomes a block group.
|
||||
/// </summary>
|
||||
public class Blueprint
|
||||
public class Blueprint : IDisposable
|
||||
{
|
||||
public uint Id { get; }
|
||||
|
||||
internal Blueprint(uint id)
|
||||
{
|
||||
Id = id;
|
||||
BlockGroup._engine.InitBlueprint(id);
|
||||
}
|
||||
|
||||
/*public static void SelectBlueprint(Blueprint blueprint)
|
||||
{
|
||||
BlueprintUtil.SelectBlueprint(null, new BlueprintInventoryItemEntityStruct
|
||||
|
@ -16,5 +23,42 @@ namespace GamecraftModdingAPI
|
|||
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.Rendering;
|
||||
using Svelto.Context;
|
||||
using Svelto.DataStructures;
|
||||
using Svelto.ECS;
|
||||
using Svelto.ECS.Schedulers.Unity;
|
||||
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;
|
||||
|
||||
public static void Init(FullGameCompositionRoot instance)
|
||||
|
|
Loading…
Reference in a new issue