π Placeholder & API
Placeholders
PlaceholderAPI, under the identifier polaroidchat. Written as %polaroidchat_<name>%.
| Placeholder | Gives |
|---|---|
nick | Their nick, wearing its colour and style |
nick_raw | Their nick as plain text |
nick_has | Whether they have one at all |
nick_cooldown | How long until they may change it |
nickcolor_has | Whether a nick colour is applied |
nickcolor_type | legacy, hex, gradient or animate |
nickcolor_displayname | The name of the colour they are wearing |
nickcolor_styles | The formats on top of it |
nickcolor_preview | A sample drawn in that colour |
chatcolor_* | The same five, for their chat colour |
The API
PolaroidChatAPI.get() after the plugin has enabled.
PolaroidChatAPI api = PolaroidChatAPI.get();
String nick = api.getNick(uuid);
api.setNick(player, "Steve");
api.resetNick(player);
AppliedColor colour = api.getChatColor(uuid);
api.setChatColor(player, colour);
api.resetChatColor(player);
The nick-colour trio (getNickColor, setNickColor, resetNickColor) matches.
AppliedColor carries the colour's type, its values, its id and the formats on it β the same
shape the storage holds.
Events
Two, both cancellable, fired in order.
PolaroidPreChatEvent β before anything is built. The place to change what was said or who
hears it.
@EventHandler
public void onPreChat(PolaroidPreChatEvent event) {
event.getSender();
event.getRawText();
event.setRawText("β¦"); // change the message
event.getReceivers(); // mutable β add or remove
event.getChannelId();
event.addMarker(uuid, comp); // attach a component for one receiver
event.setCancelled(true);
}
PolaroidChatEvent β after the line is built, before it is sent.
@EventHandler
public void onChat(PolaroidChatEvent event) {
event.getPrefixComponent(); // everything before the message
event.getMessageComponent();
event.setMessageComponent(c);
event.getReceivers();
event.getMarkers();
event.setCancelled(true);
}
Markers are how a per-receiver difference is expressed: a component attached against one player's uuid reaches only them, so one message can read differently for one reader without being sent twice.
Optional integrations
None are required. Each is detected at startup and silently skipped if absent.
| Plugin | Used for |
|---|---|
| PlaceholderAPI | Placeholders in every field, and the expansion above |
| Vault | %vault_group% in chat formats |
| LuckPerms | Picking a chat format by group weight |
| Floodgate | Native forms for Bedrock players |
| Nexo | <glyph:β¦> in messages, and nexo:id items in menus |
| CustomNameplates | Nameplates that follow the nick |
| SkinsRestorer | Skins behind <head:β¦> |
| SimpleVoiceChat | Voice groups alongside channels |
Items in menus
Any of these can supply an item by name, written as plugin:id in a menu's material:
MythicMobs Β· ItemsAdder Β· Oraxen Β· CraftEngine Β· HeadDatabase Β· MMOItems Β· ItemEdit Β· WeaponMechanics Β· ExecutableItems Β· ExecutableBlocks Β· EcoItems Β· eco
Plus two that need no plugin: itemmodel:minecraft:trophy for an item_model component
(1.21.4+), and a textured or named head.
Building from source
Needs JDK 21. Newer JDKs are not yet parsed by the Gradle version in use.
export JAVA_HOME=/path/to/jdk-21
./gradlew shadowJar # build/libs/PolaroidChat-<version>-b<build>.jar
./gradlew test
./gradlew shadowJar -Pbuild=42 stamps a build number; without one it is local.
MySQLStorageContractTest needs Docker (Testcontainers) and fails without it. Every other test
runs anywhere.