PokeLink (plugin)¶
Lets a player show off a Pokemon from their party in chat by typing [p1] to [p6]. The token
turns into the Pokemon's name, colored by its type, with a hover card that shows its stats.
What it does¶
- A player types
[p1]through[p6]in chat. Each token is one party slot. - The token becomes a link like
[Bulbasaur]. The name is colored by the Pokemon's main type. Shiny Pokemon get a gold star after the name. Eggs show asEgg. - Hovering the link shows a card with level, types, gender, nature, ability, held item, IVs, EVs, moves and original trainer.
- The card is drawn by battlecore's shared Pokemon display, so it looks the same as the GTS
listing and the Battle Tower team screen. If battlecore is missing, the plugin uses its own
card from
config.ymlinstead. - An empty slot cancels the message and tells the sender the slot is empty, so
[p6]is never sent as plain text.
PokeLink does not touch chat itself. ChatControl owns chat. PokeLink ships six ChatControl
"variable" files (p1.yml to p6.yml), the same kind as the stock [item] token, and fills
them through PlaceholderAPI.
How players use it¶
- Put the Pokemon you want to show in your party.
- Type a message with the slot token, for example:
look at my [p1]. - Others see
look at my [Charizard]. They hover it to see the card.
Things players may notice:
- The same token only works once per message.
[p1] vs [p1]expands only the first one. Different tokens are fine:[p1] vs [p2]expands both. This is how ChatControl works and cannot be changed. - If a slot is empty, the message is not sent and you see "You have nothing in party slot N."
- If you see "Pokemon links are not available right now.", the plugin is not loaded yet (see Troubleshooting).
Staff guide¶
| Task | Command | Who |
|---|---|---|
Re-read config.yml |
/pokelink reload |
pokelink.admin (op by default), or console |
/pokelink reload replies with PokeLink config reloaded (8 hover line(s)).
There is nothing to whitelist. [p1] is a chat token, not a command, so CommandWhitelist is not
involved.
To limit links to some players, add Sender_Permission: "pokelink.use" to each variable file and
grant that node. It is not set today, so everyone can link.
Configuration¶
Three parts, three ways to go live:
| File | Where on the server | How it goes live |
|---|---|---|
| The plugin jar | plugins/ |
Restart |
config.yml |
plugins/PokeLink/config.yml |
/pokelink reload |
p1.yml to p6.yml (in src/main/resources/chatcontrol-variables/) |
plugins/ChatControl/variables/ |
/chc reload |
Keys people change in config.yml:
| Key | What it does |
|---|---|
slots |
How many party slots have a token (1 to 6). The variable files must match. |
link.format |
The inline link, in MiniMessage. Tokens use braces, like {name}, {type_color}, {shiny}. |
link.shiny-marker, link.egg-name, link.fallback-color |
Shiny star, egg label, and the color used when the type is unknown. |
hover.use-shared-lore |
true uses battlecore's card. false uses hover.lines. |
hover.shared-lore-layout |
Which battlecore layout to draw. Keep chat_hover (the compact card). standard is the tall GUI card and covers the chat. |
hover.lines |
The fallback card, one row per line. Used on the Paper hub and when battlecore is missing. Keep it filled in even though use-shared-lore is on. |
type-colors |
Override the color for a type. Leave out a type to keep the default. |
sprite.* |
Sprites in chat. Leave enabled: false (see below). |
Tokens available in link.format and hover.lines: {name} {species} {nickname} {dex} {level}
{types} {gender} {nature} {ability} {held} {ivs} {iv_percent} {evs} {moves} {ot} {friendship}
{type_color} {shiny} {sprite} {slot}.
If a token cannot be read, the whole row is dropped. An egg or a missing field makes the card
shorter instead of showing "Ability: " with nothing after it. Put optional info on its own hover
row, not in link.format, or the whole link disappears.
Which rows the shared card shows is set on the server in config/battlecore/lore/chat_hover.json.
Each row there has its own enabled flag. After changing it, run /pokelink reload. A new field
added to battlecore shows up here with no PokeLink rebuild.
If you write your own hover.lines, your list replaces the built-in one fully. If you delete the
whole hover section, the plugin falls back to its built-in rows.
Sprites cannot be turned on from the server alone. Chat can only draw a picture if the
player's client has a resource pack with a font for it. Pixelmon has no such font. With no pack,
every player sees a missing-glyph box. A pack would be cheap (pure JSON that points at Pixelmon's
own textures) and could ship through resource-pack= in server.properties or the modpack
overrides. Glyph = codepoint-base + national dex number, plus shiny-offset for shinies.
Data and storage¶
None. PokeLink saves nothing. It reads the party Pixelmon already has loaded for the sender.
Troubleshooting¶
| Symptom | Cause | Fix |
|---|---|---|
| "Pokemon links are not available right now." | The variable files are live but the jar is not loaded yet, or PlaceholderAPI is down | Restart the server so the jar loads. Check the boot log for the ready line |
Literal [p1] stays in chat |
The variable files are missing, or a variable's script broke | Check plugins/ChatControl/variables/p1.yml exists, then /chc reload |
Second [p1] in a message is plain text |
ChatControl only expands each token once per message | Expected. Use different slots |
| Card is plain gray, not the colored shared card | battlecore is missing or too old, or use-shared-lore is false |
Check battlecore is installed and has PokemonLoreService |
| No EVs row on the fallback card | Pixelmon has no EVStore.getShorthand |
Expected. The shared battlecore card shows EVs |
| Every slot says empty on the Paper hub | The hub has no Pixelmon | Expected. Do not install the variable files on the Paper hub |
Boot log lines that mean it loaded:
[PokeLink] PokeLink ready: 6 slot(s), Pixelmon bound, sprites off.
On the Paper hub it says Pixelmon unavailable instead. That is normal. A boot warning
Pixelmon method EVStore.getShorthand is missing; that hover row will be omitted is also normal.
If you see PlaceholderAPI is not installed - party links will not render., install
PlaceholderAPI and restart.
Test as a non-op. With a Pokemon in slot 1, type hey look at [p1]. Check the link is colored,
the hover has no blank rows, and [p6] with an empty slot 6 cancels the message. Send from a
second backend too: the card is built on the sender's backend, so every backend needs both the jar
and the variable files.
To remove the feature: delete the six variable files and run /chc reload. Chat goes back to
normal right away. The jar can stay; it does nothing without the variables.
Maintainer notes¶
- How it talks to ChatControl. ChatControl
Type: MESSAGEvariables call PlaceholderAPI. The placeholders are%pokelink_name_N%(the link),%pokelink_hover_N%(the card, one string with newlines) and%pokelink_present_N%(true/false). PlaceholderAPI is used instead ofJava.typein the variable's JavaScript because ChatControl's script engine classloader may not see other plugins' classes. Valueis JavaScript,Hoveris not. ChatControl pastes the placeholder into the JavaScript source before running it. Names like Farfetch'd have an apostrophe, so thenameplaceholder is JS-escaped and must stay inside single quotes. Thehoverplaceholder is not escaped.- Deploy-order guard. The first check in each variable file catches the case where
ChatControl has the variable but PlaceholderAPI has no
pokelinkexpansion yet (variables go live on/chc reload, the jar only on restart). Without it, the literal%pokelink_name_1%would be posted. It is not dead code. - Nicknames are an injection risk. ChatControl strips
<click>and<hover>fromValuebut not fromHover.Sanitizerremoves<,>and&from every row. It keeps§color codes on battlecore rows so the shared card stays colored. Custom names keep their colors in the card (battlecore'snickname_formatted), but click and hover events on a name are never read. Hex colors use Spigot's§x§R§R§G§G§B§Bform. Row length is capped by visible characters, and a color code cut in half is dropped. - One hover placeholder, not eight list entries. One string with newlines lets a dropped row shorten the card. Separate list entries would leave blank rows.
- The party read never blocks.
StorageProxy.getPartycan start a disk load, and chat runs on an async thread. The plugin checksisDone()and gives up otherwise. This is safe because ChatControl renders on the sender's backend, where the party is already loaded. - All Pixelmon and battlecore access is by reflection. A mod type in a class signature fails
while the plugin class loads, before
onEnable, so no try/catch can save it. That is how VaultTickets 1.0.0 died. Each Pixelmon getter is bound on its own, so a rename costs one row, not the feature. Keep it that way. battlecore is bound throughPokemonLoreService.render(Pokemon, String). IVStore.getPercentagealready returns 0 to 100. Do not multiply it again.- Defaults live in
PokeLinkConfigas well asconfig.yml, because Bukkit does not fall back to the jar for a missing section. A test pins the two together. - The token syntax
[key]is fixed by ChatControl's pattern. TheKey:in a variable file cannot change the brackets.
Building¶
./gradlew build
Java 21. Output: build/libs/PokeLink-<version>.jar. Paper API and PlaceholderAPI are compile-only.
Unit tests run with the build.
Full command, permission and config tables: Reference.