Skip to content

Reduce server cost of room rebuilds and block updates - #131

Merged
RealAntEngineer merged 4 commits into
RealAntEngineer:1.21.1-releasefrom
dhm-msd:pr/2-performance
Oct 19, 2026
Merged

RealAntEngineer merged 4 commits into
RealAntEngineer:1.21.1-releasefrom
dhm-msd:pr/2-performance

Conversation

@dhm-msd

@dhm-msd dhm-msd commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Four small performance changes (one commit each) for the oxygen room system. None changes what counts as sealed, except for rooms touching unloaded chunks (item 4). The only visible difference is that a rebuild can run up to 5 ticks after the block change.

Changes

  1. Block-update handler (CSEventHandler.onBlockPlaced): runs on the logical server only (rooms are server logic and the client gets the shape through entity data), uses one entity query around the block instead of up to seven, and exits early when no room is nearby. It runs for every block update in every dimension, so this matters.
  2. Debounced rebuilds: a block update only flags the room. The rebuild runs on the room's next tick, at most once every 5 ticks, so a piston, a door or a machine firing many updates in a row causes one search instead of one per update. A full rebuild also clears the queued frontier of the discarded shape.
  3. RoomShape value equality: SynchedEntityData skips a set() only when the new value equals the old one, and RoomShape had identity equality, so a rebuild that produced the same room re-sent it to every tracking player.
  4. Unloaded chunks count as solid in the search, so a room at the edge of the loaded area can no longer force synchronous chunk loads or generation on the server thread.

Notes

  • Independent of the bug-fix PR; they merge cleanly in either order.
  • A room touching an unloaded chunk looks sealed until its next rebuild (item 4).

onBlockPlaced runs for every block update in every dimension. It now returns early on
the client (rooms are server logic and the client receives the shape through entity
data), and uses a single entity query around the block instead of up to seven, with an
early exit when no room is nearby.
Every block update in or beside a room used to run a full room search immediately on
the server thread, so a piston, a door or any machine firing many updates in a row
caused many searches in one tick. Updates now only flag the room; the rebuild runs on
the room's next tick, at most once every 5 ticks, and a burst collapses into one rebuild.
A full rebuild also clears the queued search frontier of the previous, discarded shape.
SynchedEntityData only skips a set() when the new value equals the old one. RoomShape
had identity equality, so every rebuild that produced the same room marked the shape
dirty and re-sent it to every tracking player. Compare volume, closed flag and boxes.
The search called getBlockState/getBlockEntity on every candidate position, which loads
or generates chunks synchronously on the server thread when a room touches the edge of
the loaded area. Unloaded positions now count as solid and are skipped.
@CLAassistant

CLAassistant commented Oct 19, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@dhm-msd
dhm-msd marked this pull request as ready for review October 19, 2026 20:20
@RealAntEngineer
RealAntEngineer merged commit 0cad4fe into RealAntEngineer:1.21.1-release Oct 19, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants