Skip to content

More efficient multi block updates#6307

Merged
onebeastchris merged 10 commits intoGeyserMC:masterfrom
valaphee:multi-block-change
Apr 26, 2026
Merged

More efficient multi block updates#6307
onebeastchris merged 10 commits intoGeyserMC:masterfrom
valaphee:multi-block-change

Conversation

@valaphee
Copy link
Copy Markdown
Member

@valaphee valaphee commented Apr 17, 2026

This PR aims to improve multi block updates, by not fanning out into up to 4096 block update packets and instead using a single UpdateSubChunkBlocksPacket.

Solves #6192

@valaphee valaphee marked this pull request as ready for review April 17, 2026 09:00
Copilot AI review requested due to automatic review settings April 17, 2026 09:00
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR targets the bulk Java ClientboundSectionBlocksUpdatePacket translation path to reduce packet fan-out by batching block changes into a single Bedrock UpdateSubChunkBlocksPacket, with some associated chunk-cache/prediction handling refactors.

Changes:

  • Reworks section multi-block update translation to build/send one UpdateSubChunkBlocksPacket instead of many per-block packets.
  • Adds chunk-section access helper in ChunkCache and adjusts how chunk-cache block updates are applied.
  • Refactors prediction removal logic in WorldCache (adds removePrediction).

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 6 comments.

File Description
core/src/main/java/org/geysermc/geyser/translator/protocol/java/level/JavaSectionBlocksUpdateTranslator.java Batches section updates into a single Bedrock subchunk update packet and changes cache/prediction handling.
core/src/main/java/org/geysermc/geyser/translator/protocol/java/JavaRecipeBookAddTranslator.java Comments out the translator annotation (disables translator registration).
core/src/main/java/org/geysermc/geyser/session/cache/WorldCache.java Simplifies prediction removal and introduces removePrediction.
core/src/main/java/org/geysermc/geyser/session/cache/ChunkCache.java Adds getChunkSection helper and changes updateBlock to use it (affecting palette allocation behavior).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread core/src/main/java/org/geysermc/geyser/session/cache/ChunkCache.java Outdated
@valaphee valaphee force-pushed the multi-block-change branch from e7be80c to 8d8978f Compare April 17, 2026 09:09
Copilot AI review requested due to automatic review settings April 17, 2026 09:14
@valaphee valaphee force-pushed the multi-block-change branch from 8d8978f to 6aecb95 Compare April 17, 2026 09:14
@valaphee valaphee marked this pull request as draft April 17, 2026 09:18
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@valaphee valaphee marked this pull request as ready for review April 17, 2026 09:22
Copilot AI review requested due to automatic review settings April 17, 2026 09:50
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI review requested due to automatic review settings April 17, 2026 10:08
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copilot AI review requested due to automatic review settings April 17, 2026 11:13
@valaphee valaphee force-pushed the multi-block-change branch from f9ceb77 to 6f3154a Compare April 17, 2026 11:13
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread core/src/main/java/org/geysermc/geyser/level/block/type/WaterBlock.java Outdated
@valaphee
Copy link
Copy Markdown
Member Author

also found this CloudburstMC/Protocol#333

but the sub chunk position has not really an effect

@onebeastchris onebeastchris added the PR: Bugfix When a PR contains a bugfix label Apr 23, 2026
Copy link
Copy Markdown
Member

@onebeastchris onebeastchris left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

Copilot AI review requested due to automatic review settings April 23, 2026 20:47
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +77 to +93
BlockState blockState = BlockState.of(entry.getBlock());
if (blockState.is(Blocks.AIR)) {
ItemFrameEntity itemFrameEntity = ItemFrameEntity.getItemFrameEntity(session, entry.getPosition());
if (itemFrameEntity != null) { // Item frame is still present and no block overrides that; refresh it
itemFrameEntity.updateBlock(true);
continue;
}
}

// Some block may have special handling, keep it that way
if (!(blockState.block().getClass().equals(Block.class))) {
blockState.block().updateBlock(session, blockState, entry.getPosition());
continue;
}

// Skull is gone
session.getSkullCache().removeSkull(entry.getPosition());
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand why you didn't use ChunkUtils#updateBlockClientSide as this would send UpdateBlockPacket for each changed block. But if we ever add something extra to Block#updateBlock (other than checkForEmptySkull) then we'd need to think about adding it here too.
This would probably require a larger refactor, so I think it's fine for now.
Not sure what other people think.

Copy link
Copy Markdown
Member Author

@valaphee valaphee Apr 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea its only called if its specialized, for anything else we would have to check both locations, could add comments

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be fine with a comment in Block#updateBlock like: any changes you do here, add them to this translator too.

Copilot AI review requested due to automatic review settings April 25, 2026 10:38
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 1 comment.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +96 to +99
// Some block may have special handling, keep it that way
if (!(blockState.block().getClass().equals(Block.class))) {
blockState.block().updateBlock(session, blockState, entry.getPosition());
continue;
Copy link

Copilot AI Apr 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The specialization check !(blockState.block().getClass().equals(Block.class)) treats all Block subclasses as requiring per-block updateBlock(...) handling, even when the subclass does not override updateBlock (e.g., BannerBlock just adds dyeColor() but inherits Block.updateBlock). That means those blocks will still fan out into individual UpdateBlockPackets and reduce the effectiveness of batching. Consider switching to an explicit marker (interface/boolean method) for blocks that truly need special update behavior, and batch everything else.

Copilot uses AI. Check for mistakes.
@onebeastchris onebeastchris merged commit 9f6db69 into GeyserMC:master Apr 26, 2026
5 of 6 checks passed
@valaphee valaphee deleted the multi-block-change branch April 27, 2026 09:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

PR: Bugfix When a PR contains a bugfix

Projects

None yet

4 participants