Für Server
Fern Server Link
Mach Fern auf deinem Server zu Hause: Erkenne Fern-Spieler, halte Matches fair und sprich mit Spielern, mit ein paar kleinen JSON-Nachrichten über Plugin-Kanäle.
Wissen, wer Fern spielt
Ein kleiner Handshake sagt deinem Plugin, welche Spieler Fern nutzen, nur wenn sie es erlauben.
Faire Matches
Schalte bestimmte Fern-Features auf deinem Server aus und sperre sie, mit einem Grund, den Spieler lesen können.
Hinweise
Kurze, begrenzte Einblendungen für Ankündigungen, Belohnungen oder Spielereignisse.
Timer auf dem Bildschirm
Countdowns oben am Bildschirm für Spielstarts, Events und Abklingzeiten.
Diese Seite gibt es nur auf Englisch.
How it works
Fern listens on a few plugin-message channels that all start with fern:. Every message is a small UTF-8 JSON object (max 8 KB).
The server always starts the conversation: Fern never announces itself on servers that don't ask.
Player joins
server ──► fern:welcome {"protocol": 1}
client ──► fern:hello {"client": "fern", "version": "0.1.0", ...} (only if the player allows it)
server ──► fern:rules / fern:notify / fern:timer (any time)
Player leaves → everything your server set is undone on the clientPlayers who don't use Fern simply ignore these channels — sending them is always safe.
Channels
| Channel | Direction | What it does |
fern:welcome | server → client | "This server supports Fern Server Link." Starts the handshake. |
fern:hello | client → server | Fern's answer: version, mod loader, enabled Fern mods. |
fern:rules | server → client | Turn off and lock Fern mods on your server. |
fern:notify | server → client | Show a notification (toast). |
fern:timer | server → client | Show, update or remove a countdown at the top of the screen. |
fern:waypoint | server → client | Planned: markers in the world. |
fern:presence | server → client | Planned: what the player's Discord status says while on your server. |
fern:welcome
{ "protocol": 1 }Send it once, shortly after the player joined (for example 1 tick after PlayerJoinEvent, so the client has registered its channels).
fern:hello (from the player)
{
"protocol": 1,
"client": "fern",
"version": "0.1.0",
"loader": "fabric",
"minecraft": "26.3",
"modules": ["fps", "zoom", "keystrokes"]
}Players can turn this off (Features → Server Features → Tell servers I use Fern). If you never receive a hello, treat the player as a normal player.
fern:rules
{ "disable": ["zoom", "fullbright"], "reason": "Not allowed in ranked matches" }- The listed mods are switched off and locked until the player leaves your server. The player sees the reason when they try to turn one back on.
- Rules only restrict. You can't turn mods on, change settings or unlock anything.
- Rules apply even when the player turned *Server Features* off — fair play comes first.
- Send
fern:rulesagain to lock more mods. Max 64 ids per message; unknown ids are ignored.
fern:notify
{ "title": "Welcome to Mossy Network", "body": "Season 3 starts today!" }titlemax 48 characters,bodymax 160. Formatting codes (§) are removed.- Max 5 notifications per 10 seconds per player; extra ones are dropped. Players can turn notifications off.
fern:timer
{ "id": "start", "label": "Game starts in", "seconds": 10, "color": "#4ADE80" }- Shows a countdown at the top centre of the screen, e.g. Game starts in 10s.
- Same
idagain = update it."seconds": 0= remove it. Max 3 timers, max 3600 seconds. coloris optional (hex). Players can turn timers off.
Module ids
| Id | Fern mod | Id | Fern mod |
fps | FPS | zoom | Zoom |
ping | Ping | toggle_sprint | Toggle Sprint |
coordinates | Coordinates | toggle_sneak | Toggle Sneak |
clock | Clock | fullbright | Fullbright |
keystrokes | Keystrokes | crosshair | Custom Crosshair |
cps | CPS | armor_status | Armor Status |
potion_effects | Potion Effects | direction | Direction |
memory | Memory |
New Fern mods get new ids; unknown ids are always ignored, so your rules keep working.
Example: Paper plugin
public final class FernLinkExample extends JavaPlugin implements Listener, PluginMessageListener {
@Override
public void onEnable() {
var messenger = getServer().getMessenger();
for (String ch : List.of("fern:welcome", "fern:rules", "fern:notify", "fern:timer")) {
messenger.registerOutgoingPluginChannel(this, ch);
}
messenger.registerIncomingPluginChannel(this, "fern:hello", this);
getServer().getPluginManager().registerEvents(this, this);
}
@EventHandler
public void onJoin(PlayerJoinEvent event) {
Player player = event.getPlayer();
// One tick later, so the client has told the server which channels it listens on.
getServer().getScheduler().runTaskLater(this, () -> send(player, "fern:welcome", "{\"protocol\":1}"), 1L);
}
@Override
public void onPluginMessageReceived(String channel, Player player, byte[] message) {
// Read and validate the JSON before trusting it — it comes from the player.
String hello = readString(message);
getLogger().info(player.getName() + " uses Fern: " + hello);
send(player, "fern:rules", "{\"disable\":[\"zoom\"],\"reason\":\"No zoom in ranked\"}");
send(player, "fern:notify", "{\"title\":\"Fern detected\",\"body\":\"Have fun!\"}");
}
private void send(Player player, String channel, String json) {
player.sendPluginMessage(this, channel, writeString(json));
}
// Minecraft strings: VarInt length + UTF-8 bytes.
private static byte[] writeString(String s) {
byte[] utf8 = s.getBytes(StandardCharsets.UTF_8);
var out = new ByteArrayOutputStream();
int len = utf8.length;
while ((len & ~0x7F) != 0) { out.write((len & 0x7F) | 0x80); len >>>= 7; }
out.write(len);
out.writeBytes(utf8);
return out.toByteArray();
}
private static String readString(byte[] data) {
int len = 0, shift = 0, i = 0, b;
do { b = data[i++]; len |= (b & 0x7F) << shift; shift += 7; } while ((b & 0x80) != 0 && shift < 35);
return new String(data, i, Math.min(len, data.length - i), StandardCharsets.UTF_8);
}
}Rules for servers
- Don't trust `fern:hello` for security decisions. Any client can claim to be Fern. Use it for comfort features only, never for anti-cheat or permissions.
- Use rules for fair play, not to punish Fern players. Fern players should never be at a disadvantage compared to vanilla players.
- Keep notifications useful and rare; players who find them spammy will turn them off.
- Respect the Minecraft EULA and Usage Guidelines.
Privacy
fern:hello only contains the Fern version, mod loader, Minecraft version and enabled Fern mod ids — no account data, hardware or files. Players can turn it off. Servers receive nothing from Fern unless they send fern:welcome first.
Changelog
| Protocol | Fern | Changes |
| 1 | 0.1 | welcome, hello, rules, notify, timer |