TownsAndNations-0.1.3.jar
What's new
# π CHANGELOG - TownsAndNations
> π«π· Version franΓ§aise : [CHANGELOG.fr.md](CHANGELOG.fr.md)
## Version 0.1.3 (Current Release)
> β οΈ **Breaking change for API consumers**: several `TownService` methods now take the acting
> player's UUID and return typed results instead of booleans. See *Typed Results* below.
### π§ Hytale API Compatibility
The plugin no longer compiled against Hytale server `0.5.7` (24 compile errors). Fixed:
- π¦ **Vector classes moved to JOML** β `com.hypixel.hytale.math.vector.Vector3d/3f/3i` and
`math.matrix.Matrix4d` are gone, replaced by `org.joml.*`. Accessors changed too: JOML exposes
`.x` / `.x()`, never `.getX()`. (`Transform` and `Rotation3f` remain in `math.vector`.)
- π’ `Matrix4d.asFloatData()` no longer exists β `matrix.get(new float[16])`
- π¨ `DisplayDebug` now expects `org.joml.Vector3fc` instead of `protocol.Vector3f`
- π¬ `Player.sendMessage(Message)` removed β message delivery lives on `PlayerRef`
### πΎ Storage β Crash Safety
- π‘οΈ **New `StorageUtils`** β writes can no longer corrupt your data
- Atomic writes: unique `.tmp` file β SHA-256 checksum verified by reading back β previous
version kept as `.bak` β atomic rename (falls back to a plain move on filesystems that
reject `ATOMIC_MOVE`)
- `readWithRecovery()` falls back to the `.bak` when the target is missing **or empty** β an
empty file being the signature of an interrupted write
- `WriteResult` sealed interface: `Success(file, checksum)` / `Failure(file, error, cause)`
- π **Wired into all 5 JSON load/save pairs** β towns, nations, wars, war invitations,
diplomatic relations. A crash mid-save no longer destroys your towns.
### π‘οΈ Protection
- π **Fixed plot detection** β protection resolved plots at a fake position in the *centre* of
the chunk (`chunk*32+16`, y=64) while the ECS listeners already had the exact block position
and discarded it. Any plot not covering the chunk centre was invisible to protection.
- New `PermissionService.BlockPosition` record carries the real position through
- New `Plot.intersectsChunk()` and `Town.getPlotInChunk()` as the fallback for callers that
only know the chunk β preferring an **owned** plot, since returning a free one would
silently widen permissions on a chunk that also holds someone's private plot
- π¬ **Denial messages with debounce** β blocked actions were cancelled *silently* (except PVP,
which spammed one message per damage event). All four protection systems now explain the
refusal, with a 2s cooldown per player+action pair. `DamageBlockEvent` (which fires on every
mining tick) shares its cooldown key with `BreakBlockEvent` to avoid duplicates.
- π **`townsandnations.bypass`** now short-circuits territory protection, alongside
`townsandnations.admin`
- β»οΈ **Deduplication** β the three near-identical `canBreak`/`canPlace`/`canInteract` internals
merged into a single method (~120 duplicated lines removed)
### π Permissions
- βοΈ **Provider chain** replacing the single LuckPerms lookup (new `permissions/` package)
- `PermissionProvider` returns `Optional<Boolean>`: a provider answering `false` for a player
it has never heard of would shadow every provider behind it
- `LuckPermsPermissionProvider` β maps LuckPerms `Tristate` (`UNDEFINED` β *no opinion*,
not *denied*)
- `HytaleNativePermissionProvider` β since `PermissionsModule` offers no tri-state, it is
probed twice with opposite defaults: same answers β node explicitly set, differing answers
β the module is just echoing the default
- `PermissionManager` β wildcard resolution from most to least specific: `a.b.c` β `a.b.*` β
`a.*`, so a precise deny beats a broad grant
- π·οΈ **`Permissions.java`** centralises the nodes. The four existing `command.*` nodes remain
authoritative and the new fine-grained nodes fall back onto them by wildcard β **existing
server configurations keep working unchanged**
- π **Authorization moved into the service** β the GUI checked the mayor *role* but never the
*permission node*, so a mayor whose `townsandnations.command.mayor` had been revoked could
still act through the interface. Both checks now live in `TownService.authorizeTownAction()`,
used by commands and GUI alike.
### π Deputies
Deputies are assistants: they handle day-to-day territory, never what would let them drain or
dismantle the town.
| Action | Mayor | Deputy |
|--------|:-----:|:------:|
| claim / unclaim | β | β **(new)** |
| togglePvp, togglePublic, setcolor | β | β |
| bank withdrawal | β | β |
| add / remove deputy | β | β |
| disband, invite, kick, sethome | β | β |
- Expressed by an explicit `RoleRequirement { MAYOR_ONLY, MAYOR_OR_DEPUTY }` rather than an
implicit boolean
- Deputies can now open `/town mayor gui` for the claim map; the page hides settings and the
danger zone from them. Security still comes from the service β hiding buttons is only comfort.
- βΉοΈ Deputies need the `townsandnations.command.mayor` node (or the fine-grained
`...mayor.claim` / `...mayor.unclaim`) for the commands to pass the command-level check.
### π§© Public API (new)
Other mods can now query, observe and veto TownsAndNations actions. See [docs/API.md](docs/API.md).
- π‘ **`EventBus`** β `register` / `unregister` / `publish` / `publishCancellable` / `clearAll`.
Listener exceptions are logged and isolated; the listener list is copied before iteration so a
listener may (un)register another without breaking the loop.
- π¨ **7 post-events**: `TownCreateEvent`, `TownDisbandEvent`, `TownClaimEvent`,
`TownUnclaimEvent` (reason `UNCLAIM` / `DISBAND`), `TownMemberEvent`, `NationCreateEvent`,
`NationDisbandEvent`
- π« **3 cancellable pre-events**: `TownCreatePreEvent`, `TownClaimPreEvent`,
`TownDisbandPreEvent`. Published after internal validation but **before any state change** β
cancelling costs the town nothing, notably no bank withdrawal.
- π **`TownsAndNationsAPI`** β `isAvailable()`, town/nation/territory/plot queries, `canBuild()`
### βοΈ Typed Results (breaking)
Callers used to **re-run the checks after the fact** to guess why an action failed ("is the
balance too low? is the limit reached?"). That reports the wrong reason as soon as state moves in
between, and could not distinguish a third-party mod cancellation at all.
```java
ClaimResult : SUCCESS, TOWN_NOT_FOUND, NO_PERMISSION, NOT_MAYOR, ALREADY_CLAIMED,
MAX_CHUNKS_REACHED, CITIZEN_LIMIT_REACHED, NOT_ADJACENT,
INSUFFICIENT_FUNDS, CANCELLED
UnclaimResult : SUCCESS, TOWN_NOT_FOUND, NO_PERMISSION, NOT_MAYOR, NOT_OWNED,
IS_HOME_CHUNK, LAST_CHUNK, WOULD_DISCONNECT
```
Changed signatures:
| Before | After |
|--------|-------|
| `claimChunk(townUuid, chunk)` β `Boolean` | `claimChunk(townUuid, chunk, actorUuid)` β `ClaimResult` |
| `unclaimChunk(townUuid, chunk)` β `Boolean` | `unclaimChunk(townUuid, chunk, actorUuid)` β `UnclaimResult` |
| `disbandTown(townUuid)` β `Void` | `disbandTown(townUuid, actorUuid)` β `Boolean` |
| `togglePvp(townUuid)` β `Boolean` | `togglePvp(townUuid, actorUuid)` β `Boolean` (null = denied) |
| `addDeputy(townUuid, playerUuid)` | `addDeputy(townUuid, playerUuid, actorUuid)` |
| `removeDeputy(townUuid, playerUuid)` | `removeDeputy(townUuid, playerUuid, actorUuid)` |
All 12 call sites now `switch` on the result.
### ποΈ Nation Interface
- π¨ **NationMenuPage reworked** into a dashboard, with `NationDashboardPage.ui` and a dedicated
`NationNavBar.ui` navigation bar
- π§ Navigation added between the nation pages
### πΊοΈ Map
- π¨ **Improved claim rendering** β `ClaimImageBuilder` now accounts for fluid particle colour,
environment water tint and block tint when generating the map image
### π Internationalization
- π¬π§π«π· **12 new keys** in both languages: protection denials, cancellations by a third-party
mod, already-claimed chunk
### π§Ή Code Quality
- β
`@Nonnull` annotations enforced across commands and GUI components
- π¦ `manifest.json` reformatted; `ServerVersion` now uses the `^${hytale_build}` placeholder
resolved at build time
- ποΈ `updatePluginManifest` build task reworked
### π Documentation
- π **[docs/API.md](docs/API.md)** β full public API reference
### π Not Yet Implemented
Admin SafeZone/WarZone, broader ECS coverage (item drop/pickup, death, respawn, mounts, NPCs),
per-UUID storage locks, GFS backups, versioned migrations, taxes/upkeep/debt, per-town and
per-plot permission matrix, town chat, outposts, town levels, PAPI placeholders.
All Relations
- All Relations
- Embedded Library
- Optional Dependency
- Required Dependency
- Tool
- Incompatible
- Include

