Compatibility
Minecraft: Java Edition
Platforms
Links
Creators
Details
WARNING:before download this plugin
Before downloading this plugin, please be aware that changes to UUIDs may result in the loss of existing online player data.
Please purchase the legitimate version of Minecraft from the official Minecraft website. The plugin author endorses and recognizes only legitimate copies of Minecraft.
ahiropg-online
A small Velocity proxy plugin that gives premium players their real Mojang UUID on an offline-mode proxy, while players without a Mojang session still get the usual offline UUID.
One job, done at login, per connection.
The problem it solves
Running a proxy with online-mode=false is the only way to accept players who do not
own a Minecraft account, but it has a side effect: Velocity hands everyone an
offline UUID (a hash of OfflinePlayer:<name>).
For players who do own the game, that breaks everything keyed to their Mojang UUID:
ranks, playtime, economy balances, region ownership, whitelists, cross-server player
data. Switching the proxy to online-mode=true fixes that and immediately locks out
every unauthenticated player.
This plugin keeps the mixed-mode setup. Premium players keep their Mojang UUID; everyone else keeps the offline UUID.
| Who logs in | UUID forwarded to your backend |
|---|---|
| Premium account, premium client | the real Mojang UUID, e.g. 5c89121b-4e93-46bd-80c9-3022a01c5bbd |
| Premium account, but logging in offline this time | the offline UUID, e.g. 0b5461e0-ea56-3019-8b05-6f4330752d8b |
| Player with no Mojang account | the offline UUID |
| Third-party auth launcher (skin sites) | the offline UUID |
How it decides who is premium
Since Minecraft 1.20.2, a client always sends its own UUID during login. Velocity
exposes it as PreLoginEvent#getUniqueId(), and it reveals what the client intends:
| Client | Declares |
|---|---|
| Premium launcher with a valid session | the account's real Mojang UUID |
| Offline launcher | the offline UUID it computed itself |
| Third-party auth launcher | that site's own UUID |
So the plugin compares the declared UUID against the offline UUID for that name:
- equal → the client means to join offline → allowed in as an offline player
- equals the Mojang UUID of that name → the client claims to be premium → Velocity
is told to verify this one connection even though the proxy is offline
(
forceOnlineMode()); a real session yields the premium UUID, a forged one fails the encryption handshake and Velocity disconnects it - anything else → configurable fallback; by default the player is let in as offline rather than kicked
Session verification itself is done by Velocity, not by this plugin. The plugin never fakes a login; it only decides which login mode a connection gets.
Because admission depends on the declared UUID rather than on the name, a player whose name happens to match a premium account is not blocked and not accidentally treated as premium. They send the offline UUID and take the offline path like anyone else.
Getting the UUID to your backend
Route 1 — the login handshake, nothing to install. When Velocity connects to a
backend it forwards the player's GameProfile including the UUID, and the plugin has
already set that UUID to its verdict. Your backend has the correct UUID from the first
tick. If your backend already reads the GameProfile UUID (BungeeGuard-style setups,
bungeecord: true + modern forwarding), you are done at this point.
Route 2 — a plugin message, for backend plugins that want to double-check or store
the verdict. Once the player is on a backend, the plugin pushes ahiropg:online:
| Field | Type |
|---|---|
| protocol version | byte, currently 1 |
| player name | UTF |
| UUID | UTF, dashed form |
| premium | boolean |
UTF is DataOutputStream#writeUTF (2-byte length + UTF-8 bytes). Receiving side:
public final class OnlineBridge extends JavaPlugin implements PluginMessageListener {
private static final String CHANNEL = "ahiropg:online";
@Override
public void onEnable() {
getServer().getMessenger().registerIncomingPluginChannel(this, CHANNEL, this);
}
@Override
public void onPluginMessageReceived(String channel, Player player, byte[] message) {
if (!CHANNEL.equals(channel)) {
return;
}
try (DataInputStream in = new DataInputStream(new ByteArrayInputStream(message))) {
byte version = in.readByte();
String name = in.readUTF();
UUID uuid = UUID.fromString(in.readUTF());
boolean premium = in.readBoolean();
getLogger().info(name + " uuid=" + uuid + " premium=" + premium);
} catch (IOException e) {
getLogger().warning("Failed to parse an ahiropg:online message: " + e);
}
}
}
The channel name is configurable, so change both sides together.
Recording and the "session dropped" notice
Every login is recorded in plugins/ahiropg-online/users.yml: name, whether the account
has ever passed premium verification, its Mojang UUID, its offline UUID, the UUID
actually forwarded, and first/last seen timestamps. The file is flushed in batches on a
timer and on shutdown, written through a temp file plus an atomic move.
If an account has joined as premium before but is offline this time, its owner receives a configurable chat message — the usual cause is an expired session, or a launcher that silently switched to offline login. Players who have never joined as premium never see it.
Configuration
The plugin creates plugins/ahiropg-online/config.yml on first start. Every key is
documented in the file; the important ones:
| Key | Default | Meaning |
|---|---|---|
session-policy |
HYBRID |
HYBRID decides per connection; PROXY does nothing and follows velocity.toml |
hybrid.allow-offline-connections |
true |
set false to reject offline connections and run a premium-only network |
hybrid.legacy-client-policy |
offline |
what to do with clients 1.19.2 and older, which declare no UUID |
hybrid.mojang-unavailable-policy |
offline |
fallback when the Mojang API cannot be reached |
forward.channel |
ahiropg:online |
plugin messaging channel |
forward.on-server-switch |
true |
push the identity again on every backend switch |
forward.override-uuid |
true |
force the forwarded GameProfile UUID to the verdict |
offline-notice.enabled |
true |
enable the "your session dropped" message |
offline-notice.message |
— | supports %player%, %uuid%, & colour codes and MiniMessage |
No commands, no permissions — configuration is the whole interface.
What this plugin does not do
Stated plainly, so nobody buys into the wrong thing:
- It does not switch your proxy to online mode. It only asks Velocity to verify individual connections that claim to be premium.
- It does not block players without an account unless you set
allow-offline-connections: false. Out of the box the network stays mixed. - It is not an authentication plugin. It does not add passwords or 2FA for offline players. It does not check anything on your backend servers.
- It does not protect against a compromised premium account. If someone has the real session, Velocity verifies them — same as vanilla online mode.
- It does not make a cracked client premium. Nothing can; a forged UUID only gets the connection forced into a handshake it cannot complete.
Requirements and installation
- Velocity 3.x (built against
velocity-api 3.4.0), Java 17+ - Drop the jar into the proxy's
plugins/, start once, adjustconfig.yml, restart - Backend servers need no plugin to receive the correct UUID; only read the plugin message if you want the extra data
Compatibility notes
- Clients 1.19.2 and older send no UUID, so intent cannot be determined; they fall
back to
legacy-client-policy. - Third-party auth launchers count as offline (they send their own UUID), so make sure your backend accepts offline UUIDs if you use one.
- Mojang API rate limits: a failed lookup falls back according to
hybrid.mojang-unavailable-policyand logs a warning. Offline connections never wait on the API; lookups run asynchronously and are cached. - Case sensitivity: offline UUIDs derive from the exact name the client logged in
with.
NapCatt_owoandNapcatt_owoare different players to this plugin, as they are to Velocity itself.
Source and licence
Source code, issue tracker and release notes: https://github.com/ShiroDyeNotFound/ahiropg-online
MIT licensed.

