diff --git a/clients/packages/contracts/src/components/BlockMetadataComponent.sol b/clients/packages/contracts/src/components/BlockMetadataComponent.sol index 91377ed..782cc3b 100644 --- a/clients/packages/contracts/src/components/BlockMetadataComponent.sol +++ b/clients/packages/contracts/src/components/BlockMetadataComponent.sol @@ -16,22 +16,23 @@ contract BlockMetadataComponent is BareComponent { keys[0] = "blockFace"; values[0] = LibTypes.SchemaValue.UINT8; - keys[1] = "blockType"; - values[1] = LibTypes.SchemaValue.UINT256; + // TODO: find some way to convert the blockType to a uint256 to save space + keys[1] = "material"; + values[1] = LibTypes.SchemaValue.STRING; } - function set(uint256 entity, BlockFace blockFace, uint256 blockType) public { - set(entity, abi.encode(uint8(blockFace), blockType)); + function set(uint256 entity, BlockFace blockFace, string memory material) public { + set(entity, abi.encode(uint8(blockFace), material)); } function getBlockFace(uint256 entity) public view returns (BlockFace) { - (uint8 blockFace, uint256 blockType) = abi.decode(getRawValue(entity), (uint8, uint256)); + (uint8 blockFace, string memory material) = abi.decode(getRawValue(entity), (uint8, string)); return BlockFace(blockFace); } - function getBlockType(uint256 entity) public view returns (uint256) { - (uint8 blockFace, uint256 blockType) = abi.decode(getRawValue(entity), (uint8, uint256)); - return blockType; + function getMaterial(uint256 entity) public view returns (string memory) { + (uint8 blockFace, string memory material) = abi.decode(getRawValue(entity), (uint8, string)); + return material; } } diff --git a/clients/packages/contracts/src/systems/RegisterCreationSystem.sol b/clients/packages/contracts/src/systems/RegisterCreationSystem.sol index 1c6f116..6a3e5ad 100644 --- a/clients/packages/contracts/src/systems/RegisterCreationSystem.sol +++ b/clients/packages/contracts/src/systems/RegisterCreationSystem.sol @@ -41,7 +41,7 @@ contract RegisterCreationSystem is System { OpcBlock memory repositionedOpcBlock = repositionedOpcBlocks[i]; positionComponent.set(blockEntityId, repositionedOpcBlock.relativeCoord); - blockMetadataComponent.set(blockEntityId, repositionedOpcBlock.blockFace, repositionedOpcBlock.blockType); + blockMetadataComponent.set(blockEntityId, repositionedOpcBlock.blockFace, repositionedOpcBlock.material); blocksComponent.addBlock(creationEntityId, blockEntityId); } @@ -75,7 +75,7 @@ contract RegisterCreationSystem is System { for (uint32 i = 0; i < opcBlocks.length; i++) { OpcBlock memory opcBlock = opcBlocks[i]; VoxelCoord memory newRelativeCoord = VoxelCoord(opcBlock.relativeCoord.x - lowestX, opcBlock.relativeCoord.y - lowestY, opcBlock.relativeCoord.z - lowestZ); - repositionedOpcBlocks[i] = OpcBlock(newRelativeCoord, opcBlock.blockFace, opcBlock.blockType); + repositionedOpcBlocks[i] = OpcBlock(newRelativeCoord, opcBlock.blockFace, opcBlock.material); } return repositionedOpcBlocks; } diff --git a/clients/packages/contracts/src/test/systems/RegisterCreationSystem.t.sol b/clients/packages/contracts/src/test/systems/RegisterCreationSystem.t.sol index f332744..5913175 100644 --- a/clients/packages/contracts/src/test/systems/RegisterCreationSystem.t.sol +++ b/clients/packages/contracts/src/test/systems/RegisterCreationSystem.t.sol @@ -22,7 +22,7 @@ contract RegisterCreationTest is MudTest { VoxelCoord memory relativeCoord = VoxelCoord(getRandomNumber(), getRandomNumber(), getRandomNumber()); BlockFace blockFace = BlockFace.NORTH; OpcBlock[] memory opcBlocks = new OpcBlock[](1); - opcBlocks[0] = OpcBlock(relativeCoord, blockFace, 2); + opcBlocks[0] = OpcBlock(relativeCoord, blockFace, "SLIME_BLOCK"); uint256 creationEntityId = registerCreationSystem.executeTyped(opcBlocks); uint256[] memory blocks = blocksComponent.getValue(creationEntityId); diff --git a/clients/packages/contracts/src/types.sol b/clients/packages/contracts/src/types.sol index 4db328b..7572372 100644 --- a/clients/packages/contracts/src/types.sol +++ b/clients/packages/contracts/src/types.sol @@ -12,12 +12,12 @@ enum BlockFace { // BlockFace = the face of a block. These enum values were take SOUTH, EAST, WEST, - TOP, - BOTTOM + UP, + DOWN } struct OpcBlock { // OpcBlock = OPCraft block. we cannot use the word "Block" since it's a reserved keyword VoxelCoord relativeCoord; // these coords are relative to the lower-south-west corner of the creation BlockFace blockFace; - uint256 blockType; // search for this in the bukkit codebase to find the block type: NORTH((byte)0, (byte)0, (byte)-1, BlockFace.EnumAxis.Z), + string material; } \ No newline at end of file diff --git a/clients/packages/simulator-client/src/index.ts b/clients/packages/simulator-client/src/index.ts index 4f8ee87..12fcd4d 100644 --- a/clients/packages/simulator-client/src/index.ts +++ b/clients/packages/simulator-client/src/index.ts @@ -4,7 +4,11 @@ import { SystemTypes } from "contracts/types/SystemTypes"; import { SystemAbis } from "contracts/types/SystemAbis.mjs"; import {config, getNetworkConfig} from "./config"; import { defineActivatedCreationsComponent } from "./components/ActivatedCreationsComponent"; -import {OpcBlockStruct, VoxelCoordStruct} from "contracts/types/ethers-contracts/RegisterCreationSystem"; +import { + OpcBlockStruct, + VoxelCoordStruct, + VoxelCoordStructOutput +} from "contracts/types/ethers-contracts/RegisterCreationSystem"; import {defineBlocksComponent} from "./components/BlocksComponent"; // The world contains references to all entities, all components and disposers. @@ -19,30 +23,96 @@ const components = { BlocksComponent: defineBlocksComponent(world), }; + const SIMULATOR_API_SERVER = "http://localhost:4500"; // Components expose a stream that triggers when the component is updated. -components.ActivatedCreationsComponent.update$.subscribe(({ value }) => { - console.log("activated creations"); - console.log(value); - fetch(SIMULATOR_API_SERVER).then((res) => { - console.log(`Simulated creation response=${res}`); - }).catch((err) => { - console.log(`Cannot simulate creation err=${err}`) - }); +components.ActivatedCreationsComponent.update$.subscribe(( res ) => { + const ownerId = res.entity; + const activatedCreations = res.value?.[0]?.value; + if(!activatedCreations || activatedCreations.length === 0) { + console.log("couldn't activate creations since we couldn't find the activated creationId") + return; + } + const activatedCreationId:any = activatedCreations.at(-1); // right now, we are assuming tha tthe last element in the array is the one they just activated + // TODO: get the blocks of the creation + // @ts-ignore + const creationBlocks = components.BlocksComponent.values[activatedCreationId]; + console.log("creation blocks"); + console.log(creationBlocks); + for(const block of creationBlocks) { + block.blockFace = blockFaceToString(block.blockFace); + } + console.log(creationBlocks); + + // console.log(value); + // console.log(String(value?.[0]?.value)); + // TODO: for now, you can only activate each creation once + const payload = { + worldName: 'exampleWorld', + ownerPlayerId: ownerId, + blocks: creationBlocks, + creationId: activatedCreationId, + }; + + // fetch(SIMULATOR_API_SERVER, { + // method: 'POST', + // headers: { + // 'Content-Type': 'application/json' + // }, + // body: JSON.stringify(payload) + // }).then((res) => { + // console.log(`Simulated creation response=${res}`); + // }).catch((err) => { + // console.log(`Cannot simulate creation err=${err}`) + // }); }); + +// updates return res, which is: { +// entity: (the entity Id) +// value: [new state, old state] (I think it's the old state) +// component: (has a reference to all key-> value pairs of that component +// } +// where newState and old state is { +// value: +// } +// This is why if we just want to get the latest value, we use: String(value?.[0]?.value) // we don't need faucets to drip cause we are just an observer -components.BlocksComponent.update$.subscribe(({ value }) => { - console.log("activated creations"); - console.log(value); - fetch(SIMULATOR_API_SERVER).then((res) => { - console.log(`Simulated creation response=${res}`); - }).catch((err) => { - console.log(`Cannot simulate creation err=${err}`) - }); +components.BlocksComponent.update$.subscribe(( res ) => { + const creationId = res.entity; + console.log(`registered creation WITH ID=${creationId}`); }); -const createOpcBlock = (x:number,y:number,z:number,face:number,type:number):OpcBlockStruct => { +// TODO: fix this so it's less sus +enum BlockFace { // the must be manually kept up-to-date with the solidity enum + NORTH, + SOUTH, + EAST, + WEST, + UP, + DOWN, + NONE, +} + +const blockFaceToString = (face:BlockFace):string => { + switch(face) { + case BlockFace.NORTH: + return "NORTH"; + case BlockFace.SOUTH: + return "SOUTH"; + case BlockFace.EAST: + return "EAST"; + case BlockFace.WEST: + return "WEST"; + case BlockFace.UP: + return "UP"; + case BlockFace.DOWN: + return "DOWN"; + case BlockFace.NONE: + return "NONE"; + } +} +const createOpcBlock = (x:number,y:number,z:number, face:BlockFace, material:string):OpcBlockStruct => { return { relativeCoord: { x: x, @@ -50,7 +120,7 @@ const createOpcBlock = (x:number,y:number,z:number,face:number,type:number):OpcB z: z, } as VoxelCoordStruct, blockFace: face, - blockType: type, + material: material, } as OpcBlockStruct; } @@ -61,13 +131,12 @@ setupMUDNetwork(config, world, components, Syste }).then( ({ startSync, systems }) => { - // why is systems an empty object here? + // why is systems an empty object here? It just takes a bit of time to initialize startSync(); const blocks = [ - createOpcBlock(0,0,0, 0,5), - createOpcBlock(0,1,0, 0,6), - createOpcBlock(0,0,4, 0,10), + createOpcBlock(0,0,0, BlockFace.NONE,"SLIME_BLOCK"), + createOpcBlock(0,0,1, BlockFace.NORTH, "STICKY_PISTON"), ]; // debugger // interesting, the systems object is not available until later @@ -77,17 +146,29 @@ setupMUDNetwork(config, world, components, Syste blocks,{ gasLimit: 100_000_000 } ).then(res => { // this res is a confirmation the contract was sent - console.log(`creationId`); - console.log(res); - res.wait().then((receipt) => { + // console.log(`creationId`); + // console.log(res); + res.wait(3).then((receipt) => { // this is the actual result of the contract - console.log("receipt"); - console.log(receipt); + // console.log("receipt"); + // console.log(receipt); }).catch(err => { - console.log("error!"); - console.log(err); + // console.log("error!"); + // console.log(err); }) ; }); } + + (window as any).activateCreation = () => { + systems["system.ActivateCreation"].executeTyped( + "asdfasdf", + { + x:0, + y:0, + z:0, + }, + { gasLimit: 100_000_000 } + ); + } } ); diff --git a/mc-simulator-in-tee/simulator-plugin/src/main/java/net/tenet/simulatorplugin/ActivateCreationHandler.java b/mc-simulator-in-tee/simulator-plugin/src/main/java/net/tenet/simulatorplugin/ActivateCreationHandler.java index 2250814..fa178c3 100644 --- a/mc-simulator-in-tee/simulator-plugin/src/main/java/net/tenet/simulatorplugin/ActivateCreationHandler.java +++ b/mc-simulator-in-tee/simulator-plugin/src/main/java/net/tenet/simulatorplugin/ActivateCreationHandler.java @@ -7,6 +7,10 @@ import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.World; +import org.bukkit.block.BlockState; +import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.type.Piston; +import org.bukkit.block.data.type.PistonHead; import org.bukkit.plugin.Plugin; import java.io.BufferedReader; @@ -110,17 +114,47 @@ private void setCreation(Creation creation) throws IllegalArgumentException { World world = Bukkit.getWorlds().get(0); // Assuming overwriting chunks in the main world Bukkit.getScheduler().runTask(pluginReference, () -> { for (Block block : creation.blocks) { - Material material = Material.matchMaterial(block.blockMaterial); + Material material = Material.matchMaterial(block.material); if (material == null) { - throw new IllegalArgumentException("Invalid material " + block.blockMaterial); + throw new IllegalArgumentException("Invalid material " + block.material); + } + org.bukkit.block.Block blockInWorld = world.getBlockAt(block.x, block.y, block.z); + blockInWorld.setType(material, true); + BlockState blockState = blockInWorld.getState(); + BlockData blockdata = blockState.getBlockData(); + if (material == Material.PISTON) { + ((Piston) blockdata).setFacing(stringToBlockFace(block.blockFace)); + blockState.setBlockData(blockdata); + blockState.update(); + } else if (material == Material.PISTON_HEAD) { + ((PistonHead) blockInWorld).setFacing(stringToBlockFace(block.blockFace)); + blockState.setBlockData(blockdata); + blockState.update(); } - world.getBlockAt(block.x, block.y, block.z).setType(material, true); } }); } + private org.bukkit.block.BlockFace stringToBlockFace(String blockFaceStr) { + switch (blockFaceStr.toUpperCase()) { + case "NORTH": + return org.bukkit.block.BlockFace.NORTH; + case "EAST": + return org.bukkit.block.BlockFace.EAST; + case "SOUTH": + return org.bukkit.block.BlockFace.SOUTH; + case "WEST": + return org.bukkit.block.BlockFace.WEST; + case "UP": + return org.bukkit.block.BlockFace.UP; + case "DOWN": + return org.bukkit.block.BlockFace.DOWN; + } + throw new IllegalArgumentException("Invalid block face " + blockFaceStr); + } + private boolean creationHasStorageBlocks(Creation creation) { - return Arrays.stream(creation.blocks).anyMatch(block -> block.blockMaterial.equalsIgnoreCase("chest")); + return Arrays.stream(creation.blocks).anyMatch(block -> block.material.equalsIgnoreCase("chest")); } // Why can't we just iterate across all the blocks in the creation and set them to air? diff --git a/mc-simulator-in-tee/simulator-plugin/src/main/java/net/tenet/simulatorplugin/Block.java b/mc-simulator-in-tee/simulator-plugin/src/main/java/net/tenet/simulatorplugin/Block.java index 3430092..a5af795 100644 --- a/mc-simulator-in-tee/simulator-plugin/src/main/java/net/tenet/simulatorplugin/Block.java +++ b/mc-simulator-in-tee/simulator-plugin/src/main/java/net/tenet/simulatorplugin/Block.java @@ -1,7 +1,8 @@ package net.tenet.simulatorplugin; public class Block { - String blockMaterial; + String material; + String blockFace; int x; int y; int z; diff --git a/mc-simulator-in-tee/tests/set-blocks.sh b/mc-simulator-in-tee/tests/set-blocks.sh index 5156574..c796670 100644 --- a/mc-simulator-in-tee/tests/set-blocks.sh +++ b/mc-simulator-in-tee/tests/set-blocks.sh @@ -1,3 +1,3 @@ #!/bin/sh -curl -X POST -H "Content-Type: application/json" -d ' { "worldName": "exampleWorld", "ownerPlayerId": "12345", "blocks": [ { "blockMaterial": "stone", "x": 1, "y": 1, "z": 1 }, { "blockMaterial": "chest", "x": -1, "y": -1, "z": -1 } ], "creationId": "hi" }' http://localhost:4500/activate-creation +curl -X POST -H "Content-Type: application/json" -d ' { "worldName": "exampleWorld", "ownerPlayerId": "12345", "blocks": [ { "material": "stone", "x": 1, "y": 1, "z": 1 }, { "material": "chest", "x": -1, "y": -1, "z": -1 }, { "material": "piston", "x": 3, "y": 5, "z": -1, blockFace: "UP" } ], "creationId": "hi" }' http://localhost:4500/activate-creation