Waypoint Configuration

Author attunable fast-travel shrines — the interactable block that makes one, and the registry a milestone's waypoint reward resolves against.

An attunable waypoint is a shrine a player discovers, interacts with, and thereafter can travel back to. Attuning is the reward; the travel itself is the recall item’s existing interruptible channel, redirected to whichever waypoint the player has picked on the world map.

There are two halves to authoring one, and most content only needs the first:

  1. The shrine itself — a waypoint: block on an interactable. Interacting with it attunes it. This is all a normal shrine needs, and it is the only form that works for a shrine placed by world generation.
  2. The registry (waypoint-config.yaml) — a table of fixed sites with known coordinates, so an Almanac milestone whose reward is family: waypoint has something to resolve its id to.

How attunement works

  • A player interacts with a shrine within its interact-range. If the shrine is behind an access lock, the lock is checked first — a denied interaction attunes nothing.
  • The attunement records the player’s own position, not the shrine’s. A waypoint returns the player to a spot they were already standing in, which is by construction somewhere they fit; a shrine’s own origin may sit inside its hitbox.
  • Attunements are per player and saved with them. Two players in one world attune independently, and a joiner arrives with none.
  • Re-interacting with a shrine already attuned refreshes its recorded position rather than adding a second entry.
  • The shrine gives no built-in feedback beyond the map updating. If you want a visible or audible response, add it in the shrine’s own server-on-interact script (see Lua Hooks) or by changing its state.

The player then opens the world map, where every attunement appears in a travel list (and, for the world being drawn, as a marker). Picking one only sets a destination — nothing teleports. The next time the player uses their recall item, the channel completes at that waypoint instead of at home. Picking the already-selected entry again clears it, and recall goes back to home.

Because the destination is spent by the recall channel, waypoint travel inherits that channel’s rules: it takes time, and taking a hit interrupts it.


Making an interactable a shrine

Add a waypoint: block to an entry in your interactable-config.yaml:

interactables:
  - name: TODO_NAME
    hitbox:
      width: 2.0
      height: 3.0
    breakable: false
    waypoint:
      id: TODO_NAME
      display-name: TODO_NAME
FieldRequiredDescription
idyesStable identifier for the site, namespaced to <mod>:<id> internally. This is what a player’s attunement set records, and what a milestone reward names. See Id rules below.
display-nameyesWhat the player reads for this site on the world map. Required — without it the map would have to fall back to the raw id, which is an internal identifier and not written to be read.

There is deliberately no position here: the position comes from the player at attune time, which is what lets the same shrine be placed anywhere, including by world generation.

breakable: false is not required but is usually right — a fast-travel target that can be mined away is a trap.

Two shrines, one attunement

Two interactables may share an id on purpose: attuning either one attunes the same entry, and the most recently touched position wins. Use it when one logical destination has several physical approaches.


The waypoint registry

A milestone reward carries only an id, so a site granted that way needs its world, position and name declared up front. That is what waypoint-config.yaml is for. A procedurally-placed shrine cannot be granted this way — nothing knows where it is until the world generates — so a milestone-granted waypoint has to be an authored, fixed site.

Register the file in your mod’s manifest (mods/<YourMod>/<YourMod>.yaml):

waypoint-config: waypoint-config.yaml

Then create the file it points to, relative to your mod’s folder:

waypoints:
  - id: TODO_NAME
    world: Genesis
    position:
      x: 1280
      y: -64
    display-name: TODO_NAME
FieldRequiredDescription
idyesThe site’s id, matching the waypoint.id on its interactable if it has one. Namespaced to <mod>:<id>.
worldyesThe world the site is in, as named in the world registry.
positionyesA { x, y } map of block coordinates the player arrives at. Nested rather than two sibling keys so a half-specified location is a load error instead of a silent (0, 0).
display-nameyesWhat the player reads for this site on the world map.

Unknown keys are rejected: a misspelled field is a load-time error naming the bad key, not a silently-ignored one.

A duplicate id fails the second entry — otherwise which one a reward resolved to would depend on load order.

Paying one out from a milestone

With the site registered, an Almanac milestone can grant it:

milestones:
  - id: TODO_NAME
    chapter: discoveries
    metric: worlds
    threshold: 3
    reward:
      family: waypoint
      id: TODO_NAME     # the registry id above

The grant is applied on the player’s next tick, and is idempotent — a reward already attuned does nothing. A reward naming a site no waypoint-config.yaml declares is logged as a warning and stays recorded, so it applies later if the entry is added.


Id rules

A mod may only declare waypoint ids in its own namespace. Writing id: OtherMod:their_shrine in your config is a load-time error, in both the interactable block and the registry — otherwise a mod could declare a site under another mod’s namespace and have its own shrine satisfy that mod’s reward. Referring to another mod’s waypoint is fine; declaring one is not.

A bare id: shrine_a in mod Creation becomes Creation:shrine_a. Writing that qualified form yourself is allowed and is not double-prefixed.


Complete Example

interactable-config.yaml:

interactables:
  - name: TODO_NAME
    hitbox:
      width: 2.0
      height: 3.0
    requires-supporting-blocks: true
    breakable: false
    interact-range: 6.0
    light:
      magnitude: 8.0
      color: [180, 240, 200]
    waypoint:
      id: TODO_NAME
      display-name: TODO_NAME
    scripts:
      server-on-interact: /interactables/waypoint-shrine/scripts/server_interact.lua

waypoint-config.yaml:

waypoints:
  - id: TODO_NAME
    world: Genesis
    position:
      x: 1280
      y: -64
    display-name: TODO_NAME

Last updated