Repository navigation
Room search: fix volume drift, respect the tick budget, and continue past capped boxes; scan occupants every 5 ticks - #132
Merged
RealAntEngineer merged 6 commits intoOct 19, 2026
Conversation
…ackets RoomShapeSerializer.copy() returned the same instance, so the set_entity_data packet kept a reference to the live box list. searchTopology edited that list in place while the packet was encoded later on a Netty thread, causing a ConcurrentModificationException -> EncoderException and a disconnect for the tracking player. A published RoomShape is now never modified: searchTopology builds a new list and a new shape on every rebuild, so the shape can be shared with packets without a lock or a copy per sync. The one list copy per rebuild replaces the in-place edit.
inO2() consumes the 'inside an oxygen room' flag, and the suffocation and overheating checks each called it. The second call always reported 'no oxygen', so entities standing in a pressurised room took overheating damage. Evaluate it once per check and run the overheating branch only when there is no oxygen.
The carver instance is shared by all chunk-generation worker threads, but its height cache was a plain HashMap, which can corrupt or loop under concurrent access. Use a ConcurrentHashMap.
searchTopology removes the box that contains the start position and searches it again, but the old shape volume was kept and the re-added volume was added on top, so the volume grew every time the same area was re-searched until the room was wrongly treated as over the per-sealer size limit. Subtract the volume of the removed boxes first.
…ast capped boxes - A single box could grow far past maxBlockPerTick (only the size of the box was capped, not the remaining budget), so one search could take much longer than configured. A box now stops growing when it would use more than what is left of the tick's budget. - When a box stops growing because of a size cap (edge length 30 or the budget) rather than because every side is blocked, the cells around it were never queued, so a room could be declared sealed while its frontier was unexplored. Queue those cells so the search continues from them. - contains() no longer allocates a Vec3 per box per candidate block.
Each room ran one all-entity query per box every tick. It now scans every 5 ticks with one LivingEntity query on a cached bounding box (filtered against the boxes). Oxygen consumption and leaf production are multiplied by the interval so the totals per second stay the same, but oxygen now changes in 5-tick steps.
RealAntEngineer
marked this pull request as ready for review
October 19, 2026 21:33
RealAntEngineer
merged commit Oct 19, 2026
211ffbb
into
RealAntEngineer:1.21.1-release
1 check passed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three changes (one commit each) that alter how a room is searched and how oxygen is applied. They change behaviour slightly, so I kept them separate from the pure performance PR.
Changes
searchTopologyremoves the box containing the start position and searches it again, but the old volume was kept and the re-added volume was added on top, so the total kept growing until the room was wrongly overmaxSizePerSealer. The volume of removed boxes is now subtracted first.maxBlockPerTick(only its edge length was capped), so one search could take much longer than configured. It now stops growing when it would use more than the tick's remaining budget. Also, when a box stops because of a size cap (edge length 30 or the budget) instead of being blocked on every side, the cells around it were never queued, so a room could be declared sealed with its frontier unexplored. Those cells are now queued.contains()also no longer allocates aVec3per box.LivingEntityquery on a cached bounding box every 5 ticks. Oxygen consumption and leaf production are multiplied by 5, so the totals per second are unchanged, but oxygen changes in 5-tick steps.What to look at