From ab7c5805fe85793aa7c2acbdac47fa74f759d236 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Sun, 24 May 2020 19:29:02 +0200 Subject: [PATCH] Add object ID block and label support --- GamecraftModdingAPI/Block.cs | 21 ++++++++-- GamecraftModdingAPI/Blocks/BlockEngine.cs | 35 ++++++++++++++++ .../Blocks/ObjectIdentifier.cs | 41 +++++++++++++++++++ GamecraftModdingAPI/SimBody.cs | 24 +++++++---- .../Tests/GamecraftModdingAPIPluginTest.cs | 17 ++++++-- 5 files changed, 125 insertions(+), 13 deletions(-) create mode 100644 GamecraftModdingAPI/Blocks/ObjectIdentifier.cs diff --git a/GamecraftModdingAPI/Block.cs b/GamecraftModdingAPI/Block.cs index 4768a57..ff89be3 100644 --- a/GamecraftModdingAPI/Block.cs +++ b/GamecraftModdingAPI/Block.cs @@ -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 } } + /// + /// The short text displayed on the block if applicable, or null. + /// Setting it is temporary to the session, it won't be saved. + /// + public string Label + { + get => BlockEngine.GetBlockInfo(Id).textLabelComponent?.text; + set + { + ref var text = ref BlockEngine.GetBlockInfo(Id); + if (text.textLabelComponent != null) text.textLabelComponent.text = value; + } + } + /// /// Whether the block exists. The other properties will return a default value if the block doesn't exist. /// @@ -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. /// - /// - public SimBody ToSimBody() + /// The SimBody of the cluster + public SimBody GetSimBody() { uint id = BlockEngine.GetBlockInfo(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() diff --git a/GamecraftModdingAPI/Blocks/BlockEngine.cs b/GamecraftModdingAPI/Blocks/BlockEngine.cs index a47a328..eecebc2 100644 --- a/GamecraftModdingAPI/Blocks/BlockEngine.cs +++ b/GamecraftModdingAPI/Blocks/BlockEngine.cs @@ -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(blockID); } + public SimBody[] GetSimBodiesFromID(byte id) + { + var ret = new FasterList(4); + if (!entitiesDB.HasAny(CommonExclusiveGroups.OWNED_BLOCKS_GROUP)) + return new SimBody[0]; + var oids = entitiesDB.QueryEntities(CommonExclusiveGroups.OWNED_BLOCKS_GROUP); + var connections = entitiesDB.QueryMappedEntities(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(4); + if (!entitiesDB.HasAny(CommonExclusiveGroups.OWNED_BLOCKS_GROUP)) + return new ObjectIdentifier[0]; + var oids = entitiesDB.QueryEntities(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() { diff --git a/GamecraftModdingAPI/Blocks/ObjectIdentifier.cs b/GamecraftModdingAPI/Blocks/ObjectIdentifier.cs new file mode 100644 index 0000000..3beacfa --- /dev/null +++ b/GamecraftModdingAPI/Blocks/ObjectIdentifier.cs @@ -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(Id)) + { + throw new BlockTypeException($"Block is not a {GetType().Name} block"); + } + } + + public ObjectIdentifier(uint id) : base(id) + { + if (!BlockEngine.GetBlockInfoExists(Id)) + { + throw new BlockTypeException($"Block is not a {GetType().Name} block"); + } + } + + public char Identifier + { + get => (char) (BlockEngine.GetBlockInfo(Id).objectId + 'A'); + set + { + BlockEngine.GetBlockInfo(Id).objectId = (byte) (value - 'A'); + Label = value + ""; //The label isn't updated automatically + } + } + + /// + /// Finds the identfier blocks with the given ID. + /// + /// The ID to look for + /// An array that may be empty + public static ObjectIdentifier[] GetByID(char id) => BlockEngine.GetObjectIDsFromID((byte) (id - 'A')); + } +} \ No newline at end of file diff --git a/GamecraftModdingAPI/SimBody.cs b/GamecraftModdingAPI/SimBody.cs index e6d1c68..f38df01 100644 --- a/GamecraftModdingAPI/SimBody.cs +++ b/GamecraftModdingAPI/SimBody.cs @@ -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 /// /// Whether the body can be moved or static /// - public bool Static - { - get => Block.BlockEngine.GetBlockInfo(Id).isStatic; - set => Block.BlockEngine.GetBlockInfo(Id).isStatic = value; - } + public bool Static => Block.BlockEngine.GetBlockInfo(Id).isStatic; + //Setting it doesn't have any effect private ref RigidBodyEntityStruct GetStruct() { return ref Block.BlockEngine.GetBlockInfo(Id); } + + public override string ToString() + { + return $"{nameof(Id)}: {Id}, {nameof(Position)}: {Position}, {nameof(Mass)}: {Mass}, {nameof(Static)}: {Static}"; + } + + /// + /// 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. + /// + /// The alphabetical ID + /// An array that may be empty + public static SimBody[] GetFromObjectID(char id) => Block.BlockEngine.GetSimBodiesFromID((byte) (id - 'A')); } } \ No newline at end of file diff --git a/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs b/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs index b662dd7..1342eae 100644 --- a/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs +++ b/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs @@ -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(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()) {