Welcome to the Hangar Open Beta. Please report any issue you encounter on GitHub!
Avatar for castledking

A fork of GriefPrevention that adds 3D subdivisions

Report GriefPrevention3D?

R

18.2.20

GriefPrevention3D v18.2.20

Wiki: https://github.com/castledking/GriefPrevention3D/wiki

Features

Automatic nature restoration is back

Upstream deleted the entire restore-nature feature in GriefPrevention#2332 (5d0ebdec, July 2024). That commit landed here through a routine upstream merge, so servers that had been running automatic cleanup for years lost it on update with nothing in the changelog pointing at it.

The manual half came back in cab3d9cf — /restorenature, /restorenatureaggressive and /restorenaturefill all work, along with RestoreNatureProcessingTask and RestoreNatureExecutionTask. The automatic half did not. restoreClaim and restoreChunk existed nowhere in the source, the AutomaticNatureRestoration config key was never read, and CleanupUnusedClaimTask deleted expired claims and left the land exactly as the owner abandoned it. There was no setting an admin could flip, because there was no setting.

This release reconnects the automatic path to the processing tasks that were already shipping.

Config:

GriefPrevention:
  Claims:
    Expiration:
      AutomaticNatureRestoration:
        SurvivalWorlds: false

Defaults to false, matching upstream, so no existing server starts editing terrain after updating. It is written back on the next config save.

Where restoration now fires:

Trigger Restores when
Chest claim expiry (Expiration.ChestClaimDays) creative world, or SurvivalWorlds: true
Inactivity expiry (Expiration.AllClaims.DaysInactive) creative world, or SurvivalWorlds: true
Staff /deleteclaim creative world, or SurvivalWorlds: true
Player /abandonclaim creative world only

That table is upstream's behaviour reproduced exactly, including the asymmetry on the last row. SurvivalWorlds was never consulted on the abandon path — upstream gated it on creativeRulesApply alone, and the field comment read "whether survival claims will be automatically restored to nature when auto-deleted." A survival player abandoning a claim does not get their build flattened.

Restoration is silent when it fires automatically. RestoreNatureExecutionTask.showVisualization returns immediately on a null player ID, so nothing is drawn and no message is sent; the only trace is the existing expiry line in the admin log.

The size guards are upstream's: admin claims are skipped entirely, and so is anything over 10000 blocks of area, 250 wide or 250 deep. Claim#getArea resolves to ClaimBounds#area() — the 2D footprint, or polygon.cellCount() for a shaped claim — and getWidth/getHeight are X and Z lengths, so these thresholds mean here what they meant upstream despite this fork's 3D claims.

Claim#removeSurfaceFluids and Messages.UnclaimCleanupWarning restored

Both were collateral in the same upstream removal and are needed by the paths above. removeSurfaceFluids clears lava and water above sea level before a claim is deleted, only in creative-rules worlds, never in the Nether, and never for admin or oversized claims. It now bounds its scan with GriefPrevention.getWorldMaxY instead of the old World#getMaxHeight.

UnclaimCleanupWarning is back in the enum and translated across all fifteen message files — cs_CZ, de_DE, en, en_PT, es, fr_FR, ja_JP, ms_MY, pl_PL, pt_BR, ru_RU, tr_TR, uk_UA, zh_CN and the base messages.yml. Each follows the quoting convention and level of formality already used in that file, and reuses that locale's established word for a claim rather than introducing a new one.

Servers with a customised messages.yml on disk are unaffected either way: a key absent from the file falls back to message.defaultValue in MessageLocalization.populateMessagesArray, so the message appears in English rather than not at all.

Technical changes

Two deliberate departures from the code that was deleted, both because this fork supports region threading and upstream did not.

Chunk coordinates are derived arithmetically. Upstream's restoreClaim iterated Claim#getChunks(), which calls world.getChunkAt(x, z) and loads chunks on the calling thread — rejected under Folia and Canvas when that thread does not own the region. restoreClaim now walks lesser.getBlockX() >> 4 to greater.getBlockX() >> 4 directly and never touches a Chunk object. restoreChunk(Chunk, ...) is kept with upstream's signature for API compatibility and delegates to the coordinate-based path.

Block capture happens on the owning region thread. Upstream scheduled the whole operation with runTaskLaterAsynchronously and read blocks from the async task. The work is now split:

SchedulerUtil.runAtLocationLater(this, snapshotOrigin, () -> {
    // snapshot 18x18 columns on the region thread
    SchedulerUtil.runAsyncNow(this, task);   // analysis off-thread
}, delayInTicks);

RestoreNatureProcessingTask already closes the loop itself, dispatching RestoreNatureExecutionTask back through SchedulerUtil.runAtLocation before it writes anything. This mirrors how the fork's existing /restorenature handler in PlayerEventHandler already worked, rather than introducing a second convention.

Two smaller details:

  • The vertical window starts at seaLevel - 15, upstream's floor, so caves and mines under a claim are left alone. The fork's RestoreNatureProcessingTask treats its miny parameter as an array index rather than a world Y, so the snapshot array itself starts at that floor and 0 is passed in — the manual tool, which captures the full column, passes a world minimum that clamps to the same 0.
  • The boundary corners describe the chunk proper, +1 and +16 off the snapshot origin, not the 18-wide array. The outer ring is reference data the execution task never writes to, and cleanupEntities uses those corners to decide which entities are in scope.

Notes

  • Nothing happens until Expiration.ChestClaimDays or Expiration.AllClaims.DaysInactive is non-zero. Restoration is driven by expiry; with expiry disabled the flag has no effect.
  • Non-aggressive mode is what the automatic path uses, so RestoreNatureExecutionTask runs getClaimAt per block and skips anything still inside a claim. Neighbouring claims that share a chunk with a deleted one are safe.
  • Restoration operates per chunk, so it reaches the whole chunk rather than the claim footprint, and for a 3D claim it spans the full column above the floor rather than the claim's Y bounds. The per-block claim check above is what keeps that from mattering.
  • No data migration. No permission changes. No command changes.

Tests

No new tests. The full suite passes — 226 tests, 0 failures, 0 errors.

The restore path has no unit coverage and does not gain any here. It needs a live world to snapshot, a region scheduler to dispatch through, and real block writes to assert against; the mock harness provides none of the three.

What was verified statically: Claim#getArea, getWidth and getHeight were traced through ClaimBounds to confirm the upstream size thresholds still describe a 2D footprint in this fork; miny was traced through every use in RestoreNatureProcessingTask to confirm it is an array index and unused in RestoreNatureExecutionTask; and both edited message files were parsed to confirm the apostrophes in the restored string do not break YAML.

Files Changed

 M gradle.properties
 M pom.xml
 M src/main/java/com/griefprevention/commands/UnifiedAdminClaimCommand.java
 M src/main/java/me/ryanhamshire/GriefPrevention/Claim.java
 M src/main/java/me/ryanhamshire/GriefPrevention/CleanupUnusedClaimTask.java
 M src/main/java/me/ryanhamshire/GriefPrevention/GriefPrevention.java
 M src/main/java/me/ryanhamshire/GriefPrevention/Messages.java
 M src/main/resources/messages.yml
 M src/main/resources/messages_cs_CZ.yml
 M src/main/resources/messages_de_DE.yml
 M src/main/resources/messages_en.yml
 M src/main/resources/messages_en_PT.yml
 M src/main/resources/messages_es.yml
 M src/main/resources/messages_fr_FR.yml
 M src/main/resources/messages_ja_JP.yml
 M src/main/resources/messages_ms_MY.yml
 M src/main/resources/messages_pl_PL.yml
 M src/main/resources/messages_pt_BR.yml
 M src/main/resources/messages_ru_RU.yml
 M src/main/resources/messages_tr_TR.yml
 M src/main/resources/messages_uk_UA.yml
 M src/main/resources/messages_zh_CN.yml

Information

Published
August 8, 2026
3Downloads

Platforms

Paper
Paper
1.8.8–26.2