From ff57a16565b1e91685c9182b6be0664c4a94ec54 Mon Sep 17 00:00:00 2001 From: NorbiPeti Date: Wed, 13 May 2020 14:02:36 +0200 Subject: [PATCH] Create Block class with existing functionality Placement, movement, rotation, removal Block looked at (in Player class), connected blocks --- GamecraftModdingAPI/Block.cs | 115 ++++++++++++++++++ GamecraftModdingAPI/Blocks/BlockEngine.cs | 39 ++++++ GamecraftModdingAPI/Blocks/BlockUtility.cs | 31 ----- GamecraftModdingAPI/Blocks/Movement.cs | 61 ---------- GamecraftModdingAPI/Blocks/MovementEngine.cs | 20 ++- GamecraftModdingAPI/Blocks/Placement.cs | 55 --------- GamecraftModdingAPI/Blocks/PlacementEngine.cs | 6 +- GamecraftModdingAPI/Blocks/Removal.cs | 28 ----- GamecraftModdingAPI/Blocks/Rotation.cs | 59 --------- GamecraftModdingAPI/Blocks/RotationEngine.cs | 7 +- GamecraftModdingAPI/Main.cs | 8 +- GamecraftModdingAPI/Player.cs | 12 ++ GamecraftModdingAPI/Players/PlayerEngine.cs | 21 ++++ .../Tests/GamecraftModdingAPIPluginTest.cs | 24 ++-- 14 files changed, 218 insertions(+), 268 deletions(-) create mode 100644 GamecraftModdingAPI/Block.cs create mode 100644 GamecraftModdingAPI/Blocks/BlockEngine.cs delete mode 100644 GamecraftModdingAPI/Blocks/BlockUtility.cs delete mode 100644 GamecraftModdingAPI/Blocks/Movement.cs delete mode 100644 GamecraftModdingAPI/Blocks/Placement.cs delete mode 100644 GamecraftModdingAPI/Blocks/Removal.cs delete mode 100644 GamecraftModdingAPI/Blocks/Rotation.cs diff --git a/GamecraftModdingAPI/Block.cs b/GamecraftModdingAPI/Block.cs new file mode 100644 index 0000000..d099aba --- /dev/null +++ b/GamecraftModdingAPI/Block.cs @@ -0,0 +1,115 @@ +using System; +using System.Collections.Generic; +using GamecraftModdingAPI.Blocks; +using GamecraftModdingAPI.Utility; +using RobocraftX.Common; +using Svelto.ECS; +using Unity.Mathematics; + +namespace GamecraftModdingAPI +{ + public class Block + { + private static readonly PlacementEngine PlacementEngine = new PlacementEngine(); + private static readonly MovementEngine MovementEngine = new MovementEngine(); + private static readonly RotationEngine RotationEngine = new RotationEngine(); + private static readonly RemovalEngine RemovalEngine = new RemovalEngine(); + private static readonly BlockEngine BlockEngine = new BlockEngine(); + + /// + /// Place a new block at the given position. If scaled, position means the center of the block. The default block size is 0.2 in terms of position. + /// Place blocks next to each other to connect them. + /// The placed block will be a complete block with a placement grid and collision which will be saved along with the game. + /// + /// The block's type + /// The block's color + /// The block color's darkness (0-9) - 0 is default color + /// The block's position in the grid - default block size is 0.2 + /// The block's rotation in degrees + /// The block's uniform scale - default scale is 1 (with 0.2 width) + /// The block's non-uniform scale - 0 means is used + /// The player who placed the block + /// The placed block or null if failed + public static Block PlaceNew(BlockIDs block, float3 position, + float3 rotation = default, BlockColors color = BlockColors.Default, byte darkness = 0, + int uscale = 1, float3 scale = default, Player player = null) + { + if (PlacementEngine.IsInGame && GameState.IsBuildMode()) + { + try + { + return new Block(PlacementEngine.PlaceBlock(block, color, darkness, + position, uscale, scale, player, rotation)); + } + catch (Exception e) + { + Logging.MetaDebugLog(e); + } + } + + return null; + } + + /// + /// Returns the most recently placed block. + /// + /// The block object + public static Block GetLastPlacedBlock() + { + return new Block(BlockIdentifiers.LatestBlockID); + } + + public Block(EGID id) + { + Id = id; + } + + public Block(uint id) + { + Id = new EGID(id, CommonExclusiveGroups.OWNED_BLOCKS_GROUP); + } + + public EGID Id { get; } + + /// + /// The block's current position. + /// + public float3 Position + { + get => MovementEngine.GetPosition(Id.entityID); + set => MovementEngine.MoveBlock(Id.entityID, value); + } + + /// + /// Returns an array of blocks that are connected to this one. + /// + public Block[] ConnectedCubes => BlockEngine.GetConnectedBlocks(Id.entityID); + + /// + /// The block's current rotation in degrees. + /// + public float3 Rotation + { + get => RotationEngine.GetRotation(Id.entityID); + set => RotationEngine.RotateBlock(Id.entityID, value); + } + + /// + /// Removes this block. + /// + /// True if the block exists and could be removed. + public bool Remove() + { + return RemovalEngine.RemoveBlock(Id); + } + + public static void Init() + { + GameEngineManager.AddGameEngine(PlacementEngine); + GameEngineManager.AddGameEngine(MovementEngine); + GameEngineManager.AddGameEngine(RotationEngine); + GameEngineManager.AddGameEngine(RemovalEngine); + GameEngineManager.AddGameEngine(BlockEngine); + } + } +} \ No newline at end of file diff --git a/GamecraftModdingAPI/Blocks/BlockEngine.cs b/GamecraftModdingAPI/Blocks/BlockEngine.cs new file mode 100644 index 0000000..ad2af1b --- /dev/null +++ b/GamecraftModdingAPI/Blocks/BlockEngine.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; +using GamecraftModdingAPI.Engines; +using RobocraftX.Blocks; +using RobocraftX.Common; +using Svelto.DataStructures; +using Svelto.ECS; +using Svelto.ECS.EntityStructs; +using Unity.Mathematics; + +namespace GamecraftModdingAPI.Blocks +{ + public class BlockEngine : IApiEngine + { + public string Name { get; } = "GamecraftModdingAPIBlockGameEngine"; + + public EntitiesDB entitiesDB { set; private get; } + + public bool isRemovable => false; + + public void Dispose() + { + } + + public void Ready() + { + } + + public Block[] GetConnectedBlocks(uint blockID) + { + Stack cubeStack = new Stack(); + FasterList cubesToProcess = new FasterList(); + ConnectedCubesUtility.TreeTraversal.GetConnectedCubes(entitiesDB, blockID, cubeStack, cubesToProcess, (in GridConnectionsEntityStruct g) => { return false; }); + var ret = new Block[cubesToProcess.count]; + for (int i = 0; i < cubesToProcess.count; i++) + ret[i] = new Block(cubesToProcess[i]); + return ret; + } + } +} \ No newline at end of file diff --git a/GamecraftModdingAPI/Blocks/BlockUtility.cs b/GamecraftModdingAPI/Blocks/BlockUtility.cs deleted file mode 100644 index 342ee73..0000000 --- a/GamecraftModdingAPI/Blocks/BlockUtility.cs +++ /dev/null @@ -1,31 +0,0 @@ -using RobocraftX.Blocks.Ghost; -using RobocraftX.Character.Camera; -using RobocraftX.Character.Factories; -using Svelto.ECS; - -namespace GamecraftModdingAPI.Blocks -{ - public class BlockUtility - { - /// - /// Returns the block the player is currently looking at. - /// - /// The player's ID - /// The entities DB - /// The maximum distance from the player (default is the player's building reach) - /// The block's EGID or null if not found - public static EGID? GetBlockLookedAt(uint playerId, EntitiesDB entitiesDB, float maxDistance = -1f) - { - if (!entitiesDB.TryQueryMappedEntities( - CameraExclusiveGroups.CameraGroup, out var mapper)) - return null; - mapper.TryGetEntity(playerId, out CharacterCameraRayCastEntityStruct rayCast); - float distance = maxDistance < 0 - ? GhostBlockUtils.GetBuildInteractionDistance(entitiesDB, rayCast) - : maxDistance; - if (rayCast.hit && rayCast.distance <= distance) - return rayCast.hitEgid; - return null; - } - } -} \ No newline at end of file diff --git a/GamecraftModdingAPI/Blocks/Movement.cs b/GamecraftModdingAPI/Blocks/Movement.cs deleted file mode 100644 index 28575a9..0000000 --- a/GamecraftModdingAPI/Blocks/Movement.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -using Unity.Mathematics; - -namespace GamecraftModdingAPI.Blocks -{ - /// - /// Common block movement operations. - /// The functionality of this class only works in build mode. - /// - public static class Movement - { - private static MovementEngine movementEngine = new MovementEngine(); - - /// - /// Move a single block by a specific (x,y,z) amount (offset). - /// The moved block will remain connected to the blocks it was touching before it was moved. - /// The block's placement grid and collision box are also moved. - /// - /// The block's id - /// The movement amount (x,y,z) - /// Whether the operation was successful - public static bool MoveBlock(uint id, float3 vector) - { - if (movementEngine.IsInGame && GamecraftModdingAPI.Utility.GameState.IsBuildMode()) - { - movementEngine.MoveBlock(id, vector); - return true; - } - return false; - } - - /// - /// Move all connected blocks by a specific (x,y,z) amount (offset). - /// The moved blocks will remain connected to the block they're touching. - /// All of the block's placement grids and collision boxes are also moved. - /// This is equivalent to calling MoveBlock() for every connected block. - /// - /// The starting block's id - /// The movement amount (x,y,z) - /// Whether the operation was successful - public static bool MoveConnectedBlocks(uint id, float3 vector) - { - if (movementEngine.IsInGame && GamecraftModdingAPI.Utility.GameState.IsBuildMode()) - { - movementEngine.MoveConnectedBlocks(id, vector); - return true; - } - return false; - } - - public static void Init() - { - GamecraftModdingAPI.Utility.GameEngineManager.AddGameEngine(movementEngine); - } - } -} diff --git a/GamecraftModdingAPI/Blocks/MovementEngine.cs b/GamecraftModdingAPI/Blocks/MovementEngine.cs index fbeea99..6615949 100644 --- a/GamecraftModdingAPI/Blocks/MovementEngine.cs +++ b/GamecraftModdingAPI/Blocks/MovementEngine.cs @@ -57,30 +57,24 @@ namespace GamecraftModdingAPI.Blocks ref LocalTransformEntityStruct transStruct = ref this.entitiesDB.QueryEntity(blockID, CommonExclusiveGroups.OWNED_BLOCKS_GROUP); ref UECSPhysicsEntityStruct phyStruct = ref this.entitiesDB.QueryEntity(blockID, CommonExclusiveGroups.OWNED_BLOCKS_GROUP); // main (persistent) position - posStruct.position += vector; + posStruct.position = vector; // placement grid position - gridStruct.position += vector; + gridStruct.position = vector; // rendered position - transStruct.position += vector; + transStruct.position = vector; // collision position FullGameFields._physicsWorld.EntityManager.SetComponentData(phyStruct.uecsEntity, new Translation { Value = posStruct.position }); + entitiesDB.QueryEntity(blockID, CommonExclusiveGroups.OWNED_BLOCKS_GROUP).isProcessed = false; return posStruct.position; } - public float3 MoveConnectedBlocks(uint blockID, float3 vector) + public float3 GetPosition(uint blockID) { - Stack cubeStack = new Stack(); - FasterList cubesToMove = new FasterList(); - ConnectedCubesUtility.TreeTraversal.GetConnectedCubes(entitiesDB, blockID, cubeStack, cubesToMove, (in GridConnectionsEntityStruct g) => { return false; }); - for (int i = 0; i < cubesToMove.count; i++) - { - MoveBlock(cubesToMove[i], vector); - entitiesDB.QueryEntity(cubesToMove[i], CommonExclusiveGroups.OWNED_BLOCKS_GROUP).isProcessed = false; - } - return this.entitiesDB.QueryEntity(blockID, CommonExclusiveGroups.OWNED_BLOCKS_GROUP).position; + ref PositionEntityStruct posStruct = ref this.entitiesDB.QueryEntity(blockID, CommonExclusiveGroups.OWNED_BLOCKS_GROUP); + return posStruct.position; } } } diff --git a/GamecraftModdingAPI/Blocks/Placement.cs b/GamecraftModdingAPI/Blocks/Placement.cs deleted file mode 100644 index c029ebb..0000000 --- a/GamecraftModdingAPI/Blocks/Placement.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System; - -using Unity.Mathematics; -using Svelto.ECS; - -using GamecraftModdingAPI.Utility; - -namespace GamecraftModdingAPI.Blocks -{ - /// - /// Common block placement operations. - /// The functionality in this class is for build mode. - /// - public static class Placement - { - private static PlacementEngine placementEngine = new PlacementEngine(); - - /// - /// Place a new block at the given position. If scaled, position means the center of the block. The default block size is 0.2 in terms of position. - /// Place blocks next to each other to connect them. - /// The placed block will be a complete block with a placement grid and collision which will be saved along with the game. - /// - /// The block's type - /// The block's color - /// The block color's darkness (0-9) - 0 is default color - /// The block's position in the grid - default block size is 0.2 - /// The block's rotation in degrees - /// The block's uniform scale - default scale is 1 (with 0.2 width) - /// The block's non-uniform scale - 0 means is used - /// The player who placed the block - /// The placed block's ID or null if failed - public static EGID? PlaceBlock(BlockIDs block, float3 position, - float3 rotation = default, BlockColors color = BlockColors.Default, byte darkness = 0, - int uscale = 1, float3 scale = default, uint playerId = 0) - { - if (placementEngine.IsInGame && GameState.IsBuildMode()) - { - try - { - return placementEngine.PlaceBlock(block, color, darkness, position, uscale, scale, playerId, rotation); - } - catch (Exception e) - { - Logging.MetaDebugLog(e); - } - } - return null; - } - - public static void Init() - { - GameEngineManager.AddGameEngine(placementEngine); - } - } -} diff --git a/GamecraftModdingAPI/Blocks/PlacementEngine.cs b/GamecraftModdingAPI/Blocks/PlacementEngine.cs index 17f3314..d0a1192 100644 --- a/GamecraftModdingAPI/Blocks/PlacementEngine.cs +++ b/GamecraftModdingAPI/Blocks/PlacementEngine.cs @@ -22,6 +22,7 @@ using uREPL; using GamecraftModdingAPI.Utility; using GamecraftModdingAPI.Engines; +using GamecraftModdingAPI.Players; namespace GamecraftModdingAPI.Blocks { @@ -46,11 +47,12 @@ namespace GamecraftModdingAPI.Blocks private static BlockEntityFactory _blockEntityFactory; //Injected from PlaceBlockEngine public EGID PlaceBlock(BlockIDs block, BlockColors color, byte darkness, float3 position, int uscale, - float3 scale, uint playerId, float3 rotation) + float3 scale, Player player, float3 rotation) { //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 (darkness > 9) throw new Exception("That is too dark. Make sure to use 0-9 as darkness. (0 is default.)"); - return BuildBlock((ushort) block, (byte) (color + darkness * 10), position, uscale, scale, rotation, playerId); + return BuildBlock((ushort) block, (byte) (color + darkness * 10), position, uscale, scale, rotation, + (player ?? new Player(PlayerType.Local)).Id); } private EGID BuildBlock(ushort block, byte color, float3 position, int uscale, float3 scale, float3 rot, uint playerId) diff --git a/GamecraftModdingAPI/Blocks/Removal.cs b/GamecraftModdingAPI/Blocks/Removal.cs deleted file mode 100644 index 0bb54fb..0000000 --- a/GamecraftModdingAPI/Blocks/Removal.cs +++ /dev/null @@ -1,28 +0,0 @@ -using Svelto.ECS; - -using GamecraftModdingAPI.Utility; - -namespace GamecraftModdingAPI.Blocks -{ - public class Removal - { - private static RemovalEngine _removalEngine = new RemovalEngine(); - - /// - /// Removes the block with the given ID. Returns false if the block doesn't exist or the game isn't in build mode. - /// - /// The block to remove - /// Whether the block was successfully removed - public static bool RemoveBlock(EGID targetBlock) - { - if (GameState.IsBuildMode()) - return _removalEngine.RemoveBlock(targetBlock); - return false; - } - - public static void Init() - { - GameEngineManager.AddGameEngine(_removalEngine); - } - } -} \ No newline at end of file diff --git a/GamecraftModdingAPI/Blocks/Rotation.cs b/GamecraftModdingAPI/Blocks/Rotation.cs deleted file mode 100644 index b881cdb..0000000 --- a/GamecraftModdingAPI/Blocks/Rotation.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -using Unity.Mathematics; - -namespace GamecraftModdingAPI.Blocks -{ - /// - /// Common block rotation operations. - /// The functionality in this class is not completely implemented and will only work in build mode. - /// - public static class Rotation - { - private static RotationEngine rotationEngine = new RotationEngine(); - - /// - /// Rotate a single block by a specific amount in degrees. - /// This not destroy inter-block connections, so neighbouring blocks will remain attached despite appearances. - /// The cube placement grid and collision are also rotated. - /// - /// The block's id - /// The rotation amount around the x,y,z-axis - /// Whether the operation was successful - public static bool RotateBlock(uint id, float3 vector) - { - if (rotationEngine.IsInGame && GamecraftModdingAPI.Utility.GameState.IsBuildMode()) - { - rotationEngine.RotateBlock(id, vector); - return true; - } - return false; - } - - /// - /// Rotate all connected blocks by a specific amount in degrees. - /// This does not do anything because it has not been implemented. - /// - /// The starting block's id - /// The rotation around the x,y,z-axis - /// Whether the operation was successful - public static bool RotateConnectedBlocks(uint id, float3 vector) - { - if (rotationEngine.IsInGame && GamecraftModdingAPI.Utility.GameState.IsBuildMode()) - { - rotationEngine.RotateConnectedBlocks(id, vector); - return true; - } - return false; - } - - public static void Init() - { - GamecraftModdingAPI.Utility.GameEngineManager.AddGameEngine(rotationEngine); - } - } -} diff --git a/GamecraftModdingAPI/Blocks/RotationEngine.cs b/GamecraftModdingAPI/Blocks/RotationEngine.cs index d56994f..b295441 100644 --- a/GamecraftModdingAPI/Blocks/RotationEngine.cs +++ b/GamecraftModdingAPI/Blocks/RotationEngine.cs @@ -72,14 +72,15 @@ namespace GamecraftModdingAPI.Blocks { Value = rotStruct.rotation }); + entitiesDB.QueryEntity(blockID, CommonExclusiveGroups.OWNED_BLOCKS_GROUP).isProcessed = false; return ((Quaternion)rotStruct.rotation).eulerAngles; } - public float3 RotateConnectedBlocks(uint blockID, Vector3 vector) + public float3 GetRotation(uint blockID) { - // TODO: Implement and figure out the math - throw new NotImplementedException(); + ref RotationEntityStruct rotStruct = ref entitiesDB.QueryEntity(blockID, CommonExclusiveGroups.OWNED_BLOCKS_GROUP); + return ((Quaternion) rotStruct.rotation).eulerAngles; } } } diff --git a/GamecraftModdingAPI/Main.cs b/GamecraftModdingAPI/Main.cs index 4dced5e..ea5911f 100644 --- a/GamecraftModdingAPI/Main.cs +++ b/GamecraftModdingAPI/Main.cs @@ -9,7 +9,9 @@ using HarmonyLib; using GamecraftModdingAPI.Utility; using GamecraftModdingAPI.Events; +using GamecraftModdingAPI.Players; using GamecraftModdingAPI.Tasks; +using uREPL; namespace GamecraftModdingAPI { @@ -61,18 +63,16 @@ namespace GamecraftModdingAPI EventManager.AddEventEmitter(GameHostTransitionDeterministicGroupEnginePatch.simEngine); // init block implementors Logging.MetaDebugLog($"Initializing Blocks"); - Blocks.Movement.Init(); - Blocks.Rotation.Init(); Blocks.Signals.Init(); - Blocks.Placement.Init(); Blocks.Tweakable.Init(); - Blocks.Removal.Init(); // init inventory Inventory.Hotbar.Init(); // init input Input.FakeInput.Init(); // init object-oriented classes Player.Init(); + Block.Init(); + RuntimeCommands.Register("getblock", () => new Player(PlayerType.Local).GetBlockLookedAt()); Logging.MetaLog($"{currentAssembly.GetName().Name} v{currentAssembly.GetName().Version} initialized"); } diff --git a/GamecraftModdingAPI/Player.cs b/GamecraftModdingAPI/Player.cs index 996ea01..3f11cfb 100644 --- a/GamecraftModdingAPI/Player.cs +++ b/GamecraftModdingAPI/Player.cs @@ -218,6 +218,18 @@ namespace GamecraftModdingAPI } playerEngine.SetLocation(Id, location, exitSeat: exitSeat); } + + /// + /// Returns the block the player is currently looking at. + /// + /// The player's ID + /// The entities DB + /// The maximum distance from the player (default is the player's building reach) + /// The block's EGID or null if not found + public Block GetBlockLookedAt(float maxDistance = -1f) + { + return playerEngine.GetBlockLookedAt(Id, maxDistance); + } // internal methods diff --git a/GamecraftModdingAPI/Players/PlayerEngine.cs b/GamecraftModdingAPI/Players/PlayerEngine.cs index beef48a..d1df72e 100644 --- a/GamecraftModdingAPI/Players/PlayerEngine.cs +++ b/GamecraftModdingAPI/Players/PlayerEngine.cs @@ -11,6 +11,9 @@ using Unity.Mathematics; using Unity.Physics; using GamecraftModdingAPI.Engines; +using RobocraftX.Blocks.Ghost; +using RobocraftX.Character.Camera; +using RobocraftX.Character.Factories; namespace GamecraftModdingAPI.Players { @@ -234,5 +237,23 @@ namespace GamecraftModdingAPI.Players s = default; return false; } + + public Block GetBlockLookedAt(uint playerId, float maxDistance = -1f) + { + if (!entitiesDB.TryQueryMappedEntities( + CameraExclusiveGroups.CameraGroup, out var mapper)) + return null; + mapper.TryGetEntity(playerId, out CharacterCameraRayCastEntityStruct rayCast); + float distance = maxDistance < 0 + ? GhostBlockUtils.GetBuildInteractionDistance(entitiesDB, rayCast) + : maxDistance; + if (rayCast.hit && rayCast.distance <= distance) + { + Console.WriteLine("Hit block: " + rayCast.hitEgid); + return new Block(rayCast.hitEgid); + } + + return null; + } } } diff --git a/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs b/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs index 80cc916..5ea4965 100644 --- a/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs +++ b/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Reflection; using HarmonyLib; @@ -94,22 +95,21 @@ namespace GamecraftModdingAPI.Tests .Build(); CommandBuilder.Builder() - .Name("MoveLastBlock") - .Description("Move the most-recently-placed block, and any connected blocks by the given offset") - .Action((float x, float y, float z) => { - bool success = GamecraftModdingAPI.Blocks.Movement.MoveConnectedBlocks( - GamecraftModdingAPI.Blocks.BlockIdentifiers.LatestBlockID, - new Unity.Mathematics.float3(x, y, z)); - if (!success) - { - GamecraftModdingAPI.Utility.Logging.CommandLogError("Blocks can only be moved in Build mode!"); - } - }).Build(); + .Name("MoveLastBlock") + .Description("Move the most-recently-placed block, and any connected blocks by the given offset") + .Action((float x, float y, float z) => + { + if (GameState.IsBuildMode()) + foreach (var block in Block.GetLastPlacedBlock().ConnectedCubes) + block.Position += new Unity.Mathematics.float3(x, y, z); + else + GamecraftModdingAPI.Utility.Logging.CommandLogError("Blocks can only be moved in Build mode!"); + }).Build(); CommandBuilder.Builder() .Name("PlaceAluminium") .Description("Place a block of aluminium at the given coordinates") - .Action((float x, float y, float z) => { Blocks.Placement.PlaceBlock(Blocks.BlockIDs.AluminiumCube, new Unity.Mathematics.float3(x, y, z)); }) + .Action((float x, float y, float z) => { Block.PlaceNew(Blocks.BlockIDs.AluminiumCube, new Unity.Mathematics.float3(x, y, z)); }) .Build(); System.Random random = new System.Random(); // for command below