Add ability to create & move block groups & other stuff
Added a way to store block groups as blueprints Blocks can be added/removed from block groups, although it doesn't work well atm Added some patches to the test class in an attempt to debug an unrelated issue Added a command to test placing a block group Added a SelectedBlueprint property to the Player class
This commit is contained in:
parent
f1376f5df6
commit
4580ae3b66
8 changed files with 332 additions and 47 deletions
|
@ -240,6 +240,8 @@ namespace GamecraftModdingAPI
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
MovementEngine.MoveBlock(Id, InitData, value);
|
MovementEngine.MoveBlock(Id, InitData, value);
|
||||||
|
if (blockGroup != null)
|
||||||
|
blockGroup.PosAndRotCalculated = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -252,6 +254,8 @@ namespace GamecraftModdingAPI
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
RotationEngine.RotateBlock(Id, InitData, value);
|
RotationEngine.RotateBlock(Id, InitData, value);
|
||||||
|
if (blockGroup != null)
|
||||||
|
blockGroup.PosAndRotCalculated = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,16 +358,32 @@ namespace GamecraftModdingAPI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private BlockGroup blockGroup;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns the block group this block is a part of. Block groups can be placed using blueprints.
|
/// Returns the block group this block is a part of. Block groups can be placed using blueprints.
|
||||||
/// Returns null if not part of a group.
|
/// Returns null if not part of a group.<br />
|
||||||
|
/// Setting the group after the block has been initialized will not update everything properly.
|
||||||
|
/// You should only set this property on blocks newly placed by your code.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public BlockGroup BlockGroup
|
public BlockGroup BlockGroup
|
||||||
{
|
{
|
||||||
get => BlockEngine.GetBlockInfo(this,
|
get
|
||||||
|
{
|
||||||
|
if (blockGroup != null) return blockGroup;
|
||||||
|
return blockGroup = BlockEngine.GetBlockInfo(this,
|
||||||
(BlockGroupEntityComponent bgec) =>
|
(BlockGroupEntityComponent bgec) =>
|
||||||
bgec.currentBlockGroup == -1 ? null : new BlockGroup(bgec.currentBlockGroup, this));
|
bgec.currentBlockGroup == -1 ? null : new BlockGroup(bgec.currentBlockGroup, this));
|
||||||
}
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
blockGroup?.RemoveInternal(this);
|
||||||
|
BlockEngine.SetBlockInfo(this,
|
||||||
|
(ref BlockGroupEntityComponent bgec, BlockGroup val) => bgec.currentBlockGroup = val?.Id ?? -1,
|
||||||
|
value);
|
||||||
|
value?.AddInternal(this);
|
||||||
|
blockGroup = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the block exists. The other properties will return a default value if the block doesn't exist.
|
/// Whether the block exists. The other properties will return a default value if the block doesn't exist.
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
using Gamecraft.Blocks.BlockGroups;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
using Gamecraft.Blocks.BlockGroups;
|
||||||
using Unity.Mathematics;
|
using Unity.Mathematics;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
|
@ -10,11 +14,14 @@ namespace GamecraftModdingAPI
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A group of blocks that can be selected together. The placed version of blueprints.
|
/// A group of blocks that can be selected together. The placed version of blueprints.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class BlockGroup
|
public class BlockGroup : ICollection<Block>
|
||||||
{
|
{
|
||||||
internal static BlueprintEngine _engine = new BlueprintEngine();
|
internal static BlueprintEngine _engine = new BlueprintEngine();
|
||||||
public int Id { get; }
|
public int Id { get; }
|
||||||
private readonly Block sourceBlock;
|
private readonly Block sourceBlock;
|
||||||
|
private readonly List<Block> blocks;
|
||||||
|
private float3 position, rotation;
|
||||||
|
internal bool PosAndRotCalculated;
|
||||||
|
|
||||||
internal BlockGroup(int id, Block block)
|
internal BlockGroup(int id, Block block)
|
||||||
{
|
{
|
||||||
|
@ -22,41 +29,155 @@ namespace GamecraftModdingAPI
|
||||||
throw new BlockException("Cannot create a block group for blocks without a group!");
|
throw new BlockException("Cannot create a block group for blocks without a group!");
|
||||||
Id = id;
|
Id = id;
|
||||||
sourceBlock = block;
|
sourceBlock = block;
|
||||||
|
blocks = new List<Block>(GetBlocks());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The position of the block group. Calculated when GetBlocks() is used.
|
/// The position of the block group (center). Recalculated if blocks have been added/removed since the last query.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float3 Position { get; private set; }
|
public float3 Position
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (!PosAndRotCalculated)
|
||||||
|
Refresh();
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
var diff = value - position;
|
||||||
|
foreach (var block in blocks)
|
||||||
|
block.Position += diff;
|
||||||
|
if (!PosAndRotCalculated) //The condition can only be true if a block has been added/removed manually
|
||||||
|
Refresh(); //So the blocks array is up to date
|
||||||
|
else
|
||||||
|
position += diff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The rotation of the block group. Calculated when GetBlocks() is used.
|
/// The rotation of the block group. Recalculated if blocks have been added/removed since the last query.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public float3 Rotation { get; private set; }
|
public float3 Rotation
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (!PosAndRotCalculated)
|
||||||
|
Refresh();
|
||||||
|
return rotation;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
var diff = value - rotation;
|
||||||
|
var qdiff = Quaternion.Euler(diff);
|
||||||
|
foreach (var block in blocks)
|
||||||
|
{
|
||||||
|
block.Rotation += diff;
|
||||||
|
block.Position = qdiff * block.Position;
|
||||||
|
}
|
||||||
|
if (!PosAndRotCalculated)
|
||||||
|
Refresh();
|
||||||
|
else
|
||||||
|
rotation += diff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*/// <summary>
|
||||||
|
/// Removes all of the blocks in this group from the world.
|
||||||
|
/// </summary>
|
||||||
|
public void RemoveBlocks()
|
||||||
|
{
|
||||||
|
_engine.RemoveBlockGroup(Id); - TODO: Causes a hard crash
|
||||||
|
}*/
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new block group consisting of a single block.
|
||||||
|
/// You can add more blocks using the Add() method or by setting the BlockGroup property of the blocks.<br />
|
||||||
|
/// Note that only newly placed blocks should be added to groups.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="block">The block to add</param>
|
||||||
|
/// <returns>A new block group containing the given block</returns>
|
||||||
|
public static BlockGroup Create(Block block)
|
||||||
|
{
|
||||||
|
return new BlockGroup(_engine.CreateBlockGroup(default, default), block);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Collects each block that is a part of this group. Also sets the position and rotation.
|
/// Collects each block that is a part of this group. Also sets the position and rotation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>An array of blocks</returns>
|
/// <returns>An array of blocks</returns>
|
||||||
public Block[] GetBlocks()
|
private Block[] GetBlocks()
|
||||||
{
|
{
|
||||||
|
if (!sourceBlock.Exists) return new[] {sourceBlock}; //The block must exist to get the others
|
||||||
var ret = _engine.GetBlocksFromGroup(sourceBlock.Id, out var pos, out var rot);
|
var ret = _engine.GetBlocksFromGroup(sourceBlock.Id, out var pos, out var rot);
|
||||||
Position = pos;
|
position = pos;
|
||||||
Rotation = ((Quaternion) rot).eulerAngles;
|
rotation = ((Quaternion) rot).eulerAngles;
|
||||||
|
PosAndRotCalculated = true;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
private void Refresh()
|
||||||
/// Removes all of the blocks in this group from the world.
|
|
||||||
/// </summary>
|
|
||||||
public void Remove()
|
|
||||||
{
|
{
|
||||||
_engine.RemoveBlockGroup(Id);
|
blocks.Clear();
|
||||||
|
blocks.AddRange(GetBlocks());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Init()
|
internal static void Init()
|
||||||
{
|
{
|
||||||
GameEngineManager.AddGameEngine(_engine);
|
GameEngineManager.AddGameEngine(_engine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEnumerator<Block> GetEnumerator() => blocks.GetEnumerator();
|
||||||
|
IEnumerator IEnumerable.GetEnumerator() => blocks.GetEnumerator();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a block to the group. You should only add newly placed blocks
|
||||||
|
/// so that the game initializes the group membership properly.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item"></param>
|
||||||
|
/// <exception cref="NullReferenceException"></exception>
|
||||||
|
public void Add(Block item)
|
||||||
|
{
|
||||||
|
if (item == null) throw new NullReferenceException("Cannot add null to a block group");
|
||||||
|
item.BlockGroup = this; //Calls AddInternal
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void AddInternal(Block item) => blocks.Add(item);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes all blocks from this group.
|
||||||
|
/// You should not remove blocks that have been initialized, only those that you placed recently.
|
||||||
|
/// </summary>
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
while (blocks.Count > 0)
|
||||||
|
Remove(blocks[blocks.Count - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Contains(Block item) => blocks.Contains(item);
|
||||||
|
public void CopyTo(Block[] array, int arrayIndex) => blocks.CopyTo(array, arrayIndex);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes a block from this group.
|
||||||
|
/// You should not remove blocks that have been initialized, only those that you placed recently.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="item"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="NullReferenceException"></exception>
|
||||||
|
public bool Remove(Block item)
|
||||||
|
{
|
||||||
|
if (item == null) throw new NullReferenceException("Cannot remove null from a block group");
|
||||||
|
bool ret = item.BlockGroup == this;
|
||||||
|
if (ret)
|
||||||
|
item.BlockGroup = null; //Calls RemoveInternal
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void RemoveInternal(Block item) => blocks.Remove(item);
|
||||||
|
|
||||||
|
public int Count => blocks.Count;
|
||||||
|
public bool IsReadOnly { get; } = false;
|
||||||
|
|
||||||
|
public Block this[int index] => blocks[index]; //Setting is not supported, since the order doesn't matter
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -5,10 +5,11 @@ using Svelto.ECS;
|
||||||
|
|
||||||
using GamecraftModdingAPI.Engines;
|
using GamecraftModdingAPI.Engines;
|
||||||
using GamecraftModdingAPI.Utility;
|
using GamecraftModdingAPI.Utility;
|
||||||
|
using RobocraftX.Blocks;
|
||||||
|
|
||||||
namespace GamecraftModdingAPI.Blocks
|
namespace GamecraftModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
public class BlockEventsEngine : IReactionaryEngine<DBEntityStruct>
|
public class BlockEventsEngine : IReactionaryEngine<BlockTagEntityStruct>
|
||||||
{
|
{
|
||||||
public event EventHandler<BlockPlacedRemovedEventArgs> Placed;
|
public event EventHandler<BlockPlacedRemovedEventArgs> Placed;
|
||||||
public event EventHandler<BlockPlacedRemovedEventArgs> Removed;
|
public event EventHandler<BlockPlacedRemovedEventArgs> Removed;
|
||||||
|
@ -27,20 +28,20 @@ namespace GamecraftModdingAPI.Blocks
|
||||||
public bool isRemovable { get; } = false;
|
public bool isRemovable { get; } = false;
|
||||||
|
|
||||||
private bool shouldAddRemove;
|
private bool shouldAddRemove;
|
||||||
public void Add(ref DBEntityStruct entityComponent, EGID egid)
|
public void Add(ref BlockTagEntityStruct entityComponent, EGID egid)
|
||||||
{
|
{
|
||||||
if (!(shouldAddRemove = !shouldAddRemove))
|
if (!(shouldAddRemove = !shouldAddRemove))
|
||||||
return;
|
return;
|
||||||
ExceptionUtil.InvokeEvent(Placed, this,
|
ExceptionUtil.InvokeEvent(Placed, this,
|
||||||
new BlockPlacedRemovedEventArgs {ID = egid, Type = (BlockIDs) entityComponent.DBID});
|
new BlockPlacedRemovedEventArgs {ID = egid});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Remove(ref DBEntityStruct entityComponent, EGID egid)
|
public void Remove(ref BlockTagEntityStruct entityComponent, EGID egid)
|
||||||
{
|
{
|
||||||
if (!(shouldAddRemove = !shouldAddRemove))
|
if (!(shouldAddRemove = !shouldAddRemove))
|
||||||
return;
|
return;
|
||||||
ExceptionUtil.InvokeEvent(Removed, this,
|
ExceptionUtil.InvokeEvent(Removed, this,
|
||||||
new BlockPlacedRemovedEventArgs {ID = egid, Type = (BlockIDs) entityComponent.DBID});
|
new BlockPlacedRemovedEventArgs {ID = egid});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using Gamecraft.Blocks.BlockGroups;
|
using Gamecraft.Blocks.BlockGroups;
|
||||||
using Gamecraft.GUI.Blueprints;
|
using Gamecraft.GUI.Blueprints;
|
||||||
|
@ -21,7 +22,7 @@ using Allocator = Svelto.Common.Allocator;
|
||||||
|
|
||||||
namespace GamecraftModdingAPI.Blocks
|
namespace GamecraftModdingAPI.Blocks
|
||||||
{
|
{
|
||||||
public class BlueprintEngine : IApiEngine
|
public class BlueprintEngine : IFactoryEngine
|
||||||
{
|
{
|
||||||
private readonly MethodInfo getBlocksFromGroup =
|
private readonly MethodInfo getBlocksFromGroup =
|
||||||
AccessTools.Method("RobocraftX.CR.MachineEditing.PlaceBlockUtility:GetBlocksSharingBlockgroup");
|
AccessTools.Method("RobocraftX.CR.MachineEditing.PlaceBlockUtility:GetBlocksSharingBlockgroup");
|
||||||
|
@ -77,13 +78,30 @@ namespace GamecraftModdingAPI.Blocks
|
||||||
connectionFactory, default).Complete();
|
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)
|
public void SelectBlueprint(uint resourceID)
|
||||||
{
|
{
|
||||||
BlueprintUtil.SelectBlueprint(null, new BlueprintInventoryItemEntityStruct
|
if (resourceID == uint.MaxValue)
|
||||||
|
BlueprintUtil.UnselectBlueprint(entitiesDB);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BlueprintUtil.SelectBlueprint(entitiesDB, new BlueprintInventoryItemEntityStruct
|
||||||
{
|
{
|
||||||
blueprintResourceId = resourceID,
|
blueprintResourceId = resourceID,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public uint CreateBlueprint()
|
public uint CreateBlueprint()
|
||||||
{
|
{
|
||||||
|
@ -91,28 +109,27 @@ namespace GamecraftModdingAPI.Blocks
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ReplaceBlueprint(uint playerID, uint blueprintID, Block[] selected, float3 pos, quaternion rot)
|
public void ReplaceBlueprint(uint playerID, uint blueprintID, ICollection<Block> selected, float3 pos, quaternion rot)
|
||||||
{
|
{
|
||||||
var blockIDs = new EGID[selected.Length];
|
var blockIDs = new EGID[selected.Count];
|
||||||
for (var i = 0; i < selected.Length; i++)
|
using (var enumerator = selected.GetEnumerator())
|
||||||
{
|
{
|
||||||
var block = selected[i];
|
for (var i = 0; enumerator.MoveNext(); i++)
|
||||||
|
{
|
||||||
|
var block = enumerator.Current;
|
||||||
blockIDs[i] = block.Id;
|
blockIDs[i] = block.Id;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var serializationData = clipboardManager.GetSerializationData(blueprintID);
|
var serializationData = clipboardManager.GetSerializationData(blueprintID);
|
||||||
SelectionSerializationUtility.ClearClipboard(playerID, entitiesDB, entityFunctions, serializationData.blueprintData);
|
SelectionSerializationUtility.ClearClipboard(playerID, entitiesDB, entityFunctions, serializationData.blueprintData);
|
||||||
if (selected.Length == 0)
|
if (selected.Count == 0)
|
||||||
return;
|
return;
|
||||||
//ref BlockGroupTransformEntityComponent groupTransform = ref EntityNativeDBExtensions.QueryEntity<BlockGroupTransformEntityComponent>(entitiesDb, (uint) local1.currentBlockGroup, BlockGroupExclusiveGroups.BlockGroupEntityGroup);
|
//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);
|
//ref ColliderAabb collider = ref EntityNativeDBExtensions.QueryEntity<ColliderAabb>(entitiesDB, (uint) groupID, BlockGroupExclusiveGroups.BlockGroupEntityGroup);
|
||||||
//float3 bottomOffset = PlaceBlockUtility.GetBottomOffset(collider);
|
//float3 bottomOffset = PlaceBlockUtility.GetBottomOffset(collider);
|
||||||
//var rootPosition = math.mul(groupTransform.blockGroupGridRotation, bottomOffset) + groupTransform.blockGroupGridPosition;
|
//var rootPosition = math.mul(groupTransform.blockGroupGridRotation, bottomOffset) + groupTransform.blockGroupGridPosition;
|
||||||
//var rootRotation = groupTransform.blockGroupGridRotation;
|
//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);
|
clipboardManager.SetGhostSerialized(blueprintID, false);
|
||||||
SelectionSerializationUtility.CopySelectionToClipboard(playerID, entitiesDB,
|
SelectionSerializationUtility.CopySelectionToClipboard(playerID, entitiesDB,
|
||||||
|
@ -189,7 +206,7 @@ namespace GamecraftModdingAPI.Blocks
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Name { get; } = "GamecraftModdingAPIBlueprintGameEngine";
|
public string Name { get; } = "GamecraftModdingAPIBlueprintGameEngine";
|
||||||
public bool isRemovable { get; }
|
public bool isRemovable { get; } = false;
|
||||||
|
|
||||||
[HarmonyPatch]
|
[HarmonyPatch]
|
||||||
private static class RemoveEnginePatch
|
private static class RemoveEnginePatch
|
||||||
|
@ -225,5 +242,7 @@ namespace GamecraftModdingAPI.Blocks
|
||||||
return AccessTools.GetDeclaredConstructors(AccessTools.TypeByName("RobocraftX.CR.MachineEditing.SelectBlockEngine"))[0];
|
return AccessTools.GetDeclaredConstructors(AccessTools.TypeByName("RobocraftX.CR.MachineEditing.SelectBlockEngine"))[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IEntityFactory Factory { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -53,15 +53,15 @@ namespace GamecraftModdingAPI.Blocks
|
||||||
private EntityComponentInitializer BuildBlock(ushort block, byte color, float3 position, int uscale, float3 scale, float3 rot, uint playerId)
|
private EntityComponentInitializer BuildBlock(ushort block, byte color, float3 position, int uscale, float3 scale, float3 rot, uint playerId)
|
||||||
{
|
{
|
||||||
if (_blockEntityFactory == null)
|
if (_blockEntityFactory == null)
|
||||||
throw new Exception("The factory is null.");
|
throw new BlockException("The factory is null.");
|
||||||
if (uscale < 1)
|
if (uscale < 1)
|
||||||
throw new Exception("Scale needs to be at least 1");
|
throw new BlockException("Scale needs to be at least 1");
|
||||||
if (scale.x < 4e-5) scale.x = uscale;
|
if (scale.x < 4e-5) scale.x = uscale;
|
||||||
if (scale.y < 4e-5) scale.y = uscale;
|
if (scale.y < 4e-5) scale.y = uscale;
|
||||||
if (scale.z < 4e-5) scale.z = uscale;
|
if (scale.z < 4e-5) scale.z = uscale;
|
||||||
uint dbid = block;
|
uint dbid = block;
|
||||||
if (!PrefabsID.DBIDMAP.ContainsKey(dbid))
|
if (!PrefabsID.HasPrefabRegistered(dbid, 0))
|
||||||
throw new Exception("Block with ID " + dbid + " not found!");
|
throw new BlockException("Block with ID " + dbid + " not found!");
|
||||||
//RobocraftX.CR.MachineEditing.PlaceBlockEngine
|
//RobocraftX.CR.MachineEditing.PlaceBlockEngine
|
||||||
ScalingEntityStruct scaling = new ScalingEntityStruct {scale = scale};
|
ScalingEntityStruct scaling = new ScalingEntityStruct {scale = scale};
|
||||||
Quaternion rotQ = Quaternion.Euler(rot);
|
Quaternion rotQ = Quaternion.Euler(rot);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using Unity.Mathematics;
|
using Unity.Mathematics;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
namespace GamecraftModdingAPI
|
namespace GamecraftModdingAPI
|
||||||
{
|
{
|
||||||
|
@ -35,16 +36,27 @@ namespace GamecraftModdingAPI
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Set the blocks that the blueprint contains.
|
/// Set the blocks that the blueprint contains.
|
||||||
|
/// Use the BlockGroup overload for automatically calculated position and rotation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="blocks">The array of blocks to use</param>
|
/// <param name="blocks">The array of blocks to use</param>
|
||||||
/// <param name="position">The anchor position of the blueprint</param>
|
/// <param name="position">The anchor position of the blueprint</param>
|
||||||
/// <param name="rotation">The rotation of the blueprint</param>
|
/// <param name="rotation">The base rotation of the blueprint</param>
|
||||||
public void SetStoredBlocks(Block[] blocks, float3 position = default, float3 rotation = default)
|
public void StoreBlocks(Block[] blocks, float3 position, float3 rotation)
|
||||||
{
|
{
|
||||||
BlockGroup._engine.ReplaceBlueprint(Player.LocalPlayer.Id, Id, blocks, position,
|
BlockGroup._engine.ReplaceBlueprint(Player.LocalPlayer.Id, Id, blocks, position,
|
||||||
quaternion.Euler(rotation));
|
quaternion.Euler(rotation));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Store the blocks from the given group in the blueprint with correct position and rotation for the blueprint.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="group">The block group to store</param>
|
||||||
|
public void StoreBlocks(BlockGroup group)
|
||||||
|
{
|
||||||
|
BlockGroup._engine.ReplaceBlueprint(Player.LocalPlayer.Id, Id, group, group.Position,
|
||||||
|
Quaternion.Euler(group.Rotation));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Places the blocks the blueprint contains at the specified position and rotation.
|
/// Places the blocks the blueprint contains at the specified position and rotation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using Gamecraft.GUI.Blueprints;
|
||||||
using Unity.Mathematics;
|
using Unity.Mathematics;
|
||||||
using RobocraftX.Common;
|
using RobocraftX.Common;
|
||||||
using RobocraftX.Common.Players;
|
using RobocraftX.Common.Players;
|
||||||
|
@ -343,6 +343,17 @@ namespace GamecraftModdingAPI
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The player's selected blueprint in their hand. Set to null to clear. Dispose after usage.
|
||||||
|
/// </summary>
|
||||||
|
public Blueprint SelectedBlueprint
|
||||||
|
{
|
||||||
|
get => playerEngine.GetPlayerStruct(Id, out BlueprintInventoryItemEntityStruct biies)
|
||||||
|
? new Blueprint(biies.blueprintResourceId)
|
||||||
|
: null;
|
||||||
|
set => BlockGroup._engine.SelectBlueprint(value?.Id ?? uint.MaxValue);
|
||||||
|
}
|
||||||
|
|
||||||
// object methods
|
// object methods
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -1,24 +1,29 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Reflection.Emit;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using IllusionInjector;
|
using IllusionInjector;
|
||||||
// test
|
// test
|
||||||
|
using GPUInstancer;
|
||||||
using Svelto.ECS;
|
using Svelto.ECS;
|
||||||
using RobocraftX.Blocks;
|
using RobocraftX.Blocks;
|
||||||
using RobocraftX.Common;
|
using RobocraftX.Common;
|
||||||
using RobocraftX.SimulationModeState;
|
using RobocraftX.SimulationModeState;
|
||||||
using RobocraftX.FrontEnd;
|
using RobocraftX.FrontEnd;
|
||||||
using Unity.Mathematics;
|
using Unity.Mathematics;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
using GamecraftModdingAPI.Commands;
|
using GamecraftModdingAPI.Commands;
|
||||||
using GamecraftModdingAPI.Events;
|
using GamecraftModdingAPI.Events;
|
||||||
using GamecraftModdingAPI.Utility;
|
using GamecraftModdingAPI.Utility;
|
||||||
using GamecraftModdingAPI.Blocks;
|
using GamecraftModdingAPI.Blocks;
|
||||||
using GamecraftModdingAPI.Players;
|
using GamecraftModdingAPI.Players;
|
||||||
|
using EventType = GamecraftModdingAPI.Events.EventType;
|
||||||
|
|
||||||
namespace GamecraftModdingAPI.Tests
|
namespace GamecraftModdingAPI.Tests
|
||||||
{
|
{
|
||||||
|
@ -269,6 +274,20 @@ namespace GamecraftModdingAPI.Tests
|
||||||
Logging.CommandLog("Health set to: " + val);
|
Logging.CommandLog("Health set to: " + val);
|
||||||
}).Build();
|
}).Build();
|
||||||
|
|
||||||
|
CommandBuilder.Builder("placeBlockGroup", "Places some blocks in a group")
|
||||||
|
.Action((float x, float y, float z) =>
|
||||||
|
{
|
||||||
|
var pos = new float3(x, y, z);
|
||||||
|
var group = BlockGroup.Create(Block.PlaceNew(BlockIDs.AluminiumCube, pos,
|
||||||
|
color: BlockColors.Aqua));
|
||||||
|
Block.PlaceNew(BlockIDs.AluminiumCube, pos += new float3(1, 0, 0), color: BlockColors.Blue)
|
||||||
|
.BlockGroup = group;
|
||||||
|
Block.PlaceNew(BlockIDs.AluminiumCube, pos += new float3(1, 0, 0), color: BlockColors.Green)
|
||||||
|
.BlockGroup = group;
|
||||||
|
Block.PlaceNew(BlockIDs.AluminiumCube, pos += new float3(1, 0, 0), color: BlockColors.Lime)
|
||||||
|
.BlockGroup = group;
|
||||||
|
}).Build();
|
||||||
|
|
||||||
GameClient.SetDebugInfo("InstalledMods", InstalledMods);
|
GameClient.SetDebugInfo("InstalledMods", InstalledMods);
|
||||||
Block.Placed += (sender, args) =>
|
Block.Placed += (sender, args) =>
|
||||||
Logging.MetaDebugLog("Placed block " + args.Type + " with ID " + args.ID);
|
Logging.MetaDebugLog("Placed block " + args.Type + " with ID " + args.ID);
|
||||||
|
@ -391,6 +410,88 @@ namespace GamecraftModdingAPI.Tests
|
||||||
return ((Action) MinimumSpecsCheck.CheckRequirementsMet).Method;
|
return ((Action) MinimumSpecsCheck.CheckRequirementsMet).Method;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch]
|
||||||
|
public class BugHuntPatch
|
||||||
|
{
|
||||||
|
public static MethodInfo method =
|
||||||
|
SymbolExtensions.GetMethodInfo<string>(str => Console.WriteLine(str));
|
||||||
|
|
||||||
|
public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
foreach (var instruction in instructions)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
yield return instruction; //Return the instruction first
|
||||||
|
//stloc, dup, callvirt
|
||||||
|
if (instruction.opcode.Name.ToLower().StartsWith("stloc")
|
||||||
|
|| instruction.opcode == OpCodes.Dup
|
||||||
|
|| instruction.opcode == OpCodes.Callvirt)
|
||||||
|
{
|
||||||
|
yield return new CodeInstruction(OpCodes.Ldstr,
|
||||||
|
"Just ran the " + i + ". instruction ending with " + instruction.opcode.Name);
|
||||||
|
yield return new CodeInstruction(OpCodes.Call, method);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MethodInfo TargetMethod()
|
||||||
|
{
|
||||||
|
return AccessTools.Method("RobocraftX.CR.MachineEditing.BoxSelect.CopySelectionEngine:GenerateThumbnail");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch]
|
||||||
|
public class BugHuntPatch2
|
||||||
|
{
|
||||||
|
public static void Prefix(int width, float fieldOfView, Vector3 cameraDirection, Vector3 lightDirection)
|
||||||
|
{
|
||||||
|
Console.WriteLine("TakeThumbnail invoked with parameters: " + width + ", " + fieldOfView + ", " +
|
||||||
|
cameraDirection + ", " + lightDirection);
|
||||||
|
|
||||||
|
GPUInstancerManager manager = GPUInstancerAPI.GetActiveManagers().Find(m => m is GPUInstancerPrefabManager);
|
||||||
|
Bounds instancesBounds = manager.ComputeInstancesBounds(2);
|
||||||
|
Console.WriteLine("Bounds: " + instancesBounds);
|
||||||
|
Console.WriteLine("Size: " + instancesBounds.size);
|
||||||
|
Console.WriteLine("Size.x < 0: " + (instancesBounds.size.x < 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Postfix(Texture2D __result)
|
||||||
|
{
|
||||||
|
Console.WriteLine("TakeThumbnail returned: " + (__result == null ? null : __result.name));
|
||||||
|
}
|
||||||
|
|
||||||
|
private delegate Texture2D TakeThumbnailDel(int width, float fieldOfView, Vector3 cameraDirection,
|
||||||
|
Vector3 lightDirection);
|
||||||
|
|
||||||
|
public static MethodInfo TargetMethod()
|
||||||
|
{
|
||||||
|
return ((TakeThumbnailDel) ThumbnailUtility.TakeThumbnail).Method;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HarmonyPatch]
|
||||||
|
public class BugHuntPatch3
|
||||||
|
{
|
||||||
|
public static void Prefix(int width, int filterLayerMask, GPUInstancerManager manager,
|
||||||
|
Vector3 cameraPosition, Quaternion cameraRotation, float cameraFov, Vector3 lightDirection,
|
||||||
|
int cullingLayer)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Inner TakeThumbnail invoked with parameters: " + width + ", " + filterLayerMask +
|
||||||
|
", " + (manager != null ? manager.name : null) + ", " + cameraPosition + ", " +
|
||||||
|
cameraRotation + ", " + cameraFov + ", " + lightDirection + ", " + cullingLayer);
|
||||||
|
}
|
||||||
|
|
||||||
|
private delegate Texture2D TakeThumbnailDel(int width, int filterLayerMask, GPUInstancerManager manager,
|
||||||
|
Vector3 cameraPosition, Quaternion cameraRotation, float cameraFov, Vector3 lightDirection,
|
||||||
|
int cullingLayer);
|
||||||
|
|
||||||
|
public static MethodInfo TargetMethod()
|
||||||
|
{
|
||||||
|
return ((TakeThumbnailDel) ThumbnailUtility.TakeThumbnail).Method;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue