Add support for flipped blocks and auto-wiring, other fixes

This commit is contained in:
Norbi Peti 2021-04-19 03:13:00 +02:00
parent 9a4ff858f3
commit 1f688195af
No known key found for this signature in database
GPG key ID: DBA4C4549A927E56
5 changed files with 47 additions and 34 deletions

View file

@ -13,6 +13,7 @@ using Gamecraft.Blocks.GUI;
using GamecraftModdingAPI.Blocks; using GamecraftModdingAPI.Blocks;
using GamecraftModdingAPI.Utility; using GamecraftModdingAPI.Utility;
using RobocraftX.Rendering.GPUI;
namespace GamecraftModdingAPI namespace GamecraftModdingAPI
{ {
@ -45,13 +46,15 @@ namespace GamecraftModdingAPI
/// <param name="rotation">The block's rotation in degrees</param> /// <param name="rotation">The block's rotation in degrees</param>
/// <param name="uscale">The block's uniform scale - default scale is 1 (with 0.2 width)</param> /// <param name="uscale">The block's uniform scale - default scale is 1 (with 0.2 width)</param>
/// <param name="scale">The block's non-uniform scale - 0 means <paramref name="uscale"/> is used</param> /// <param name="scale">The block's non-uniform scale - 0 means <paramref name="uscale"/> is used</param>
/// <param name="isFlipped">Whether the block should be flipped</param>
/// <param name="autoWire">Whether the block should be auto-wired (if functional)</param>
/// <param name="player">The player who placed the block</param> /// <param name="player">The player who placed the block</param>
/// <returns>The placed block or null if failed</returns> /// <returns>The placed block or null if failed</returns>
public static Block PlaceNew(BlockIDs block, float3 position, float3 rotation = default, public static Block PlaceNew(BlockIDs block, float3 position, float3 rotation = default,
BlockColors color = BlockColors.Default, BlockMaterial material = BlockMaterial.Default, BlockColors color = BlockColors.Default, BlockMaterial material = BlockMaterial.Default,
int uscale = 1, float3 scale = default, Player player = null) int uscale = 1, float3 scale = default, bool isFlipped = false, bool autoWire = false, Player player = null)
{ {
return PlaceNew<Block>(block, position, rotation, color, material, uscale, scale, player); return PlaceNew<Block>(block, position, rotation, color, material, uscale, scale, isFlipped, autoWire, player);
} }
/// <summary> /// <summary>
@ -66,16 +69,19 @@ namespace GamecraftModdingAPI
/// <param name="rotation">The block's rotation in degrees</param> /// <param name="rotation">The block's rotation in degrees</param>
/// <param name="uscale">The block's uniform scale - default scale is 1 (with 0.2 width)</param> /// <param name="uscale">The block's uniform scale - default scale is 1 (with 0.2 width)</param>
/// <param name="scale">The block's non-uniform scale - 0 means <paramref name="uscale"/> is used</param> /// <param name="scale">The block's non-uniform scale - 0 means <paramref name="uscale"/> is used</param>
/// <param name="isFlipped">Whether the block should be flipped</param>
/// <param name="autoWire">Whether the block should be auto-wired (if functional)</param>
/// <param name="player">The player who placed the block</param> /// <param name="player">The player who placed the block</param>
/// <returns>The placed block or null if failed</returns> /// <returns>The placed block or null if failed</returns>
public static T PlaceNew<T>(BlockIDs block, float3 position, public static T PlaceNew<T>(BlockIDs block, float3 position,
float3 rotation = default, BlockColor? color = null, BlockMaterial material = BlockMaterial.Default, float3 rotation = default, BlockColor? color = null, BlockMaterial material = BlockMaterial.Default,
int uscale = 1, float3 scale = default, Player player = null) where T : Block int uscale = 1, float3 scale = default, bool isFlipped = false, bool autoWire = false, Player player = null)
where T : Block
{ {
if (PlacementEngine.IsInGame && GameState.IsBuildMode()) if (PlacementEngine.IsInGame && GameState.IsBuildMode())
{ {
var egid = PlacementEngine.PlaceBlock(block, color ?? BlockColors.Default, material, var egid = PlacementEngine.PlaceBlock(block, color ?? BlockColors.Default, material,
position, uscale, scale, player, rotation, out var initializer); position, uscale, scale, player, rotation, isFlipped, autoWire, out var initializer);
var bl = New<T>(egid.entityID, egid.groupID); var bl = New<T>(egid.entityID, egid.groupID);
bl.InitData.Group = BlockEngine.InitGroup(initializer); bl.InitData.Group = BlockEngine.InitGroup(initializer);
Placed += bl.OnPlacedInit; Placed += bl.OnPlacedInit;
@ -293,6 +299,24 @@ namespace GamecraftModdingAPI
} }
} }
/**
* Whether the block is fipped.
*/
public bool Flipped
{
get => BlockEngine.GetBlockInfo(this, (ScalingEntityStruct st) => st.scale.x < 0);
set
{
BlockEngine.SetBlockInfo(this, (ref ScalingEntityStruct st, bool val) =>
st.scale.x = math.abs(st.scale.x) * (val ? -1 : 1), value);
BlockEngine.SetBlockInfo(this, (ref GFXPrefabEntityStructGPUI st, bool val) =>
{
uint prefabId = PrefabsID.GetOrCreatePrefabID((ushort) Type, (byte) Material, 0, value);
st.prefabID = prefabId;
}, value);
}
}
/// <summary> /// <summary>
/// The block's type (ID). Returns BlockIDs.Invalid if the block doesn't exist anymore. /// The block's type (ID). Returns BlockIDs.Invalid if the block doesn't exist anymore.
/// </summary> /// </summary>

View file

@ -80,17 +80,7 @@ namespace GamecraftModdingAPI.Blocks
public ref T GetBlockInfoViewStruct<T>(EGID blockID) where T : struct, INeedEGID, IEntityViewComponent public ref T GetBlockInfoViewStruct<T>(EGID blockID) where T : struct, INeedEGID, IEntityViewComponent
{ {
if (entitiesDB.Exists<T>(blockID)) if (entitiesDB.Exists<T>(blockID))
{ return ref entitiesDB.QueryEntity<T>(blockID);
// TODO: optimize by using EntitiesDB internal calls instead of iterating over everything
BT<MB<T>> entities = entitiesDB.QueryEntities<T>(blockID.groupID).ToBuffer();
for (int i = 0; i < entities.count; i++)
{
if (entities.buffer[i].ID == blockID)
{
return ref entities.buffer[i];
}
}
}
T[] structHolder = new T[1]; //Create something that can be referenced T[] structHolder = new T[1]; //Create something that can be referenced
return ref structHolder[0]; //Gets a default value automatically return ref structHolder[0]; //Gets a default value automatically
} }

View file

@ -2,6 +2,7 @@
using RobocraftX.Common; using RobocraftX.Common;
using HarmonyLib; using HarmonyLib;
using Svelto.DataStructures;
namespace GamecraftModdingAPI.Blocks namespace GamecraftModdingAPI.Blocks
{ {
@ -12,8 +13,8 @@ namespace GamecraftModdingAPI.Blocks
{ {
/// <summary> /// <summary>
/// Blocks placed by the player /// Blocks placed by the player
/// </summary> - TODO /// </summary>
//public static ExclusiveGroup OWNED_BLOCKS { get { return CommonExclusiveGroups.REAL_BLOCKS_GROUPS_DON_T_USE_IN_NEW_CODE; } } public static FasterReadOnlyList<ExclusiveGroupStruct> OWNED_BLOCKS { get { return CommonExclusiveGroups.REAL_BLOCKS_GROUPS_DON_T_USE_IN_NEW_CODE; } }
/// <summary> /// <summary>
/// Extra parts used in functional blocks /// Extra parts used in functional blocks

View file

@ -2,6 +2,7 @@ using System;
using System.Reflection; using System.Reflection;
using DataLoader; using DataLoader;
using Gamecraft.Wires;
using HarmonyLib; using HarmonyLib;
using RobocraftX.Blocks; using RobocraftX.Blocks;
using RobocraftX.Blocks.Scaling; using RobocraftX.Blocks.Scaling;
@ -41,16 +42,16 @@ namespace GamecraftModdingAPI.Blocks
private static BlockEntityFactory _blockEntityFactory; //Injected from PlaceSingleBlockEngine private static BlockEntityFactory _blockEntityFactory; //Injected from PlaceSingleBlockEngine
public EGID PlaceBlock(BlockIDs block, BlockColor color, BlockMaterial materialId, float3 position, int uscale, public EGID PlaceBlock(BlockIDs block, BlockColor color, BlockMaterial materialId, float3 position, int uscale,
float3 scale, Player player, float3 rotation, out EntityInitializer initializer) float3 scale, Player player, float3 rotation, bool isFlipped, bool autoWire, out EntityInitializer initializer)
{ //It appears that only the non-uniform scale has any visible effect, but if that's not given here it will be set to the uniform one { //It appears that only the non-uniform scale has any visible effect, but if that's not given here it will be set to the uniform one
if (color.Darkness > 9) if (color.Darkness > 9)
throw new Exception("That is too dark. Make sure to use 0-9 as darkness. (0 is default.)"); throw new Exception("That is too dark. Make sure to use 0-9 as darkness. (0 is default.)");
initializer = BuildBlock((ushort) block, color.Index, (byte) materialId, position, uscale, scale, rotation, initializer = BuildBlock((ushort) block, color.Index, (byte) materialId, position, uscale, scale, rotation,
(player ?? new Player(PlayerType.Local)).Id); isFlipped, autoWire, (player ?? new Player(PlayerType.Local)).Id);
return initializer.EGID; return initializer.EGID;
} }
private EntityInitializer BuildBlock(ushort block, byte color, byte materialId, float3 position, int uscale, float3 scale, float3 rot, uint playerId) private EntityInitializer BuildBlock(ushort block, byte color, byte materialId, float3 position, int uscale, float3 scale, float3 rot, bool isFlipped, bool autoWire, uint playerId)
{ {
if (_blockEntityFactory == null) if (_blockEntityFactory == null)
throw new BlockException("The factory is null."); throw new BlockException("The factory is null.");
@ -63,7 +64,7 @@ namespace GamecraftModdingAPI.Blocks
if (!PrefabsID.PrefabIDByResourceIDMap.ContainsKey(resourceId)) if (!PrefabsID.PrefabIDByResourceIDMap.ContainsKey(resourceId))
throw new BlockException("Block with ID " + block + " not found!"); throw new BlockException("Block with ID " + block + " not found!");
//RobocraftX.CR.MachineEditing.PlaceSingleBlockEngine //RobocraftX.CR.MachineEditing.PlaceSingleBlockEngine
ScalingEntityStruct scaling = new ScalingEntityStruct {scale = scale}; ScalingEntityStruct scaling = new ScalingEntityStruct {scale = scale * (isFlipped ? -1 : 1)};
Quaternion rotQ = Quaternion.Euler(rot); Quaternion rotQ = Quaternion.Euler(rot);
RotationEntityStruct rotation = new RotationEntityStruct {rotation = rotQ}; RotationEntityStruct rotation = new RotationEntityStruct {rotation = rotQ};
GridRotationStruct gridRotation = new GridRotationStruct GridRotationStruct gridRotation = new GridRotationStruct
@ -86,7 +87,7 @@ namespace GamecraftModdingAPI.Blocks
{ {
materialId = materialId materialId = materialId
}); });
uint prefabId = PrefabsID.GetOrCreatePrefabID(block, 0, 0, false); //TODO uint prefabId = PrefabsID.GetOrCreatePrefabID(block, materialId, 0, isFlipped);
structInitializer.Init(new GFXPrefabEntityStructGPUI(prefabId)); structInitializer.Init(new GFXPrefabEntityStructGPUI(prefabId));
structInitializer.Init(new PhysicsPrefabEntityStruct(prefabId)); structInitializer.Init(new PhysicsPrefabEntityStruct(prefabId));
structInitializer.Init(dbEntity); structInitializer.Init(dbEntity);
@ -102,7 +103,7 @@ namespace GamecraftModdingAPI.Blocks
{ {
loadedFromDisk = false, loadedFromDisk = false,
placedBy = playerId, placedBy = playerId,
triggerAutoWiring = false //TODO triggerAutoWiring = autoWire && structInitializer.Has<BlockPortsStruct>()
}); });
/*structInitializer.Init(new CollisionFilterOverride /*structInitializer.Init(new CollisionFilterOverride

View file

@ -11,6 +11,8 @@ using Svelto.ECS;
using GamecraftModdingAPI.Blocks; using GamecraftModdingAPI.Blocks;
using GamecraftModdingAPI.Utility; using GamecraftModdingAPI.Utility;
using GamecraftModdingAPI.Engines; using GamecraftModdingAPI.Engines;
using RobocraftX.Blocks;
using Techblox.FlyCam;
namespace GamecraftModdingAPI.Inventory namespace GamecraftModdingAPI.Inventory
{ {
@ -36,18 +38,13 @@ namespace GamecraftModdingAPI.Inventory
public bool SelectBlock(int block, uint playerID, bool cubeSelectedByPick = false) public bool SelectBlock(int block, uint playerID, bool cubeSelectedByPick = false)
{ {
var inputs = entitiesDB.QueryEntities<LocalInputEntityStruct>(InputExclusiveGroups.LocalPlayers).ToBuffer(); if (!entitiesDB.TryQueryEntitiesAndIndex<EquippedPartStruct>(playerID, Techblox.FlyCam.FlyCam.Group,
if (inputs.count == 0) return false; out var index, out var inputs))
for (int i = 0; i < inputs.count; i++) return false;
{ inputs[index].CubeSelectedByPick = cubeSelectedByPick;
if (inputs.buffer[i].ID.entityID == playerID) { inputs[index].SelectedDBPartID = block;
/*inputs.buffer[i].cubeSelectedByPick = cubeSelectedByPick; - TODO
inputs.buffer[i].selectedCube = block;*/
return true;
}
}
// TODO: expose the rest of the input functionality // TODO: expose the rest of the input functionality
return false; return true;
} }
public uint GetLocalPlayerID() public uint GetLocalPlayerID()