You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
FlorianMichael edited this page Mar 12, 2025
·
3 revisions
Introduction
Starting with ViaVersion 5.3.0, the player details protocol is an optional feature that allows platforms to communicate the native version of players across backend servers.
This enables more accurate version-specific handling on backend servers for plugins like anti-cheats. The current implementation supports Velocity (and BungeeCord),
sending a player's native version to backend servers automatically.
Payload structure
ViaVersion installed on a Velocity/Bungee proxy:
vv:proxy_details
Players using ViaFabric/ViaForge mods and joining the server:
vv:mod_details
platformVersion: The version of the proxy/platform.
version: The numeric protocol version of the player.
versionName: The readable version name of the player’s client.
How to use this API as a plugin developer?
Caution
Please be aware that custom payload data can of course spoofed by players. The vv:proxy_details channel is only validated when ViaVersion is present on the proxy.
If such spoofing can cause issues on your end, add a configuration to your plugin and have the custom payload listeners disabled by default.
importcom.google.gson.Gson;
importcom.google.gson.JsonObject;
importorg.bukkit.entity.Player;
importorg.bukkit.plugin.java.JavaPlugin;
importorg.bukkit.plugin.messaging.PluginMessageListener;
// Small without error handlingpublicclassExamplePluginextendsJavaPluginimplementsPluginMessageListener {
privatestaticfinalStringCHANNEL = "vv:proxy_details";
privatestaticfinalGsonGSON = newGson();
@OverridepublicvoidonEnable() {
this.getServer().getMessenger().registerIncomingPluginChannel(this, CHANNEL, this);
}
@OverridepublicvoidonDisable() {
this.getServer().getMessenger().unregisterIncomingPluginChannel(this);
}
@OverridepublicvoidonPluginMessageReceived(Stringchannel, Playerplayer, byte[] bytes) {
if (!channel.equals(CHANNEL)) {
return;
}
finalJsonObjectpayload = GSON.fromJson(newString(bytes), JsonObject.class);
finalintversion = payload.get("version").getAsInt();
// Store into a custom player object
}
}