mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-08-27 12:41:43 +00:00
156 lines
7.3 KiB
Markdown
156 lines
7.3 KiB
Markdown
# 09 - PlaceholderAPI
|
||
|
||
Iris registers the `iris` PlaceholderAPI expansion on Bukkit-family servers when PlaceholderAPI is enabled at Iris enable time. It publishes sixteen keys: seven world-family readings for the player and nine global pregeneration keys. This is an operator board contract, not a Java API; plugins that need the same data with more precision use `90 - API - Getting Started.md`, `91 - API - Terrain.md`, and `92 - API - World Events.md`. PlaceholderAPI is not available on Fabric/Forge/NeoForge. See also `07 - Pregeneration.md` and `28 - Integrations.md`.
|
||
|
||
## Registration
|
||
|
||
| Item | Value |
|
||
|---|---|
|
||
| Expansion id | `iris` |
|
||
| Expansion version | `2.0.0` |
|
||
| Author string | `Volmit Software` |
|
||
| Required plugin | `Iris` |
|
||
| Soft-depend | `PlaceholderAPI` in `plugin.yml` |
|
||
| `persist()` | `true` — survives `/papi reload` without Iris restart |
|
||
|
||
Iris schedules setup after enable. If PlaceholderAPI is not enabled then, the expansion is not registered and there is no late `PluginEnableEvent` re-attempt. Soft-depend alone does not load PlaceholderAPI.
|
||
|
||
List published paths with `/papi info iris`.
|
||
|
||
## Value grammar
|
||
|
||
| Rule | Detail |
|
||
|---|---|
|
||
| Path form | Dot-separated, lowercase, no underscores. Iris lowercases the path before resolve, so `%iris_WORLD.BIOME%` works, but write lowercase |
|
||
| Plain text only | No color codes, no unit suffixes, no `%` in values, `.` as decimal separator, no thousands grouping |
|
||
| Pack name scrubbing | Section-sign sequences and `%` characters inside pack-authored names are stripped before return |
|
||
| Real zero | `0` (or `0.00` for two-decimal numbers), never `---` |
|
||
|
||
Three answers:
|
||
|
||
| Answer | When | Board shows |
|
||
|---|---|---|
|
||
| A value | Known key with data | The value |
|
||
| `---` | Known key with no data right now | `---` |
|
||
| Nothing (null to PAPI) | Unknown path | Literal `%iris_...%` |
|
||
|
||
Unknown paths stay visible on purpose. There is no catch-all blank fallback.
|
||
|
||
## Full key table
|
||
|
||
### World family
|
||
|
||
| Placeholder | Value |
|
||
|---|---|
|
||
| `%iris_available%` | `true` when the Iris terrain service is live, `false` otherwise |
|
||
| `%iris_world.available%` | `true` when the reading player is in an Iris world and a reading exists |
|
||
| `%iris_world.biome%` | Surface biome display name at the player column (example: `Hot Desert Dunes`) |
|
||
| `%iris_world.biome-key%` | Surface biome load key (example: `desert/hot-dunes`) |
|
||
| `%iris_world.region%` | Region display name at the player column |
|
||
| `%iris_world.region-key%` | Region load key |
|
||
| `%iris_world.dimension%` | Dimension (pack) load key of the player's world |
|
||
|
||
`%iris_available%` does not need a player. Every other `world.*` key needs a tracked online player. Console, offline player, or untracked position: `world.available` is `false` and the rest are `---`.
|
||
|
||
### Pregeneration family
|
||
|
||
| Placeholder | Value |
|
||
|---|---|
|
||
| `%iris_pregen.available%` | `true` while a pregeneration job is running |
|
||
| `%iris_pregen.world%` | World name the running job is pregenerating |
|
||
| `%iris_pregen.percent%` | Completion `0.00`–`100.00`, no `%` character |
|
||
| `%iris_pregen.eta%` | Estimated seconds remaining, whole number |
|
||
| `%iris_pregen.eta-text%` | Same estimate as `45s`, `2m 5s`, or `1h 30m` |
|
||
| `%iris_pregen.chunks%` | Chunks generated so far |
|
||
| `%iris_pregen.total%` | Chunks in the job |
|
||
| `%iris_pregen.chunks-per-second%` | Current rate, two decimal places |
|
||
| `%iris_pregen.paused%` | `true` while the job is paused |
|
||
|
||
`pregen.*` is global (one job per server). Values match for every player and the console. Snapshot is published on pregen events (`STARTED`, `TICK`, `PAUSED`, `RESUMED`, `SAVING`) and cleared on `COMPLETED` or `CANCELLED`. After clear, `pregen.available` is `false` and other `pregen.*` keys are `---`. Before enough chunks exist for an ETA, `eta`/`eta-text` read `0` / `0s`.
|
||
|
||
### Paths as reported by `/papi info iris`
|
||
|
||
```
|
||
available
|
||
pregen.available
|
||
pregen.chunks
|
||
pregen.chunks-per-second
|
||
pregen.eta
|
||
pregen.eta-text
|
||
pregen.paused
|
||
pregen.percent
|
||
pregen.total
|
||
pregen.world
|
||
world.available
|
||
world.biome
|
||
world.biome-key
|
||
world.dimension
|
||
world.region
|
||
world.region-key
|
||
```
|
||
|
||
Prefix each with `%iris_` and suffix with `%`.
|
||
|
||
## Surface readings and cache
|
||
|
||
`world.biome`, `world.biome-key`, `world.region`, and `world.region-key` are **surface** column readings: the biome/region the generator places at ground level for that X/Z. A player in a cave under an overhang still reads the surface biome above, not the cave biome.
|
||
|
||
### Position tracking
|
||
|
||
| Event | Publish |
|
||
|---|---|
|
||
| Walking (`PlayerMoveEvent`) | At most once per second per player; skipped while the player stays in the same block column |
|
||
| Join, respawn, world change, portal, any teleport (including `/iris goto`, `/tp`, ender pearl, random TP) | Immediate |
|
||
|
||
Standing still never keeps a stale column from a previous place after an immediate publish. Quit releases the player's position and world view.
|
||
|
||
### View rebuild TTL
|
||
|
||
World views rebuild at most **once per second per player** (`VIEW_TTL_MS = 1000`), and only when something reads a `world.*` key that needs the view. Consequences:
|
||
|
||
- A board full of `world.*` keys costs one rebuild per player per second
|
||
- Values can lag a sprinting player by up to one second
|
||
- An unread board costs no terrain queries
|
||
|
||
### Pregen snapshot
|
||
|
||
Pregen values come from a single global snapshot updated by `IrisPregenerationEvent`, not per-player polling.
|
||
|
||
## Permissions
|
||
|
||
Iris never gates a placeholder on a permission. Values that should not be public (for example world seed) are not published.
|
||
|
||
## Failure policy
|
||
|
||
| Situation | Shown |
|
||
|---|---|
|
||
| Unknown path | Nothing (literal `%iris_...%`) |
|
||
| Known path, no data | `---` |
|
||
| No player context on `world.*` | `---` and `world.available` = `false` |
|
||
| Player not in an Iris world | `---` and `world.available` = `false` |
|
||
| Terrain service not registered | `---` / `world.available` = `false` / `%iris_available%` = `false` |
|
||
| No pregen job | `---` / `pregen.available` = `false` |
|
||
| Resolver throws | `---`; one warning per distinct path, max 64 distinct paths |
|
||
|
||
Failed keys are not quarantined; they keep answering `---`.
|
||
|
||
## Migration from pre-2.0 keys
|
||
|
||
Pre-2.0 underscore keys are gone. No alias and no dual-accept window. Old keys render literally.
|
||
|
||
| Old key | New key | Notes |
|
||
|---|---|---|
|
||
| `%iris_biome_name%` | `%iris_world.biome%` | Dot grammar |
|
||
| `%iris_biome_id%` | `%iris_world.biome-key%` | `id` was always the load key |
|
||
| `%iris_region_name%` | `%iris_world.region%` | Dot grammar |
|
||
| `%iris_region_id%` | `%iris_world.region-key%` | `id` was always the load key |
|
||
| `%iris_biome_file%` | removed | Exposed absolute server paths; threw without a backing file |
|
||
| `%iris_region_file%` | removed | Same as `biome_file` |
|
||
| `%iris_world_seed%` | removed | No permission context on scoreboards; use terrain API `IrisWorldInfo.seed()` when a plugin needs seed |
|
||
| `%iris_terrain_height%` | removed | Generated height before objects/edits; disagreed with the block underfoot |
|
||
| `%iris_terrain_slope%` | removed | Expensive pack-authoring diagnostic |
|
||
| `%iris_world_mode%` | removed | Studio vs production is not a live-board concern |
|
||
| `%iris_world_speed%` | removed | Mutated engine rate-window state on read; use `%iris_pregen.chunks-per-second%` for pregen rate |
|
||
|
||
Behavior change inside the renames: old keys sampled two blocks above the player's feet (cave/overhang Y). New keys are always surface for the column. `%iris_world.dimension%` is new and has no pre-2.0 equivalent.
|