Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
e3476f5
Version 1.4.5: fix DestroySigns config and guard against orphaned-cla…
claude Aug 24, 2026
bb03854
ci: bump actions/upload-artifact to v4
claude Aug 24, 2026
f4b9033
fix: point GriefDefenderAPI dependency at the correct Maven coordinate
claude Aug 24, 2026
bf3a6ba
fix: exclude GriefDefenderAPI's unshaded transitive dependencies
claude Aug 24, 2026
4eb8cb6
Port PlaceholderAPI support and fix parent-claim-purchase bug from bl…
claude Aug 24, 2026
c29b4a0
fix: correct placeholderapi version pin
claude Aug 24, 2026
98f8c82
Add automatic claim block snapshot/restore for rent and lease
claude Aug 24, 2026
0ff46ea
Add per-player sell/rent/lease limits (owner and buyer side)
claude Aug 24, 2026
d11bf97
Add IClaimAPI.getTransaction(UUID) hook for GriefDefender's map integ…
claude Aug 24, 2026
8de3551
Fix auction sell-limit bypass and admin-claim owner-limit false block
claude Aug 24, 2026
c6bb77c
Move claim snapshot creation to move-in time; log snapshot failures
claude Aug 24, 2026
9ece3e1
fix: pool auction listings into the sell-owner limit count
claude Aug 24, 2026
d0447d3
fix: stop logging spurious snapshot warnings on non-GriefDefender pro…
claude Aug 24, 2026
2446ab3
deps: update GriefPrevention, WorldGuard, WorldEdit, and Towny
claude Aug 24, 2026
28690ce
fix: revert WorldGuard/WorldEdit/Towny bumps -- JDK 16 can't read the…
claude Aug 24, 2026
75fff76
build: raise JDK toolchain to 25
claude Aug 24, 2026
42229a4
build: parameterize spigot-api/paper-api target version
claude Aug 24, 2026
e86ff13
ci: build a matrix across all four supported Minecraft targets
claude Aug 24, 2026
0b86649
fix: remove -- from pom.xml comments, invalid inside XML comments
claude Aug 24, 2026
ebda077
fix: quote -D flags in build.yml so Maven version ranges survive the …
claude Aug 24, 2026
6231b91
fix: exclude ancient transitive bukkit/spigot-api from EssentialsX/Wo…
claude Aug 24, 2026
24a27a1
fix: stop pinning adventure-api, let paper-api's own version win
claude Aug 24, 2026
9978990
deps: re-attempt WorldGuard/WorldEdit/Towny bumps now that JDK is 25
claude Aug 24, 2026
10397a1
docs: correct misleading comment on spigot-api/paper-api profile orde…
claude Aug 24, 2026
36dddbb
fix: paper-only profile never activated for a plain `mvn package`
claude Sep 1, 2026
0de67f8
feat: add scripts/run-server.sh for local multi-target testing
claude Sep 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ jobs:

steps:
- uses: actions/checkout@v3
- name: Set up JDK 16
uses: actions/setup-java@v3
- name: Set up JDK 25
uses: actions/setup-java@v4
with:
java-version: '16'
distribution: 'adopt'
java-version: '25'
distribution: 'temurin'
- name: Build with Maven
run: mvn --batch-mode --update-snapshots package
65 changes: 54 additions & 11 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,40 +1,83 @@
name: build

on:
on:
workflow_dispatch:
push:

jobs:
build:
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
include:
# Legacy (pre-calendar-versioning) Minecraft/Spigot/Paper targets:
# both spigot-api and paper-api are published as
# "<version>-R0.1-SNAPSHOT" for these.
- target: '1.21.1'
minecraft-api-version: '1.21.1'
spigot-api-version: '1.21.1-R0.1-SNAPSHOT'
paper-api-version: '1.21.1-R0.1-SNAPSHOT'
skip-spigot-api: 'false'
- target: '1.21.4'
minecraft-api-version: '1.21.4'
spigot-api-version: '1.21.4-R0.1-SNAPSHOT'
paper-api-version: '1.21.4-R0.1-SNAPSHOT'
skip-spigot-api: 'false'
- target: '1.21.11'
minecraft-api-version: '1.21.11'
spigot-api-version: '1.21.11-R0.1-SNAPSHOT'
paper-api-version: '1.21.11-R0.1-SNAPSHOT'
skip-spigot-api: 'false'
# Current/latest target: Minecraft's new calendar-based version
# scheme (26.x+). Paper publishes paper-api as
# "<version>.build.<n>-<channel>"; "[<version>.build,)" resolves
# to the newest published build. Spigot has not published a
# spigot-api under this scheme, so this target is Paper-only.
- target: '26.1.2'
minecraft-api-version: '26.1.2'
spigot-api-version: '' # unused, skip-spigot-api is true
paper-api-version: '[26.1.2.build,)'
skip-spigot-api: 'true'

steps:
- name: 'Checkout source code'
uses: actions/checkout@v4
- name: 'Set up JDK'
uses: actions/setup-java@v3
uses: actions/setup-java@v4
with:
java-version: '16'
distribution: 'adopt'
java-version: '25'
distribution: 'temurin'

- name: 'Cache dependencies'
uses: actions/cache@v3
with:
path: ~/.m2
key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2
key: ${{ runner.os }}-m2-${{ matrix.target }}-${{ hashFiles('**/pom.xml') }}
restore-keys: ${{ runner.os }}-m2-${{ matrix.target }}

- name: 'Build, test, and package'
run: mvn -B package --file pom.xml
run: >
mvn -B package --file pom.xml
"-Dminecraft.api.version=${{ matrix.minecraft-api-version }}"
"-Dspigot.api.version=${{ matrix.spigot-api-version }}"
"-Dpaper.api.version=${{ matrix.paper-api-version }}"
"-Dskip.spigot.api=${{ matrix.skip-spigot-api }}"

- name: 'Get artifact version'
id: pomVersion
run: |
VERSION=$( mvn help:evaluate -Dexpression=project.version -q -DforceStdout )
echo "::set-output name=version::$VERSION"
echo "version=$VERSION" >> "$GITHUB_OUTPUT"

- name: 'Rename artifact for this target'
run: |
cp "target/RealEstate-${{ steps.pomVersion.outputs.version }}.jar" \
"RealEstate-${{ matrix.target }}-${{ steps.pomVersion.outputs.version }}.jar"

- name: 'Upload artifact'
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: RealEstate-${{ steps.pomVersion.outputs.version }}.jar
path: target/RealEstate-${{ steps.pomVersion.outputs.version }}.jar
name: RealEstate-${{ matrix.target }}-${{ steps.pomVersion.outputs.version }}.jar
path: RealEstate-${{ matrix.target }}-${{ steps.pomVersion.outputs.version }}.jar
10 changes: 7 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ build.bat
/bin/
/target/
.vscode
report.cmd
report.txt
javadoc.cmd
report.cmd
report.txt
javadoc.cmd

# Local test servers set up by scripts/run-server.sh (downloaded Paper
# jars, world data, logs, etc.) — not something to commit.
/servers/
34 changes: 34 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,39 @@
# Changelog

# Version 1.4.5 (2026-08-24)

## Bug Fixes

- **Sign destruction ignored config:** `DestroySigns.Rent` and `DestroySigns.Lease` in `config.yml` stopped being honored after the 1.4.2 claim API refactor — signs were always destroyed on rent/lease regardless of the setting. Both are now respected again. (#84, #87)
- **`/re info` could crash on an orphaned transaction:** if the claim tied to a sign's transaction could no longer be found (e.g. the claim was resized, abandoned, or deleted while a transaction was still open), previewing that transaction threw an unhandled `NullPointerException` instead of showing an error. Sell, rent, lease, and auction previews now report the problem to the player and log a warning instead of crashing. (#87)
- **Parent claim purchases always reported an error:** buying a parent (non-sub) claim always sent the buyer an "unexpected error" message even though the purchase and ownership transfer had already succeeded. The stale post-transfer verification causing this has been removed.
- **The project failed to build entirely:** the `GriefDefenderAPI` dependency was pinned to a JitPack build of a commit that no longer exists upstream after a history rewrite, so it could never be resolved. Repointed to the real `com.griefdefender:api` coordinate GriefDefender actually publishes, with its already-shaded transitive dependencies excluded.

## New Features

- **PlaceholderAPI support:** exposes `%realestate_claim_rent_amount%`, `%realestate_claim_sell_amount%`, and `%realestate_claim_lease_amount%`, showing the price of the transaction sign at a player's current location.
- **Automatic claim snapshot/restore for rent and lease:** when a tenant moves into a rented or leased claim (right before they're granted access), its blocks are now snapshotted automatically; once that tenant's rental period or lease ends (expiry without renewal, failed payment, or admin-forced cancellation), the claim is restored back to that snapshot, undoing anything the tenant built or destroyed. The snapshot is taken at move-in time rather than when the sign is first listed, so any changes the owner makes to their own claim after listing it but before a tenant moves in are preserved rather than wiped. This does not apply when a lease completes and ownership transfers to the buyer — the new owner's changes are kept. Controlled by the new `RealEstate.Rules.ClaimSnapshots` config option (default: enabled). Currently only implemented for GriefDefender (via its `ClaimSnapshot` API); GriefPrevention, WorldGuard, and Towny claims are unaffected and behave exactly as before.
- **Per-player sell/rent/lease limits:** admins can now cap, per player, how many claims someone can simultaneously have listed for sale/rent/lease (`RealEstate.Default.Limit.Sell.Owner`, `.Rent.Owner`, `.Lease.Owner`), how many they can simultaneously be renting/leasing (`.Rent.Buyer`, `.Lease.Buyer`), and how many they may ever purchase outright (`.Sell.Buyer`, a lifetime total). All six default to `-1` (unlimited). The five concurrency-based limits are derived directly from the live transaction store and work identically on every supported claim provider (GriefPrevention, GriefDefender, WorldGuard, Towny); the lifetime purchase count is tracked in RealEstate's own transaction data store (file or database, matching whichever backend is already configured) rather than on the claim itself, so it too is provider-agnostic. An auction is treated as a sale for both of these: listing an auction counts against `.Sell.Owner` and winning one counts against `.Sell.Buyer`, exactly like a sell sign. None of the owner-side limits (`.Sell.Owner`, `.Rent.Owner`, `.Lease.Owner`) apply to admin-claim listings, since those are never attributed to the listing admin's personal count. Ported and adapted from `bloodmc/realestate@4e34dff`; that fork's per-rank LuckPerms meta overrides were intentionally left out, since this codebase has no existing LuckPerms integration and adding one is a separate dependency decision — limits here are global, config-only.
- **Map-integration data hook for GriefDefender:** added `IClaimAPI#getTransaction(UUID)`, letting a claim be looked up by its provider-specific unique ID and returning the RealEstate transaction (price, buyer, period) currently associated with it, if any. This is purely a data-access hook — RealEstate does not add or render any map UI itself; it exists so that GriefDefender's own built-in BlueMap/Dynmap claim-popup integration can pull RealEstate's transaction info when a server has it enabled. Implemented for GriefDefender, which can resolve a claim from its UUID directly; GriefPrevention, WorldGuard, and Towny have no existing by-ID claim lookup in this codebase (only by-location), so they return `null`.

## Improvements

- **Dependency alignment:** bumped the `spigot-api` dependency from 1.21.1 to 1.21.4 to match `paper-api` and the plugin's declared `api-version`.
- **CI:** the build workflow's `actions/upload-artifact@v3` step was hard-deprecated by GitHub and failed before checkout even ran; bumped to v4.
- **JDK toolchain raised from 16 to 25.** Paper's own build (as of Minecraft's new 26.x calendar-based version scheme) compiles against a JDK 25 toolchain, and WorldGuard/WorldEdit/Towny's latest releases publish JDK 25 (class file 69) bytecode — unreadable by the previous JDK 16 toolchain. JDK 25 reads everything from old JDK 16 class files up through the newest dependencies, so a single toolchain covers every supported target below with no per-target JDK matrix needed. `maven-compiler-plugin` was also bumped (`3.8.0` → `3.13.0`) for reliable JDK 25 support, and both GitHub Actions workflows' `java-version` were updated to match.
- **Multi-target build support: RealEstate now builds against four Minecraft/Paper/Spigot targets — 1.21.1, 1.21.4, 1.21.11, and the current 26.x release (26.1.2 and newer).** `pom.xml` gained `minecraft.api.version`, `spigot.api.version`, and `paper.api.version` properties (parameterizing the `api-version:` field in `plugin.yml`/`paper-plugin.yml` and the `spigot-api`/`paper-api` dependency versions via the same resource-filtering mechanism already used for `version: ${project.version}`), so any one target can be built with `mvn package -D<property>=<value>...` without editing source. `.github/workflows/build.yml` (runs on every push) now builds all four targets in a parallel matrix and uploads each as a separately-named artifact (`RealEstate-<target>-<plugin-version>.jar`); `.github/workflows/build.yaml` (the PR sanity check) stays a single build on the pom's defaults (the latest/26.x target).
- **Spigot has not published a `spigot-api` under the new 26.x version scheme** (confirmed via Paper's own docs: `docs.papermc.io`'s project-setup guide notes the version-string format changed at `26.1`/`1.21.11`, and Paper's `paper-api` build declares an outgoing Gradle capability conflict against `org.spigotmc:spigot-api` at the same version specifically to say the two are alternatives, not a signal that Spigot itself ships one at that version). 1.21.11 is, as of this writing, the newest Minecraft version with a real `spigot-api` release. The 26.x build target is therefore Paper-only: the new `skip.spigot.api` property (default `true`) omits the `spigot-api` dependency entirely for that target via a Maven profile, while the three older targets keep both `spigot-api` and `paper-api` together as before.
- **Two latent classpath conflicts surfaced while wiring this up, both now fixed:** EssentialsX transitively pulls `org.bukkit:bukkit:1.12.2-R0.1-SNAPSHOT` and WorldGuard transitively pulls `org.spigotmc:spigot-api:1.16.2-R0.1-SNAPSHOT` — both pre-date the 1.20 sign-side API (`Sign#getSide`/`SignSide`) this codebase uses. These were always present but only started actually losing Maven's classpath-ordering race once dependency resolution shifted under the JDK 25 / multi-target changes; both are now explicitly excluded via `<exclusions>` so only this project's own explicitly-declared, correctly-versioned `spigot-api`/`paper-api` can ever provide those classes. Separately, this project's own pinned `net.kyori:adventure-api:4.18.0` dependency was removed entirely: it isn't imported by this project's own source (GriefDefender integration code uses GriefDefender's shaded `com.griefdefender.lib.kyori.adventure.*` copy instead), and pinning it directly shadowed paper-api's own transitively-supplied Adventure version via Maven's "nearest wins" mediation, which broke compilation against the 26.x target specifically (paper-api's `Player` interface referenced newer Adventure classes the old pinned jar didn't have). Each target now resolves whatever Adventure version paper-api (and spigot-api, where present) actually supplies.

## Tooling

- **Local test server script:** `scripts/run-server.sh <target>` (targets: `1.21.1`, `1.21.4`, `1.21.11`, `26.1.2`/`latest`, matching the multi-target build's matrix above) downloads the matching Paper server jar via PaperMC's Fill downloads API (`fill.papermc.io`, the successor to the old `api.papermc.io`), builds the plugin for that target using the same `mvn package -D...` invocation as `build.yml`, drops the freshly-built jar into `servers/<target>/plugins/`, accepts the EULA, and launches the server — so changes can be tested in-game instead of only compile-checked in CI. Paper server jars are used for every target, including the three pre-26.x ones, since Paper is a strict superset that runs Spigot plugins fine and sourcing separate Spigot/CraftBukkit jars via BuildTools would be far slower for a local dev loop. `servers/` is gitignored.

## Dependency Updates

- **GriefPrevention: `16.18.4` → `17.0.0`** (skipped `18.0.0`). The API surface this codebase actually calls (`Claim#getID/getArea/isAdminClaim/getLesserBoundaryCorner/setPermission/dropPermission/clearPermissions/setSubclaimRestrictions`, the `children`/`parent`/`managers`/`ownerID` fields, `ClaimPermission`, `DataStore#getClaimAt/saveClaim/getPlayerData/changeClaimOwner`, `PlayerData`'s claim-block getters/setters, and the `ClaimDeletedEvent`/`ClaimPermissionCheckEvent` classes) is byte-for-byte unchanged between `16.18.4` and `17.0.0` — confirmed by diffing the real source at both tags in `GriefPrevention/GriefPrevention` on GitHub. `18.0.0` was deliberately not taken: its `pom.xml` sets `maven.compiler.release=21` (up from `16` in `17.0.0`, matching this project's own `16` target and the CI JDK at the time), a hard requirement change that risked the JDK 16 CI toolchain being unable to compile against it, and it also reorders the `ClaimPermission` enum so `Manage` grants `Build`/`Inventory`/`Access` (previously a separate track that granted nothing) — a real behavior change to permission semantics this codebase relies on via `GPClaim#addPlayerPermissions`. `17.0.0` gets a full major version closer to current with none of that risk. (Now that the JDK toolchain is 25, `18.0.0`'s JDK 21 requirement is no longer a blocker — but its `ClaimPermission` behavior change stands regardless of JDK, so it's still not taken here without a deliberate look at that semantics shift.)
- **WorldGuard `7.0.5` → `7.0.18`, WorldEdit `7.2.0` → `7.4.5`, Towny `0.101.1.0` → `0.103.2.0`.** Source-level API diffing (same method as above) had already shown no incompatible usage for any of the three; the only blocker was that their published artifacts are JDK 25-compiled class files the previous JDK 16 toolchain couldn't read at all (`class file has wrong version 69.0, should be 60.0`). Now that the toolchain is JDK 25 (see above), all three build and compile cleanly across every supported target in CI.

# Version 1.4.3 (2025-02-14)

## New Features
Expand Down
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ WorldGuard plugin can be found [here](https://dev.bukkit.org/projects/worldguard

Towny plugin can be found [here](https://www.spigotmc.org/resources/towny-advanced.72694/).

## Local testing
To try changes in-game instead of just relying on CI, `scripts/run-server.sh <target>` downloads a matching Paper server (cached under `servers/<target>/`), builds the plugin for that target, and launches the server with it already installed:
```sh
./scripts/run-server.sh 1.21.11 # or 1.21.1, 1.21.4, 26.1.2 / latest
```
See the script's header comment for full usage and requirements.

## Translation
We are looking to increase our language locale. If you speak multiple languages, you can help contribute to our project.

Expand Down
6 changes: 5 additions & 1 deletion paper-plugin.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: RealEstate
main: me.EtienneDx.RealEstate.RealEstate
version: ${project.version}
api-version: 1.21.4
api-version: ${minecraft.api.version}
authors:
- EtienneDx
- DmitryRendov
Expand Down Expand Up @@ -37,6 +37,10 @@ dependencies:
load: BEFORE
required: false
join-classpath: true
PlaceholderAPI:
load: BEFORE
required: false
join-classpath: true
commands:
re:
description: Access to the claim transaction information.
Expand Down
3 changes: 2 additions & 1 deletion plugin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ softdepend:
- WorldGuard
- WorldEdit
- Towny
api-version: 1.21.4
- PlaceholderAPI
api-version: ${minecraft.api.version}
commands:
re:
description: Access to the claim transaction information.
Expand Down
Loading
Loading