Skip to content

Core structure suppression for all game modes (#116/#117/#118)#3019

Merged
tastybento merged 2 commits into
developfrom
feature/core-structure-suppression
Jul 9, 2026
Merged

Core structure suppression for all game modes (#116/#117/#118)#3019
tastybento merged 2 commits into
developfrom
feature/core-structure-suppression

Conversation

@tastybento

Copy link
Copy Markdown
Member

Problem

Disabling a vanilla structure in a BentoBox game mode has, so far, been a per-addon job. CaveBlock solved it in #117 and #118, but any game mode whose worlds delegate to vanilla generation (Boxed, SkyGrid, CaveBlock, custom worlds) can hit the same two problems:

  1. /locate freeze (ASkyblock vs BSkyblock #117). Cancelling AsyncStructureSpawnEvent stops a structure being placed but leaves the world's placement rules intact. Every structure search/locate, Eyes of Ender, explorer/treasure maps, dolphins, villager cartographer trades (per StructuresLocateEvent's own javadoc) — keeps proposing candidate positions that all get cancelled, scanning to the radius cap and freezing the main thread (62 s in CaveBlock's test, tripping the Paper Watchdog).
  2. Spawn-area leak (Fix YAMLException #118). A disabled structure can still generate near spawn, because a world's spawn chunks are generated during createWorlds(), before a listener registered in onEnable() exists.

This moves the fix into core so every game mode gets it for free.

Design

Two config layers

  • Global defaultworld.disabled-structures in config.yml (Settings), applied to every BentoBox game mode world (overworld/nether/end). Empty by default → no behaviour change on upgrade.
  • Per-world override — new WorldSettings.getStructureSettings() default method (binary-compatible), a Map<String,Boolean> (structure → should-generate) letting a game mode both disable extra structures (false) and force-enable one the global list disables (true). Absent entry → inherit global.

Effective decision: a per-world entry always wins; otherwise the global list applies. Keys are normalised (lower-case, -_) so casing/separators don't matter.

StructureListener handles both halves:

  • AsyncStructureSpawnEvent → cancel placement of a disabled structure.
  • StructuresLocateEvent → drop disabled structures from the search; cancel outright when nothing enabled remains, so the scan is skipped.

Timing (#118): one listener is registered per GameModeAddon in AddonsManager, immediately before createWorlds(), so it is active for the initial spawn-area generation. Worlds are matched by configured name (overworld / _nether / _the_end) rather than the world manager, because they are not yet registered during createWorlds().

Testing

StructureListenerTest (11 tests, all pass): global-default disable, per-world override disable, override force-enable-over-global, unlisted passthrough, nether name-match, out-of-world ignore, and the /locate all-disabled/mixed/all-enabled/out-of-world cases. Existing AddonsManager / Settings tests unaffected.

Follow-ups (separate PRs)

  • CaveBlock: override getStructureSettings() to return its generateStructures map and delete its now-redundant StructureGenerationListener + early registration.
  • Docs for world.disabled-structures and the new WorldSettings method.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Jbkc3n7vnNbtMx3s9dbkbc

Ports the CaveBlock structure-suppression fix into core BentoBox so every
game mode with vanilla-generated worlds (Boxed, SkyGrid, CaveBlock, ...) can
disable structures without the /locate freeze and spawn-area leak.

Two config layers:
- Global default: world.disabled-structures in config.yml (Settings), applied
  to every game mode world. Empty by default, so behaviour is unchanged.
- Per-world override: new WorldSettings.getStructureSettings() default method
  (binary-compatible) letting a game mode disable more structures or force-
  enable one the global list disables.

StructureListener handles both halves:
- AsyncStructureSpawnEvent -> stops the structure being placed
- StructuresLocateEvent -> narrows/cancels searches (/locate, Eyes of Ender,
  explorer/treasure maps, dolphins, cartographer trades) so they no longer
  scan to the border and freeze the main thread (#117)

One listener is registered per GameModeAddon in AddonsManager, immediately
before createWorlds(), so it is active for the initial spawn-area generation
(#118). Worlds are matched by configured name (overworld/nether/end) because
they are not yet registered with the world manager during createWorlds().

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jbkc3n7vnNbtMx3s9dbkbc

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Moves vanilla structure suppression into BentoBox core so all game modes that rely on vanilla world generation can both (a) prevent disabled structures from being placed and (b) prevent /locate (and related structure searches) from scanning forever for structures that will never generate.

Changes:

  • Add global configuration world.disabled-structures (empty by default) and Settings#getDisabledStructures().
  • Introduce per-world override hook WorldSettings#getStructureSettings() (default empty map) and implement suppression in new StructureListener for both spawn and locate paths.
  • Register the listener early (before createWorlds()) and add unit tests covering global/override behavior and locate filtering/cancellation.

Reviewed changes

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

Show a summary per file
File Description
src/main/java/world/bentobox/bentobox/managers/AddonsManager.java Registers structure suppression listener prior to world creation.
src/main/java/world/bentobox/bentobox/listeners/StructureListener.java Implements spawn cancellation + locate filtering/cancellation for disabled structures.
src/main/java/world/bentobox/bentobox/Settings.java Adds world.disabled-structures config entry + accessor methods.
src/main/java/world/bentobox/bentobox/api/configuration/WorldSettings.java Adds default per-world structure override map API.
src/test/java/world/bentobox/bentobox/listeners/StructureListenerTest.java Adds test coverage for suppression logic and world matching.

Comment thread src/main/java/world/bentobox/bentobox/managers/AddonsManager.java Outdated
Use AddonsManager.registerListener(addon, listener) instead of a raw
PluginManager.registerEvents call so the listener is tracked in the listeners
map and unregistered when the game mode addon is disabled or unloaded.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jbkc3n7vnNbtMx3s9dbkbc
@sonarqubecloud

sonarqubecloud Bot commented Jul 9, 2026

Copy link
Copy Markdown

@tastybento tastybento merged commit a6168c4 into develop Jul 9, 2026
3 checks passed
@tastybento tastybento deleted the feature/core-structure-suppression branch July 9, 2026 15:05
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.

2 participants