@@ -7,6 +7,7 @@ using Svelto.ECS.EntityStructs; | |||
using RobocraftX.Common; | |||
using RobocraftX.Blocks; | |||
using Unity.Mathematics; | |||
using Gamecraft.Blocks.GUI; | |||
using GamecraftModdingAPI.Blocks; | |||
using GamecraftModdingAPI.Utility; | |||
@@ -231,6 +232,20 @@ namespace GamecraftModdingAPI | |||
} | |||
} | |||
/// <summary> | |||
/// The short text displayed on the block if applicable, or null. | |||
/// Setting it is temporary to the session, it won't be saved. | |||
/// </summary> | |||
public string Label | |||
{ | |||
get => BlockEngine.GetBlockInfo<TextLabelEntityViewStruct>(Id).textLabelComponent?.text; | |||
set | |||
{ | |||
ref var text = ref BlockEngine.GetBlockInfo<TextLabelEntityViewStruct>(Id); | |||
if (text.textLabelComponent != null) text.textLabelComponent.text = value; | |||
} | |||
} | |||
/// <summary> | |||
/// Whether the block exists. The other properties will return a default value if the block doesn't exist. | |||
/// </summary> | |||
@@ -251,8 +266,8 @@ namespace GamecraftModdingAPI | |||
/// Returns the rigid body of the cluster of blocks this one belongs to during simulation. | |||
/// Can be used to apply forces or move the block around while the simulation is running. | |||
/// </summary> | |||
/// <returns></returns> | |||
public SimBody ToSimBody() | |||
/// <returns>The SimBody of the cluster</returns> | |||
public SimBody GetSimBody() | |||
{ | |||
uint id = BlockEngine.GetBlockInfo<GridConnectionsEntityStruct>(Id).machineRigidBodyId; | |||
return new SimBody(id); | |||
@@ -260,7 +275,7 @@ namespace GamecraftModdingAPI | |||
public override string ToString() | |||
{ | |||
return $"{nameof(Id)}: {Id}, {nameof(Position)}: {Position}, {nameof(Rotation)}: {Rotation}"; | |||
return $"{nameof(Id)}: {Id}, {nameof(Position)}: {Position}, {nameof(Type)}: {Type}, {nameof(Color)}: {Color}, {nameof(Exists)}: {Exists}"; | |||
} | |||
public static void Init() | |||
@@ -1,5 +1,6 @@ | |||
using System.Collections.Generic; | |||
using Gamecraft.Wires; | |||
using RobocraftX.Blocks; | |||
using RobocraftX.Common; | |||
using RobocraftX.GUI.Hotbar.Colours; | |||
@@ -91,6 +92,40 @@ namespace GamecraftModdingAPI.Blocks | |||
return entitiesDB.Exists<T>(blockID); | |||
} | |||
public SimBody[] GetSimBodiesFromID(byte id) | |||
{ | |||
var ret = new FasterList<SimBody>(4); | |||
if (!entitiesDB.HasAny<ObjectIdEntityStruct>(CommonExclusiveGroups.OWNED_BLOCKS_GROUP)) | |||
return new SimBody[0]; | |||
var oids = entitiesDB.QueryEntities<ObjectIdEntityStruct>(CommonExclusiveGroups.OWNED_BLOCKS_GROUP); | |||
var connections = entitiesDB.QueryMappedEntities<GridConnectionsEntityStruct>(CommonExclusiveGroups.OWNED_BLOCKS_GROUP); | |||
foreach (ref ObjectIdEntityStruct oid in oids) | |||
{ | |||
if (oid.objectId != id) continue; | |||
var rid = connections.Entity(oid.ID.entityID).machineRigidBodyId; | |||
foreach (var rb in ret) | |||
{ | |||
if (rb.Id.entityID == rid) | |||
goto DUPLICATE; //Multiple Object Identifiers on one rigid body | |||
} | |||
ret.Add(new SimBody(rid)); | |||
DUPLICATE: ; | |||
} | |||
return ret.ToArray(); | |||
} | |||
public ObjectIdentifier[] GetObjectIDsFromID(byte id) | |||
{ | |||
var ret = new FasterList<ObjectIdentifier>(4); | |||
if (!entitiesDB.HasAny<ObjectIdEntityStruct>(CommonExclusiveGroups.OWNED_BLOCKS_GROUP)) | |||
return new ObjectIdentifier[0]; | |||
var oids = entitiesDB.QueryEntities<ObjectIdEntityStruct>(CommonExclusiveGroups.OWNED_BLOCKS_GROUP); | |||
foreach (ref ObjectIdEntityStruct oid in oids) | |||
if (oid.objectId == id) | |||
ret.Add(new ObjectIdentifier(oid.ID)); | |||
return ret.ToArray(); | |||
} | |||
#if DEBUG | |||
public EntitiesDB GetEntitiesDB() | |||
{ | |||
@@ -0,0 +1,41 @@ | |||
using Gamecraft.Wires; | |||
using Svelto.ECS; | |||
namespace GamecraftModdingAPI.Blocks | |||
{ | |||
public class ObjectIdentifier : Block | |||
{ | |||
public ObjectIdentifier(EGID id) : base(id) | |||
{ | |||
if (!BlockEngine.GetBlockInfoExists<ObjectIdEntityStruct>(Id)) | |||
{ | |||
throw new BlockTypeException($"Block is not a {GetType().Name} block"); | |||
} | |||
} | |||
public ObjectIdentifier(uint id) : base(id) | |||
{ | |||
if (!BlockEngine.GetBlockInfoExists<ObjectIdEntityStruct>(Id)) | |||
{ | |||
throw new BlockTypeException($"Block is not a {GetType().Name} block"); | |||
} | |||
} | |||
public char Identifier | |||
{ | |||
get => (char) (BlockEngine.GetBlockInfo<ObjectIdEntityStruct>(Id).objectId + 'A'); | |||
set | |||
{ | |||
BlockEngine.GetBlockInfo<ObjectIdEntityStruct>(Id).objectId = (byte) (value - 'A'); | |||
Label = value + ""; //The label isn't updated automatically | |||
} | |||
} | |||
/// <summary> | |||
/// Finds the identfier blocks with the given ID. | |||
/// </summary> | |||
/// <param name="id">The ID to look for</param> | |||
/// <returns>An array that may be empty</returns> | |||
public static ObjectIdentifier[] GetByID(char id) => BlockEngine.GetObjectIDsFromID((byte) (id - 'A')); | |||
} | |||
} |
@@ -1,8 +1,8 @@ | |||
using RobocraftX.Common; | |||
using Gamecraft.Wires; | |||
using RobocraftX.Common; | |||
using RobocraftX.Physics; | |||
using Svelto.ECS; | |||
using Unity.Mathematics; | |||
using Unity.Physics; | |||
using UnityEngine; | |||
namespace GamecraftModdingAPI | |||
@@ -74,15 +74,25 @@ namespace GamecraftModdingAPI | |||
/// <summary> | |||
/// Whether the body can be moved or static | |||
/// </summary> | |||
public bool Static | |||
{ | |||
get => Block.BlockEngine.GetBlockInfo<MassEntityStruct>(Id).isStatic; | |||
set => Block.BlockEngine.GetBlockInfo<MassEntityStruct>(Id).isStatic = value; | |||
} | |||
public bool Static => Block.BlockEngine.GetBlockInfo<MassEntityStruct>(Id).isStatic; | |||
//Setting it doesn't have any effect | |||
private ref RigidBodyEntityStruct GetStruct() | |||
{ | |||
return ref Block.BlockEngine.GetBlockInfo<RigidBodyEntityStruct>(Id); | |||
} | |||
public override string ToString() | |||
{ | |||
return $"{nameof(Id)}: {Id}, {nameof(Position)}: {Position}, {nameof(Mass)}: {Mass}, {nameof(Static)}: {Static}"; | |||
} | |||
/// <summary> | |||
/// Returns the object identified by the given ID (A-Z). | |||
/// This has the same result as calling ObjectIdentifier.GetByID(id) and then GetRigidBody() with the duplicates filtered out. | |||
/// </summary> | |||
/// <param name="id">The alphabetical ID</param> | |||
/// <returns>An array that may be empty</returns> | |||
public static SimBody[] GetFromObjectID(char id) => Block.BlockEngine.GetSimBodiesFromID((byte) (id - 'A')); | |||
} | |||
} |
@@ -175,7 +175,7 @@ namespace GamecraftModdingAPI.Tests | |||
//With Sync() at the end: 380ms | |||
Block b = null; | |||
CommandBuilder.Builder("moveBlockInSim", "Run in build mode first, then in sim while looking at a block to move it up") | |||
CommandBuilder.Builder("moveBlockInSim", "Run in build mode first while looking at a block, then in sim to move it up") | |||
.Action(() => | |||
{ | |||
if (b == null) | |||
@@ -184,7 +184,7 @@ namespace GamecraftModdingAPI.Tests | |||
Logging.CommandLog("Block saved: " + b); | |||
} | |||
else | |||
Logging.CommandLog("Block moved to: " + (b.ToSimBody().Position += new float3(0, 2, 0))); | |||
Logging.CommandLog("Block moved to: " + (b.GetSimBody().Position += new float3(0, 2, 0))); | |||
}).Build(); | |||
CommandBuilder.Builder("Error", "Throw an error to make sure SimpleCustomCommandEngine's wrapper catches it.") | |||
@@ -209,6 +209,16 @@ namespace GamecraftModdingAPI.Tests | |||
}).Build(); | |||
CommandBuilder.Builder("GetBlockByID", "Gets a block based on its object identifier and teleports it up.") | |||
.Action<char>(ch => | |||
{ | |||
foreach (var body in SimBody.GetFromObjectID(ch)) | |||
{ | |||
Logging.CommandLog("SimBody: " + body); | |||
body.Position += new float3(0, 10, 0); | |||
} | |||
}).Build(); | |||
GameClient.SetDebugInfo("lookedAt", LookedAt); | |||
GameClient.SetDebugInfo("InstalledMods", InstalledMods); | |||
@@ -277,7 +287,8 @@ namespace GamecraftModdingAPI.Tests | |||
{ | |||
Block block = player.GetBlockLookedAt(); | |||
if (block == null) return "Block: none"; | |||
return "Block: " + block.Type + "\nColor: " + block.Color + "\n" + "At: " + block.Position; | |||
return "Block: " + block.Type + "\nColor: " + block.Color + "\n" + "At: " + block.Position | |||
+ "\nText: " + block.Label; | |||
} | |||
if (GameState.IsSimulationMode()) | |||
{ | |||