regionguard-0.2.0.jar
Curse Maven Snippet
What's new
v0.2.0
------
- Fixed a server crash ("Cannot encode empty ItemStack") when a player entered a
creative-mode region. InventoryStash.stash serialized every inventory slot,
including empty ones, and ItemStack.save throws on empty stacks in vanilla
1.21.1. Empty slots are now skipped and each item is tagged with its slot index
so items restore to the correct slot. stash() now returns success/failure and
enterCreativeRegion only clears the inventory + switches game mode after a
successful backup, so a disk error can never wipe a player's survival gear.
- Fixed fluid-spread (for real this time). Root cause: the server runs on
Mohist (a Forge + Paper hybrid), not pure NeoForge. On Mohist, vanilla fluid
flow is routed through Bukkit's BlockFromToEvent (confirmed by decompiling the
server's FlowingFluid tick path), which a NeoForge BlockEvent handler never sees
— so all earlier attempts did nothing. FluidProtectionHandler now also listens to
BlockFromToEvent and cancels it when the target is inside a fluid-spread-deny
region; the NeoForge EntityPlaceEvent handler remains as a fallback for pure
- Fixed fluid-spread AND block placement on the live Mohist server. Two real bugs:
1. FluidProtectionHandler read getToBlock().getType() (the destination, which is
AIR) to detect the fluid, so it never recognized water/lava and always bailed
before checking the region. It now reads the fluid TYPE from getBlock() (the
source) and checks the region at BOTH the source and destination positions.
2. Diagnostics used java.util.logging, which is invisible on Mohist's Log4j
console — that's why no [RegionGuard] lines appeared. Now uses the mod logger.
Also added BlockPlaceBukkitHandler: on Mohist, a player placing a water/lava bucket
(or any block) is routed through Bukkit's BlockPlaceEvent, NOT the NeoForge
EntityPlaceEvent that BlockProtectionHandler watches — so players could place
fluids in claims they didn't own. The new handler enforces the block-place flag for
real players via BlockPlaceEvent. Both Bukkit hooks are registered reflectively and
are still gated behind a temporary DEBUG flag for verification.
- Creative-mode hub confinement FIXED (target-based, was player-based):
- A player inside a creative-mode region can now only build / open containers at a
TARGET position that is itself inside a creative region. This closes the exploit
"stand inside the hub, place/open a chest outside it" — previously the check used the
player's own position, so standing inside the hub let you act on outside blocks.
- Applied on both the NeoForge handlers (BlockProtectionHandler.onPlace,
InteractionProtectionHandler container path) and the Mohist Bukkit handler
(BlockPlaceBukkitHandler), via the new ProtectionChecks.isCreativeBuildAllowed helper.
- Item-drop ban for creative players remains (CreativeItemHandler).
- Fluid / bucket placement in claims:
- FIXED (root cause): on Youer/Mohist the Bukkit event player is a CraftPlayer WRAPPER, not a
Forge ServerPlayer, so every guard that did `instanceof ServerPlayer` returned false and the
handler bailed silently — which is why non-members could place fluids with no log output and
the earlier RightClickBlock/PlayerBucketEmptyEvent/BlockPlaceEvent fixes never fired.
Handlers now resolve the real ServerPlayer via CraftPlayer.getHandle() (UUID fallback) before
running the membership checks.
- Added a PlayerInteractEvent (RIGHT_CLICK_BLOCK) net — the most reliable, earliest hook the
hybrid fires for a bucket empty. Cancels a water/lava bucket right-click BEFORE the source
block exists, gated by canPlaceFluid() (milk/fish/snow buckets ignored).
- PlayerBucketEmptyEvent + BlockPlaceEvent reflective listeners now also use the corrected
player resolution and name-based fluid detection.
- ProtectionChecks.canPlaceFluid(): wilderness = allow; inside a region = owner/member only.
- Added ProtectionChecks.canPlaceFluid(): in the wilderness anyone may place fluids; inside a
region only owners/members may. Enforced on both the NeoForge RightClickBlock path and the
NeoForge EntityPlaceEvent path.
- Console spam removed entirely: with fluid-placement working, all per-event diagnostics are
off (DEBUG=false) in BlockPlaceBukkitHandler and FluidProtectionHandler. The console now logs
only startup registration notices and real errors — no lines on normal place/deny/fluid-spread.
The *cancels* still run on every event; only logging is disabled.
- REMOVED the server-side FluidSweepHandler backstop. It caused a hard server crash:
sweeping getBlockState() over the global region (entire world, ±30M) on the tick
thread force-loaded chunks and corrupted the lighting/chunk queue, tripping the
watchdog (crash-2026-08-03_04.27.18). Fluid enforcement now relies solely on the
event-cancel path, which is safe.
- The Bukkit BlockFromToEvent listener registration is hardened: proxies are now built
with the Bukkit class's own classloader (previously the mod classloader, which on
hybrid servers made the hook silently fail to register with "interface not visible"),
and plugin lookup also tries the Youer core plugin. Logs a clear one-time
"[RegionGuard] BlockFromToEvent fluid listener registered (owner=...)" line so we can
confirm the hook fired.
- Removed the now-unused general.fluidSweep config option and RegionStorage.managersSnapshot().
- A player in a creative-mode region can no longer PLACE blocks OUTSIDE that claim
(BlockProtectionHandler + new isCreativePlayerOutsideClaim helper), so they can't
drop a chest outside the hub, stash items in it, walk out, and grab them in survival.
- A creative-mode player can no longer DROP/toss items at all (was previously only
blocked while inside the claim); now blocked everywhere, killing the
drop-outside-then-pick-up-in-survival loot path.
- A creative-mode player can no longer OPEN containers while outside the claim
(InteractionProtectionHandler), closing the pre-existing-outside-chest path.
- New message key protection.creative_outside_claim.
- Added creative-exit safety. When a player leaves a creative-mode region, they are
now teleported to the highest solid, standable block at their current X/Z (and
their fall distance is zeroed) so leaving a floating creative hub does not drop
them to their death. Implemented in MovementProtectionHandler.exitCreativeRegion.
v0.1.9
------
- Added creative-mode hub item rules:
- Players inside a creative-mode region cannot drop / toss items.
- Players outside a creative-mode region cannot pick up items lying on the
ground inside one (loot protection).
- Containers (chests etc.) inside a creative-mode region can only be opened by
a player who is themselves inside that region; outsiders are denied.
New flag-independent enforcement lives in CreativeItemHandler and
ProtectionChecks.isCreativeRegion / the chest check in allowBlockInteraction.
v0.1.9
------
Optimization & structure:
- Added RegionMath shared geometry helper and replaced the three duplicated
"push entity to nearest outside point" implementations (player, mob, Pixelmon
handlers) with a single source of truth.
- Parent flag inheritance: regions can now inherit unset flags from a parent region
via CuboidRegion.getFlagInherited + ProtectionChecks resolution. Priority ordering
was already in place.
Commands:
- Added /rg parent <id> <parent> and /rg parent clear <id> to set/clear a region's
parent, with cycle and self/parent guards.
New features (from community requests):
- Added `fluid-spread` flag (boolean, default allow). Set `fluid-spread deny`
on a region to stop water/lava from spreading there. Placing fluids with
buckets is still allowed (it is a player action).
- Added `creative-mode` flag (boolean, default deny). Entering a region with
`creative-mode allow` swaps the player to creative and stashes their survival
inventory + game mode; leaving restores it. The stash is persisted to
config/RegionGuard/inventory_stash/<uuid>.dat so it survives restarts, and a
player who logs in outside a creative region with a pending stash is
automatically restored.
- Added `block-break-allow` and `block-break-deny` flags (string sets). They
let you whitelist/blacklist specific blocks by id (e.g. minecraft:grass_block).
`block-break-deny` blocks the listed blocks; `block-break-allow` permits only
the listed blocks and denies everything else; otherwise the base `block-break`
flag (-> `build`) decides. These are exposed through `/rg flag <region> <flag> <value>`.
This mod has no additional files

