Skip to content

new release#269

Merged
tastybento merged 31 commits into
masterfrom
develop
Jun 13, 2026
Merged

new release#269
tastybento merged 31 commits into
masterfrom
develop

Conversation

@tastybento

Copy link
Copy Markdown
Member

No description provided.

tastybento and others added 30 commits May 5, 2026 18:30
Track block counts, entity counts, limits, and offsets independently per
World.Environment so overworld, nether, and end no longer share a single
count. Counts are now persistent rather than derived from getNearbyEntities,
so they stay accurate when nether/end chunks are unloaded — the original
bug in #43.

- IslandBlockCount: every map keyed by Environment first; legacy data
  migrates lazily into Environment.NORMAL on first access.
- BlockLimitsListener: env-aware tracking; resolution priority is island-env,
  world-named, env-default. New blocklimits-nether and blocklimits-end
  config sections override the env default for one env each.
- EntityLimitListener: persistent per-env counts maintained via spawn-handler
  increments and EntityRemoveEvent decrements (UNLOAD cause excluded so
  chunk unload doesn't drop the count). EntityPortalEvent migrates counts
  between envs to prevent the obvious portal exploit.
- JoinListener: permission format extended. 5-segment perms still apply
  the limit to all envs independently; new 6-segment form
  '<gm>.island.limit.<env>.<KEY>.<N>' targets one env (overworld/nether/end).
- LimitPanel: one tab per env (skipped for envs the gamemode doesn't
  generate). LimitTab reads counts from the IBC.
- Placeholders: env-suffixed variants added (_overworld_count etc.); the
  unsuffixed forms remain as sums for back-compat.
- RecountCalculator: rebuilds counts per-env, including a loaded-entity
  scan to seed migrated servers' nether/end entity counts.
- Tests: 230/230 passing, including new coverage for migration, env-prefixed
  perms, env-isolated counts, and per-env panel display.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Separate block and entity limits per dimension (fixes #43)
- Drop redundant eq() matchers in JoinListenerTest verify() calls (S6068)
- Replace public modifier with package-private on JUnit 5 tests (S5786)
- Use non-deprecated PlayerJoinEvent(Player, Component) constructor (S5738)
- Rename `var` local in LimitTabTest to avoid restricted identifier (S6213)
- Remove unused imports (eq, mock, Disabled) (S1128)
- Use StringBuilder.isEmpty() over length() > 0 (S7158)
- Drop "throws Exception" from BlockLimitsListenerTest methods that don't throw (S1130)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Drop the unused islandWorldManager field from Limits
- Remove unnecessary intermediate raw Map cast in IslandBlockCount.newInner

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Extract entity-key handling from loadEntityLimits into applyEntityKey to
  cut cognitive complexity from 17 to under the threshold
- Extract group-override handling into helpers so loadGroupLimitOverrides
  has a single break/continue path
- Replace duplicated " - skipping..." and ".limit" string literals with
  SKIPPING and LIMIT_SUFFIX constants

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Drop the unused GameModeAddon parameter from LimitPanel.addEnvTab
  (was 8 params, now 7) and the unused Island parameter from
  LimitTab.addEntityLimits/addEntityGroupLimits
- Hoist the duplicated translation keys (max-color, regular-color,
  block-limit-syntax) and "[limit]" placeholder into constants
- Use EnumMap for the EntityType limit map in addEntityLimits

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Split RecountCalculator.scanAsync's nested chunk/column logic into a
  scanColumn helper and lift loop bounds out of the per-block check
- Break EntityLimitListener.atLimit into resolveTypeLimit,
  resolveGroupLimits, checkTypeLimit, and checkGroupLimits so each
  method has a single responsibility
- Extract JoinListener.checkPerms's per-permission body into
  applyOnePerm so the loop becomes a thin filter-and-apply pass

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Now that addEntityLimits/addEntityGroupLimits no longer use the island,
the constructor's island parameter is dead too. Remove it and update the
LimitPanel and LimitTabTest call sites.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- JoinListener.applyOnePerm: pull the @nullable event-IBC into a local
  before the null check so the analyzer sees the guard before the
  applyLimit call
- IslandBlockCount.newInner: use diamond operator on the EnumMap via a
  typed local, dodging the unchecked-cast inference issue

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The floating jitpack snapshot v1.21-SNAPSHOT resolves to an ephemeral
git-described build whose jar/POM get evicted, breaking CI even on
unchanged commits. Switch to the equivalent stable Maven Central
coordinates (org.mockbukkit.mockbukkit:mockbukkit-v1.21:4.110.0).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Brings the supported-versions list in line with the other addons (1.21.5-1.21.11, 26.1, 26.1.1, 26.1.2).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Update Modrinth game-versions to current MC range
- BlockSpreadEvent: decrement old block before adding new (was leaking old counts)
- BlockGrowEvent: revert count increment when event is cancelled due to limit hit
- RecountCalculator: load chunks in parallel instead of sequentially (fixes calc timeout on large islands)
- RecountCalculator: use @nonnull getIsland(Island) to prevent permission limit loss on null ibc
The BlockGrowEvent handler decremented the new block's count after a
cancelled (over-limit) grow. But process(block, true) returns before
incrementing when the limit is hit, so that decrement removed a count
that was never added — driving a real, physically-present block's count
below its true value and letting the next grow slip past the limit.

Drop the spurious decrement (the cancel branch was already balanced) and
add tests covering:
- BlockSpreadEvent decrementing the old block and adding the new (the
  leak this PR fixes)
- BlockSpreadEvent reverting cleanly when the new material is at limit
- BlockGrowEvent at a non-zero limit leaving the count untouched on a
  blocked grow (regression guard for the reverted line)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fix block count leaks and parallelize recount chunk loading (supersedes #263)
… in CLAUDE.md

Add a "Block State Transitions" section capturing the count-balance rule
for form/spread/grow handlers (decrement old, add new with limit check,
revert on cancel) and the gotcha that process(block, true) does not
increment when the limit is hit — so no compensating decrement belongs in
the cancel branch. Also brings in the pending Dependency Source Lookup,
Project Layout, and Key Dependencies sections.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
BlockMultiPlaceEvent extends BlockPlaceEvent and does not declare its own
HandlerList, so a single multi-place dispatch is delivered to BOTH
onBlock(BlockPlaceEvent) and onBlock(BlockMultiPlaceEvent) — each calling
process(block, true). A bed (or door, double-tall plant) was therefore
counted twice on placement, while breaking it fired a single BlockBreakEvent
and decremented once, permanently leaking +1 per place/break cycle until the
island hit a phantom limit.

Skip BlockMultiPlaceEvent instances in the BlockPlaceEvent handler and let
the dedicated handler count them once — the same subtype-guard pattern
onBlock(BlockFormEvent) already uses for its subclasses.

Tests dispatch through the real plugin manager (so the double delivery
actually occurs) and assert a bed counts once and returns to zero after a
break.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Count multi-block placements (beds, doors) once, not twice (#86)
#127)

When a player built an iron golem, detectIronGolem() assumed the
CreatureSpawnEvent location was the BASE iron block and only searched
upward. The built-mob spawn location is not guaranteed to be a specific
block of the structure — when it is the body block, the old search matched
nothing and removed only the spawn block, leaving the base, both arms and
the pumpkin behind. Vanilla consumes those blocks, so Limits left a
half-built golem's worth of blocks in the world (and uncounted).

Anchor detection on the carved pumpkin / jack o'lantern instead, which is
unambiguous: scan the spawn block and the two above it for the head, then
verify and erase the body, base and arms relative to it. This works whether
the spawn anchors on the base, body or head, and — unlike the old code,
which unconditionally aired the spawn block — erases nothing unless a full
valid pattern matches. Snowman detection is anchored the same way.

Tests build a coordinate-keyed mock block grid and verify every structure
block is removed for both spawn anchors, that a snowman is cleared, and
that a lone iron block is left untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Fix entity counts drifting above reality when mobs die off-island.
  trackSpawn counted the entity against the island where it spawned, but
  onEntityRemove used getIslandAt(entity.getLocation()) which returns
  empty when the entity wandered outside island bounds before dying or
  despawning. Added an entityIslandMap (UUID → islandId) so decrement
  always targets the correct island regardless of the entity's current
  location. onEntityPortal also updates the mapping for env-to-env
  transfers. A justPortaled debounce list prevents double-decrement if
  EntityRemoveEvent fires for the source-world removal during portal.

- Fix HangingPlaceEvent race: change onBlock priority from MONITOR to
  LOW. Both onBlock (limit check) and onHangingPlaceTrack (tracking)
  were at MONITOR. Bukkit does not guarantee handler dispatch order
  within a single listener class, so trackSpawn could increment the
  entity count before the limit check had a chance to cancel the event,
  leaving a spurious +1 in the persistent count.

- Fix processIsland undoing other plugins' event cancellations.
  cancelableEvent.setCancelled(false) was called unconditionally when
  the entity was not on a tracked island. Now guarded by runAsync so
  it only reverses this plugin's own pre-cancellation for async spawns
  (golems, withers). Other plugins' cancellations are left intact.
Anchor golem/snowman block removal on the pumpkin, not the spawn block (#127)
Fix three entity counting bugs in EntityLimitListener
Previously the only entity-limit check for spawn eggs was on the resulting
CreatureSpawnEvent, which is cancelled when over the limit — but by then the
egg item has already been consumed, so players lost the egg and got no spawn
(and no message). Reported for right-clicking a mob with a spawn egg.

Add LOW-priority guards on PlayerInteractEvent (egg on a block) and
PlayerInteractEntityEvent (egg on a mob) that resolve the egg's entity type,
check the island's limit for that type up front, and cancel the interaction
(keeping the egg) with the entity-limits.hit-limit message when at the limit.
A spawn egg always produces its own type, so the egg material maps directly
to the entity type being checked.

Refactors atLimit(Island, Entity) to delegate to a new
atLimit(Island, EntityType, Environment) overload so the limit can be checked
without an entity instance.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Deny spawn-egg use before consumption when at the entity limit (#134)
fixMaterial() hard-referenced Material.COPPER_WALL_TORCH, COPPER_TORCH
and the COPPER_*_CHEST family, which only exist on Minecraft 1.21.9+.
On older servers (e.g. Paper 1.21.8) the JVM failed to link these static
field references, throwing NoSuchFieldError on the first BlockFadeEvent.

Resolve these constants by name via Guava's Enums.getIfPresent into
static final Optionals at class load, and guard the fixMaterial branches
on isPresent(). The same jar now links and runs on both 1.21.8 and
1.21.9+. Lookups happen once, not in the per-tick hot path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Resolve the open issues reported on the new-code period:

Main code:
- BlockLimitsListener: replace Guava Optional copper fields with nullable
  Material (S4738); refactor fixMaterial to a lookup map and extract
  loadLimits helpers to cut cognitive complexity (S3776); lazy-supplier
  logging (S2629); drop unused handleBreak param (S1172).
- EntityLimitListener: constants for duplicated literals (S1192); extract
  assignment from condition (S1121); remove always-false getHand() null
  check (S2583); single Optional resolve before get (S3655).
- Stream.toList() over collect(toList()) (S6204) in Limits,
  RecountCalculator, OffsetCommand; rename shadowing locals (S1117);
  switch->if in CalcCommand/RecountCommand (S1301); CalcCommand island
  field -> local (S1450); drop unused OffsetCommand alias param (S1172);
  remove redundant lambda braces in JoinListener (S1602).

Tests:
- Drop redundant public modifier on 181 JUnit 5 methods (S5786).
- Replace deprecated PlayerJoinEvent(String)/BlockMultiPlaceEvent ctors
  and PlayerInteractEvent.isCancelled() (S5738/S1874).
- Parameterize the four invalid-perm-format tests (S5976); method
  reference (S1612); assertNotEquals (S5785); drop useless eq() matchers
  (S6068); remove unused imports/vars/throws/commented code and add a
  missing assertion (S1128/S1481/S1854/S1130/S125/S2699).

All 243 tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add the four keys introduced this release to all 20 translation files:
admin.limits.offset.description (reused each file's existing translation,
previously orphaned under offset.main.description) and the panel
env-overworld/env-nether/env-end dimension names, localized per language.

Convert 375 legacy & color codes to MiniMessage tags across all 21 locale
files (e.g. &c -> <red>, &a -> <green>). Also fix eight pre-existing broken
codes in translations where the colour letter had been dropped (hr, es, uk,
tr messages and it regular-color) to <green>. CRLF line endings preserved.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@tastybento tastybento merged commit aa54c61 into master Jun 13, 2026
5 checks 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.

2 participants