[Solved] Disguised Block Data

Hello Everyone,

I would like to know if it would be possible to disguise any block e.g. sand, with any block texture e.g. chest. If so, how would I add the disguise to the sand block code below. Thanks!

BlockState sand = BlockState.builder().blockType(BlockTypes.SAND).build();

At this stage in the API apart from sending fake block changes to the client this isn’t currently possible.

Maybe if you explain more what you are trying to do, we can offer some suggestions.

1 Like

I would like to create a special sand block disguised as a chest. Once this is done, I would set a location where this special block would fall. On impact, it would delete itself and spawn random mobs in it’s place.

Why do you even need it to be a chest, if you are just going to have it delete itself as soon as it impacts?

If the result you want is something to fall from the sky and land on the surface, as a sand block would, to identify the top block on the surface, then you don’t need it to be a chest, just use the sand block – and even then if its a matter of "I have a coordinate location, I want to drop something from a height in order to determine the block that it would land on from the top of the map /starting at an arbitrary high value, with the only interest being to identify the point that a falling block WOULD land on, you can check the block lighting properties of locations within that column to find the point where it decreases. But you could just spawn sand in the air and let it fall and land to find that position…

If the effect you are after is ‘a falling chest, visible to someone for a few seconds before it hits the ground’ you can actually just create a falling chest. All blocks in the game can be turned into falling-entities, and fall as a sand block would (which auto-converts them into fixed-position blocks when they land). No need to disguise it, the chest just turns into a block that is impacted by gravity…
You would need to first create a chest block at a given height, given location. Then you spawn a falling block entity form of the chest at the exact same location – falling block entities require a blockstate at a location to match the blockstate used for the falling entity, or else it glitches out and doesn’t work. The server removes the block as the entity is spawned, and the falling commences.

Either spawning sand in the air, and letting it turn itself into falling sand, or spawning a block+fallingblock in the air, a falling-block entity is what does the falling. When the block hits the ground and solidifies, a ChangeBlockEvent.Place, root cause instanceof FallingBlockEntity event is thrown. You could listen for that event, cancel/remove the transaction if the location x/z matches a spawned one (or if its the only way your server will have falling chest blocks, respond to all falling block chest blocks), grab the location, and pass that into your mob spawning system.

Note: Falling blocks need to be spawned at 0.5/0.5 coordinates so that the block lands solidly. If it is offset, or with a motion vector that displaces it, when it lands, the results are inconsistant: if it lands on a flat plane, it will slide into a nearby available coordinate, if it lands where there is an edge, it will be destroyed or slide down into the lower position depending on which x or z axis is where the bulk of it lays, and how much is over the center line, in ways which basically appear random and inconsistant. 0.5/0.5 spawn positions, and you have zero problems.

1 Like

The effect that I was looking for was a falling chest. I did not know that the keys of a sand block could be implemented to a chest block.

I looked at the code provided in the “FallingBlock Behaving Oddly” topic page, and I was able to modify Socratic_Phoenix’s code for my purpose. It’s identical, except that instead of using the block under the user as a BlockState object, I tried using a chest, but when I executed the code, the chest does not appear.

    World world = ((Player) src).getWorld();
    Vector3i location = ((Player) src).getLocation().getPosition().toInt();
    Optional<Entity> entityOptional = world.createEntity(EntityTypes.FALLING_BLOCK, location.toDouble().add(0.5, 10, 0.5));
    FallingBlock block = (FallingBlock) entityOptional.get();
    
    BlockState blockState = BlockState.builder().blockType(BlockTypes.CHEST).build();
    block.offer(Keys.CAN_PLACE_AS_BLOCK, true);
    block.offer(Keys.CAN_DROP_AS_ITEM, true);
    block.offer(Keys.FALL_TIME, 120);
    block.offer(Keys.FALLING_BLOCK_STATE, blockState);
    
    world.spawnEntity(block, Cause.of(NamedCause.source(SpawnCause.builder().type(SpawnTypes.PLUGIN).build())));

PS: I don’t know how to properly site another topic’s code.

Update: I changed the CAN_PLACE_AS_BLOCK and the CAN_DROP_AS_ITEM keys to false, and it made the chest appear on the surface it should land on, but not in the air.

Create a FallingBlock entity, get the FallingBlockData from it, set the BlockState on the data, set the boolean for canPlaceAsBlock to false, set the canDropItem to false, set the data back to the FallingBlock entity, and then spawn it into the world with your custom cause. Quite possibly, you’ll need to listen to the destruct event or something thereof to spawn the mobs after it lands on the ground.

1 Like

Just to note here, canPlaceAsBlock currently does not work as expected

1 Like