Files
Iris/docs/09 - PlaceholderAPI.md
T
Brian Neumann-Fopiano ebfe278b3b Docvks
2026-08-10 15:47:26 -04:00

9.8 KiB
Raw Blame History

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; related runtime and integration details are in 07 - Pregeneration.md and 28 - Integrations.md.

Tutorial: verify a placeholder before using it in another plugin

Prerequisites: Bukkit-family Iris, PlaceholderAPI installed before Iris enables, a full server restart, and a player in a loaded Iris world.

  1. Confirm registration: /papi info iris. The output must list expansion id iris and its published paths.
  2. Confirm the service: /papi parse me %iris_available%. Expect true while Iris terrain service is live.
  3. Confirm player context: /papi parse me %iris_world.available%. Expect true while the named player is in an Iris world.
  4. Parse a concrete terrain value: /papi parse me %iris_world.biome-key%. Expect a load key such as desert/hot-dunes, not ---.
  5. While standing in the Iris world, run /iris pregen start 352 center=0,0 gui=false, then parse /papi parse me %iris_pregen.percent%. Expect a numeric value from 0.00 through 100.00 with no percent sign.
  6. Stop with /iris pregen stop or let the job finish, then run /papi parse me %iris_pregen.available%. Expect false; other pregen values return --- after the snapshot clears.
  7. Copy the exact verified placeholder into the scoreboard, chat, or HUD plugin and test that consumer once more.

The workflow passes when registration, player-scoped terrain, and global pregen values each produce their documented value shape. Do not debug formatting in the consuming plugin until direct /papi parse succeeds.

Recovery

Symptom Meaning Recovery
/papi info iris has no expansion PlaceholderAPI was unavailable when Iris scheduled registration Perform a full restart with both plugins installed; /papi reload alone does not trigger Iris registration
Placeholder remains literal Path is unknown or uses a removed pre-2.0 name Copy an exact path from /papi info iris or the full table below
World value is --- No online player context, player is outside Iris, or terrain service has no reading Parse as a named online player after entering a loaded Iris world
world.available is true but biome lags movement Player view cache is within its one-second TTL Wait one second or trigger an immediate publish by teleport/world change before diagnosing the consumer
Pregen value is --- No global job snapshot is active Start a job and wait for its first event; use pregen.available as the guard in board templates
Scoreboard adds % twice pregen.percent deliberately omits the suffix Add one literal % in the consumer format, not in the placeholder

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.00100.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.