Skip to content

feat: add stable session UUID to MinecraftConnection#1840

Open
xfy2412 wants to merge 4 commits into
PaperMC:dev/3.0.0from
xfy2412:dev/3.0.0
Open

feat: add stable session UUID to MinecraftConnection#1840
xfy2412 wants to merge 4 commits into
PaperMC:dev/3.0.0from
xfy2412:dev/3.0.0

Conversation

@xfy2412

@xfy2412 xfy2412 commented Jul 6, 2026

Copy link
Copy Markdown

Add a stable connection identifier to MinecraftConnection

A unique connectionId (AtomicLong) is held in MinecraftConnection,
the shared underlying instance across all InboundConnection wrappers,
surfaced via InboundConnection.getSessionId().

This allows plugins to reliably track the same TCP connection across
PreLoginEvent, GameProfileRequestEvent, and LoginEvent, even when
the InboundConnection wrapper object differs between events.

Tested with both online-mode and offline-mode connections:

  • Same connection across all login-phase events: same connId
  • Different players: different connId
  • Premium (Mojang-authenticated) connections: connId stable

@WouterGritter

Copy link
Copy Markdown
Member

You're using FQDN's in the code instead of importing, and I'd rather like to see the use of UUIDs instead of an incrementing ID here. This way the connection IDs are also unique across reboots (useful contract to have when exposing this to plugins)

@electronicboy

Copy link
Copy Markdown
Member

UUIDs also generally have the advantage that they're more useful should plugins want to externalise that identity for other systems, especially in a network

@xfy2412

xfy2412 commented Jul 6, 2026

Copy link
Copy Markdown
Author

I initially chose long (AtomicLong) thinking it could serve dual purpose as both a connection identifier and a rough connection counter for server operators who use such metrics. But your point about UUIDs being more useful for external systems and surviving reboots makes sense, I'm going to change it

@xfy2412

xfy2412 commented Jul 6, 2026

Copy link
Copy Markdown
Author

@electronicboy Done, please review again

@WouterGritter

Copy link
Copy Markdown
Member

I think we should shift from a per-connection id to a session id: one UUID that's stable for the player's entire session on the proxy, and shared across the client<->proxy connection and every proxy<->backend connection they open. So I'd name it sessionId rather than connectionId.

Right now that shared/stable property doesn't actually hold. Since every MinecraftConnection generates its own UUID.randomUUID() in the constructor:

  • each serverbound connection gets a different id, regenerated on every server switch, so it's neither stable nor shared with the client side
  • outgoing server-list pings (VelocityRegisteredServer) allocate an id they never use

It happens to work for the login-phase events only because the InboundConnection wrappers all delegate to the one clientbound MinecraftConnection, but that's incidental, not a contract we could promise to plugins.

What I'd propose:

  • @Nullable UUID sessionId on MinecraftConnection, passed in via the constructor
  • incoming client connections get a fresh id in ServerChannelInitializer: new MinecraftConnection(ch, server, UUID.randomUUID())
  • serverbound connections copy the player's id in VelocityServerConnection: new MinecraftConnection(channel, server, proxyPlayer.getConnection().getSessionId())
  • outgoing pings pass null

The null case is never reachable through InboundConnection, so the API can stay non-null by construction:

// VelocityInboundConnection
default UUID getSessionId() {
  return Objects.requireNonNull(getConnection().getSessionId(), "sessionId");
}

LoginInboundConnection just delegates to delegate.getSessionId(), InitialInboundConnection/ConnectedPlayer get it for free, and InboundConnection#getSessionId can be abstract + documented as non-null.

One thing to note is that this shouldn't be confused with Minecraft 26.2's new session ID (a shared "play session" UUID across every connected player that resets when the server goes from empty->non-empty). I'm not too sure if "session id" would be the right name here, but this could probably also be solved by a javadoc comment on InboundConnection#getSessionId (maybe proxySessionId? seems a bit too verbose).

@xfy2412

xfy2412 commented Jul 7, 2026

Copy link
Copy Markdown
Author

Hmmm… indeed, this is a scenario I didn't test before. I only tested multiple players joining the same backend server, but I didn't consider the case of switching between backend servers. I will test this scenario and make the necessary adjustments accordingly. Thanks for pointing this out!

@xfy2412

xfy2412 commented Jul 8, 2026

Copy link
Copy Markdown
Author

I also wrote a plugin for test

[13:42:36 INFO]: Booting up Velocity 3.5.0-SNAPSHOT (git-48e7519e)...
[13:42:36 INFO]: Connections will use NIO channels, Java compression, Java ciphers
[13:42:36 INFO]: Loading localizations...
[13:42:36 INFO]: Loading plugins...
[13:42:36 INFO]: Loaded plugin cidtest 3.5.0-SNAPSHOT by xfy2412
[13:42:36 INFO]: Loaded 2 plugins
[13:42:36 INFO] [cidtest]: CIDTest Loaded — Testing the stability of getSessionId()
[13:42:36 INFO]: Listening on /[0:0:0:0:0:0:0:0]:25565
[13:42:36 INFO]: Done (0.62s)!
[13:42:54 INFO] [cidtest]: [CIDTEST] PreLogin: xfy2102 connId=e1e309f8-e7c3-424c-8b02-56153af8633f hash=1834913037
[13:42:56 INFO] [cidtest]: [CIDTEST] GameProfileRequest: xfy2102 connId=e1e309f8-e7c3-424c-8b02-56153af8633f hash=1834913037
[13:42:56 INFO]: [connected player] xfy2102 (/192.168.110.1:4564) has connected
[13:42:56 INFO] [cidtest]: [CIDTEST] Login: xfy2102 connId=e1e309f8-e7c3-424c-8b02-56153af8633f uuid=2439bef3-b313-424b-a22c-662e894ffca3
[13:42:56 INFO] [cidtest]: [CIDTEST] ServerPreConnect: xfy2102 connId=e1e309f8-e7c3-424c-8b02-56153af8633f server=hub
[13:42:56 INFO]: [server connection] xfy2102 -> hub has connected
[13:42:59 INFO] [cidtest]: [CIDTEST] ServerPreConnect: xfy2102 connId=e1e309f8-e7c3-424c-8b02-56153af8633f server=login
[13:42:59 INFO]: [server connection] xfy2102 -> login has connected
[13:42:59 INFO]: [server connection] xfy2102 -> hub has disconnected
[13:43:04 INFO] [cidtest]: [CIDTEST] ServerPreConnect: xfy2102 connId=e1e309f8-e7c3-424c-8b02-56153af8633f server=hub
[13:43:04 INFO]: [server connection] xfy2102 -> hub has connected
[13:43:04 INFO]: [server connection] xfy2102 -> login has disconnected
[13:43:06 INFO] [cidtest]: [CIDTEST] Disconnect: xfy2102 connId=e1e309f8-e7c3-424c-8b02-56153af8633f
[13:43:06 INFO]: [connected player] xfy2102 (/192.168.110.1:4564) has disconnected
[13:43:06 INFO]: [server connection] xfy2102 -> hub has disconnected

@xfy2412

xfy2412 commented Jul 8, 2026

Copy link
Copy Markdown
Author

Let me rename this PR

@xfy2412 xfy2412 changed the title feat: Add connectionId to MinecraftConnection feat: add stable session UUID to MinecraftConnection Jul 8, 2026
Comment thread api/src/main/java/com/velocitypowered/api/proxy/InboundConnection.java Outdated
Comment thread proxy/src/main/java/com/velocitypowered/proxy/connection/MinecraftConnection.java Outdated
@xfy2412

xfy2412 commented Jul 8, 2026

Copy link
Copy Markdown
Author

Maybe call it ”clientConnectionId” will be better?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants