Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Setting blockstate on java server doesn't update on geyser until chunk reloads #4625

Open
Karltroid opened this issue May 3, 2024 · 12 comments
Labels
Confirmed Bug The bug reported is confirmed and able to be replicated.

Comments

@Karltroid
Copy link

Karltroid commented May 3, 2024

Describe the bug

In the plugin I am making for my server I am setting the facing direction of a shulker box when placed. This works on java edition as expected but the block state remains default (UP) on bedrock edition until the bedrock client reloads the chunk (leaving and coming back or relogging).

To Reproduce

  1. Make a plugin that sets the facing direction of a shulkerbox (or any block with a facing property).
  2. View this change in real time on a java and geyser client, it will update on java but not on bedrock.

Expected behaviour

Updating blockstate on geyser client when its updated on java.

Screenshots / Videos

image

Server Version and Plugins

No response

Geyser Dump

DUMP

Geyser Version

2.3.0

Minecraft: Bedrock Edition Device/Version

v1.20.81

Additional Context

No response

@Karltroid
Copy link
Author

Karltroid commented May 3, 2024

image
I don't know if this stems from the same issue or bedrock just handles blockstates differently, but it seems to ignore me setting stair nbt to straight instead of corner as well.

Difference with the stairs in particular is that reloading chunks doesn't fix the issue

@Karltroid
Copy link
Author

Karltroid commented May 3, 2024

image
Here is proof showing the shulker facing block state fixes after reloading the chunk

@Camotoy
Copy link
Member

Camotoy commented May 3, 2024

Please update to the latest version (and install ViaVersion as well) and re-test this and provide a Geyser dump. Thanks!

@Camotoy Camotoy added the Waiting On Response When an issue or PR is waiting on a response from a [specific] person. label May 3, 2024
@Karltroid
Copy link
Author

https://dump.geysermc.org/CAVfs9mo8A92a7vJASKQdDRKsu7C9FSi

Paper: 1.20.4 # 496
Geyser: 2.3.0
ViaVersion: 4.10.0

Same issue persists after updating everything

@Camotoy Camotoy removed the Waiting On Response When an issue or PR is waiting on a response from a [specific] person. label May 3, 2024
@Karltroid
Copy link
Author

For context, this is the code on my spigot plugin that is setting the block state of the shulker

private void convertToFatChest(Block block, Material fatChestType, BlockFace facing)
{
    if (!(block.getState() instanceof Container)) return;

    // save pre conversion container
    ItemStack[] containerContents = ((Container) block.getState()).getInventory().getContents();

    // convert container to desired chest type
    BlockData newFatChest = fatChestType.createBlockData();
    ((Directional) newFatChest).setFacing(facing);
    block.setBlockData(newFatChest);

    // load pre conversion container to new container
    ((Container) block.getState()).getInventory().setContents(containerContents);
}

@valaphee
Copy link
Contributor

When do you change the block state? As Vanilla always sends the block state on placing and interacting, and when you modify it there it might send two block state updates.

@Karltroid
Copy link
Author

When do you change the block state? As Vanilla always sends the block state on placing and interacting, and when you modify it there it might send two block state updates.

@EventHandler
public void onChestPlace(BlockPlaceEvent event) {

  // get if block representing a chest was placed
  Block placedBlock = event.getBlockPlaced();
  if (!placedBlock.getType().equals(GUI_CHEST)) return;
  
  // can't place chest in the middle of two chests
  List<Block> adjacentChests = getAdjacentChests(placedBlock);
  if (adjacentChests.size() > 1) {
	  event.setCancelled(true);
	  return;
  }
  
  // can't place adjacent chest next to double chest, if normal chest then create double chest!
  for (Block chest : adjacentChests) {
	  Material adjacentType = chest.getType();
	  if (isDoubleChest(adjacentType)) {
		  event.setCancelled(true);
		  return;
	  } else if (isSingleChest(adjacentType)) {
		  convertToDoubleChest(placedBlock, chest);
		  return;
	  }
  }
  
  // not a double chest, make a single chest!
  if (adjacentChests.isEmpty()) convertToFatChest(placedBlock, SINGLE_CHEST);
}

I am setting the placed block's block data right on BlockPlaceEvent

@Karltroid
Copy link
Author

Karltroid commented May 15, 2024

// not a double chest, make a single chest!
if (adjacentChests.isEmpty())
{
	convertToFatChest(placedBlock, SINGLE_CHEST);
	placedBlock.getState().update(true, true);
}

So by adding the forced state update it halfway fixes it. The fake chest is still facing upwards (default shulker state) but with the forced update it will correct its orientation when opened. So whatever is happening when the player opens the shulker needs to somehow be done on state update.

@Karltroid
Copy link
Author

2024-05-14.23-53-42.mp4

Heres a video of what I mean in my previous comment

@Karltroid
Copy link
Author

New discoveries:

  • even using vanilla commands to set a block to be a "fat chest" shulker box with a given direction (ex: east) the fat chest will have the same issue and face its default position (north/up) on bedrock's send until they open it like the vieo above.

  • FastAsyncWorldEdit CAN properly set a block with the wand and bedrock sees it perfectly fine, so however they are doing it seems to work with geyser.

@Karltroid
Copy link
Author

Got it working! Since using //set worked I decided to set the blockdata using Fawe/WorldEdit's API in my plugin and worked like a charm!

private void convertToFatChest(Block block, Material fatChestType) {

    // save pre conversion container
    ItemStack[] containerContents = new ItemStack[0];
    if ((block.getState() instanceof Container))
        containerContents = ((Container) block.getState()).getInventory().getContents();

    // convert container to desired chest type
    BlockFace facing = ((Directional) block.getBlockData()).getFacing();
    BlockData fatChest = fatChestType.createBlockData();
    ((Directional) fatChest).setFacing(facing);

    // convert block data to World Edit API and set block via said API
    try (EditSession editSession = WorldEdit.getInstance().newEditSession(FaweAPI.getWorld(block.getWorld().getName()))) {
        com.sk89q.worldedit.world.block.BlockState fatChestFAWE = BukkitAdapter.adapt(fatChest);
        editSession.setBlock(block.getX(), block.getY(), block.getZ(), fatChestFAWE);
    } catch (Exception e) {
        ModernBeta.log("An error occurred creating fat chest: " + e.getMessage());
    }

    // load pre conversion container to new container
    if (containerContents.length > 0) ((Container) block.getState()).getInventory().setContents(containerContents);
}

So this could be closed, but I think there still is an issue here, this is just a bandaid fix for me right now.

@Camotoy
Copy link
Member

Camotoy commented May 18, 2024

Working with refactoring our block code, I think I know what's going on. I don't know the best way to fix it globally, though, but just for shulkers is likely doable.

Shulker box direction is part of the block entity in Bedrock. However, we only update the block entity if a Java block entity packet is sent. Because the Bedrock block state doesn't have a direction, we just send a block update packet with no changes.
We already have a similar mitigation in place for double chests.

@onebeastchris onebeastchris added the Confirmed Bug The bug reported is confirmed and able to be replicated. label May 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Confirmed Bug The bug reported is confirmed and able to be replicated.
Projects
None yet
Development

No branches or pull requests

4 participants