MCME Wiki

Guidebook welcomes players to the places they walk into. Staff define named Areas in a world; when a player enters
one, Guidebook shows the Area's title on screen and sends its description in chat, at most once a minute per Area.
Staff create and edit Areas from WorldEdit selections and Paper dialogs, Area text is MiniMessage with a few Guidebook
tags of its own, and every Area is drawn on the web map when Dynmap runs. This page describes 2.0.1, the latest
release on master (tag v2.0.1), the Paper 26.2 rewrite. The source is public at
MCME/Guidebook under the GPL-3.0 licence.

At a glance

Repository MCME/Guidebook
Release branch master (work goes to development first)
Version described 2.0.1 (tag v2.0.1, 2026-10-20)
Platform Paper, api-version: '26.2' (taken from the paper-api version at build time), load: POSTWORLD
Build Gradle 9.7.1 (Kotlin DSL, version catalogue), Java toolchain 25
Depends on WorldEdit and PluginUtils (hard, depend); Multiverse-Core and dynmap (soft)
Maven coordinate com.mcmiddleearth:Guidebook:2.0.1 on repo.mcmiddleearth.com

The repository has a GLOSSARY.md for its domain words
(Area, Shape, Warp point, Welcome, Opted out, …) and architecture decision records in
docs/adr. Read both before changing code.

How the code is organised

Everything lives under com.mcmiddleearth.guidebook.

Package Job
(root) GuidebookPlugin: on enable it picks the web map, loads the Areas, starts a check every second (20 ticks) of each online player against each enabled Area, and registers the command.
command GuidebookRoot declares /guidebook with StrokkCommands annotations; the annotation processor generates GuidebookRootBrigadier at compile time. AreaArgument and NewAreaNameArgument are custom argument types; GuidebookHelp holds the help table, filtered by permission.
data InfoArea (one Area: text, shape, enabled, the Welcome), Shape and AreaGeometry (sphere, cuboid, prism), AreaRegistry (lookup and suggestions), PlacementCheck and friends (overlap and clearance checks before saving), AreaFileLoader and LegacyMarkupConverter (loading, and the one-way conversion from 1.x markup), AreaMarkers (Area to map marker), and PluginData, the static store and file I/O.
dialog PlacementDialog (create and move), EditDialog (text and switches), ConfirmDialog (delete). Dialogs need a 1.21.6 or newer client.
events GuidebookSendEvent, the public extension point.
listener PlayerListener: forgets a player who quits.
util AreaText (renders MiniMessage plus the Guidebook tags), GuidebookMessages, DevUtil (debug output).
webmap A small vendor-neutral web map API (WebMap, MarkerLayer, Marker, Outline, MarkerStyle, NoWebMap), with the Dynmap adapter in webmap/dynmap. It imports nothing from Guidebook (ADR 0005), so it can move into a shared library later.
worldedit WorldEditSelections: reads a player's cuboid or polygon selection, and sets a selection from an Area's shape.

Building and testing

./gradlew build       # compile, run Spotless and the tests, write build/libs/Guidebook-<version>.jar
./gradlew runServer   # start a Paper test server in run/ with WorldEdit and PluginUtils downloaded

CI and releases. .github/workflows/build.yml builds and tests every push to master and development, every pull
request, and every v* tag, and uploads the jar as a workflow artefact. On a v* tag it then:

  1. checks that the tag matches the version in the built plugin.yml;
  2. takes the release notes from the tag's dated section in CHANGELOG.md (an "Unreleased" heading fails the run);
  3. publishes com.mcmiddleearth:Guidebook (with a sources jar) to repo.mcmiddleearth.com, releases or snapshots
    by the version suffix;
  4. creates the GitHub release with the jar and its .sha256, titled "version X for mc Y".

A manual run from the Actions tab also publishes. The releases repository refuses to overwrite a version, so each
version is published once. Publishing needs the MCME_MAVEN_NAME / MCME_MAVEN_SECRET organisation secrets; without
them only the publish step fails.

Configuration

Guidebook ships no config.yml. Its data folder holds:

File Holds
plugins/Guidebook/<world>/<area>.yml One file per Area. Keys include title, subtitle, description (MiniMessage), showTitle, showScoreboard (the boss bar), enabled and world, plus the shape and warp point. After editing a file by hand, run /guidebook reload.
plugins/Guidebook/config.yml excludedPlayers: the UUIDs of players who opted out with /guidebook off. Written when the plugin disables.
plugins/Guidebook-legacy-backup-<timestamp>/ Made once, on the first start of 2.x, before Area files in the 1.x markup are converted to MiniMessage. The conversion is one-way.

Area names are unique ignoring case and may contain only letters, digits and _ - . +. The convention is
<world>-<project>-<place>, and the name suggestions follow it.

Guidebook tags can be used in a title, subtitle or description next to MiniMessage's own tags: <guide>,
<date>…</date>, <term:'meaning'>, <wiki:page> (opens the page on Tolkien Gateway), <warp:name> (runs
/warp <name>) and <bullet>. They are permanent once stored text uses them (ADR 0004): a tag may change how it looks,
but removing or renaming one breaks every Area that uses it.

Commands and permissions

/guidebook is a Brigadier command with no aliases. Bare /guidebook, or an incomplete command, shows the help for
what the sender may run.

Command What it does Permission
/guidebook on / off Receive, or stop receiving, Welcomes. guidebook.user
/guidebook help [command] The commands you can use, or one in detail. guidebook.user
/guidebook create <world>-<project>-<place> Create an Area from your WorldEdit selection (or a sphere around you) in the Placement dialog; your position becomes the warp point. guidebook.staff
/guidebook move <area> Move or reshape an Area to your current selection, in the Placement dialog. guidebook.staff
/guidebook select <area> Set your WorldEdit selection to the Area's shape (you must be in its world). guidebook.staff
/guidebook edit [area] The Edit dialog for the named Area, or the one you stand in. guidebook.staff
/guidebook rename <area> <new-name> Rename an Area (and its file). guidebook.staff
/guidebook delete <area> Delete an Area after a confirmation dialog (players only). guidebook.staff
/guidebook warp <area> Teleport to an Area's warp point. guidebook.staff
/guidebook list [filter] [page] List Areas, 10 per page, with edit / warp / select / delete buttons. guidebook.staff
/guidebook reload Reload every Area from its file. guidebook.staff
/guidebook dev [console <true\|false> \| level <n> \| watch \| unwatch] Show or change the debug output. guidebook.staff
Permission Default Grants
--- --- ---
guidebook.user true on, off and help.
guidebook.staff op Every /guidebook command.

When you add a subcommand, put its @Permission on an @Executes("<name>") with a non-empty path, never on the class:
an empty path puts the permission on the /guidebook root and locks guidebook.user players out (ADR 0001).

APIs and extension points

GuidebookSendEvent (com.mcmiddleearth.guidebook.events) is fired on the main thread just before a player gets a
Welcome. It is Cancellable; getPlayer() gives the player and getGuidebookName() the Area's name. Cancelling it
stops that Welcome. It is not fired when the per-Area cooldown (one minute) suppresses the Welcome, and it is fired
before Guidebook checks whether the player opted out.

To compile against it:

repositories {
    maven("https://repo.mcmiddleearth.com/releases")
}

dependencies {
    compileOnly("com.mcmiddleearth:Guidebook:2.0.1")
}

Then add Guidebook to your plugin's depend or softdepend. No MCME plugin listens for the event today.

The web map API in webmap is deliberately generic (layers of markers with a circle or polygon outline and a
plain-text popup), so supporting another map (BlueMap, squaremap, Pl3xMap) means one new adapter. It is meant to move
into a shared MCME library; until then it is internal to Guidebook.

How it talks to other plugins and systems

System Direction How
WorldEdit reads and writes selections create and move read the player's cuboid or polygon selection; select sets it from an Area.
PluginUtils uses Every Area's shape is a PluginUtils region (CuboidRegion, PrismoidRegion, SphericalRegion), so no Area loads without it. Its message parser is used for the 1.x markup conversion.
Dynmap writes Through DynmapWebMap: one layer, Guidebook (hidden by default), with each Area's outline, enabled state and text as a staff review aid.
Multiverse-Core load order Soft dependency only, so Guidebook enables after Multiverse has loaded its worlds and saved Areas can find their world.
/warp runs The <warp:name> tag makes clickable text that runs /warp <name>; on MCME that command comes from MCME-Warps.
flowchart LR
  S[Staff: /guidebook create, move, edit] --> WE[WorldEdit selection]
  S --> D[Paper dialogs]
  D --> F[(Area files per world)]
  F --> PU[PluginUtils regions]
  T[Every second: player inside an Area?] --> E{GuidebookSendEvent cancelled?}
  E -- no --> W[Welcome: title, boss bar, chat]
  F --> M[Dynmap layer 'Guidebook']

Further reading