Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ public boolean isSupported() {
MINECRAFT_1_21_7(772, "1.21.7", "1.21.8"),
MINECRAFT_1_21_9(773, "1.21.9", "1.21.10"),
MINECRAFT_1_21_11(774, "1.21.11"),
MINECRAFT_26_1(775, "26.1", "26.1.1", "26.1.2");
MINECRAFT_26_1(775, "26.1", "26.1.1", "26.1.2"),
MINECRAFT_26_2(776, "26.2");

private static final int SNAPSHOT_BIT = 30;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public boolean handle(KeepAlivePacket packet) {

@Override
public boolean handle(JoinGamePacket packet) {
MinecraftConnection smc = serverConn.ensureConnected();
final MinecraftConnection smc = serverConn.ensureConnected();
final RegisteredServer previousServer = serverConn.getPreviousServer().orElse(null);
final ConnectedPlayer player = serverConn.getPlayer();
final VelocityServerConnection existingConnection = player.getConnectedServer();
Expand All @@ -106,6 +106,9 @@ public boolean handle(JoinGamePacket packet) {
// Reset Tablist header and footer to prevent desync
player.clearPlayerListHeaderAndFooter();

// Override online mode
packet.setOnlineMode(player.isOnlineMode());

// The goods are in hand! We got JoinGame. Let's transition completely to the new state.
smc.setAutoReading(false);
server.getEventManager()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,9 @@ private void completeLoginProtocolPhaseAndInitialize(ConnectedPlayer player) {
success.setUsername(player.getUsername());
success.setProperties(player.getGameProfileProperties());
success.setUuid(player.getUniqueId());
if (inbound.getProtocolVersion().noLessThan(ProtocolVersion.MINECRAFT_26_2)) {
success.setSessionId(UUID.randomUUID()); // use random uuid for now

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interestingly, mojang seems to be a "use the same session ID for everybody but regenerate it when the server is empty"

https://mcsrc.dev/1/26.2-rc-2/net/minecraft/server/network/ServerConnectionListener#L225

https://mcsrc.dev/1/26.2-rc-2/net/minecraft/server/network/ServerConnectionListener#L241

This is used purely for metrics on mojangs side, I guess the "good behavior" here would probably be to reproduce that logic

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering what Mojang sees as a "session" in this case. Does a new session occur the moment the last player online disconnects (or the moment the first player connects, going from 0 -> 1 players, effectively the same), or does a new session only occur when the server was "paused" due to it being empty (correct me if I'm wrong, but a vanilla server should pause processing ticks after no players have been online for x seconds (30?))

If it's the latter that's harder to match in Velocity... Though regardless, if the client expects the session ID to be the same for everyone connected at the same time, it's most likely better to match this behavior. Easiest is to just generate a session ID on boot.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(or uh, grab the session ID from the backend? is that possible here? why do we need to generate our own in velocity land?)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

session ID is sent from the proxy long before we have a backend, so that's not an option;

And I guess their modal is basically single player servers where people join in the eveing, have a "play session" together, and leave, and come back in a day or a few hours or whatever. For a larger server which always had players on that would always be shared

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then again, doesn't really translate to proxies, do we just sent 0,0? I'll ask mojang...

@WouterGritter WouterGritter Jun 15, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a hunch the session ID will be used in the new friends feature that got dropped from the 26.2 release. I'd guess you would be able to easily add players that are on the same server as you. As this will be done through Mojang's own API, the client can just report the session UUID it got from the connected server, and Mojang can match players against the same session UUID and consider them in the same server.

This would break with the current random UUID per connection approach (and also a zero UUID as youre suggesting). Though, it might also be useful for plugins to be able to control this. I could imagine a feature where certain players want to turn this off (staff? content people?). A plugin would be able to check a permission, and override the session UUID with a random one. Though that's all assuming it will be used for the dropped social/friends feature.

}
mcConnection.write(success);

loginState = State.SUCCESS_SENT;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public class JoinGamePacket implements MinecraftPacket {
private @Nullable Pair<String, Long> lastDeathPosition; // 1.19+
private int portalCooldown; // 1.20+
private int seaLevel; // 1.21.2+
private boolean onlineMode; // 26.2+
private boolean enforcesSecureChat; // 1.20.5+

public int getEntityId() {
Expand Down Expand Up @@ -190,6 +191,10 @@ public void setSeaLevel(int seaLevel) {
this.seaLevel = seaLevel;
}

public void setOnlineMode(boolean onlineMode) {
this.onlineMode = onlineMode;
}

public boolean getEnforcesSecureChat() {
return this.enforcesSecureChat;
}
Expand All @@ -213,7 +218,7 @@ public String toString() {
dimensionInfo + '\'' + ", currentDimensionData='" + currentDimensionData + '\'' +
", previousGamemode=" + previousGamemode + ", simulationDistance=" + simulationDistance +
", lastDeathPosition='" + lastDeathPosition + '\'' + ", portalCooldown=" + portalCooldown +
", seaLevel=" + seaLevel +
", seaLevel=" + seaLevel + ", onlineMode=" + this.onlineMode +
'}';
}

Expand Down Expand Up @@ -358,6 +363,10 @@ private void decode1202Up(ByteBuf buf, ProtocolVersion version) {
this.seaLevel = ProtocolUtils.readVarInt(buf);
}

if (version.noLessThan(ProtocolVersion.MINECRAFT_26_2)) {
this.onlineMode = buf.readBoolean();
}

if (version.noLessThan(ProtocolVersion.MINECRAFT_1_20_5)) {
this.enforcesSecureChat = buf.readBoolean();
}
Expand Down Expand Up @@ -510,6 +519,10 @@ private void encode1202Up(ByteBuf buf, ProtocolVersion version) {
ProtocolUtils.writeVarInt(buf, seaLevel);
}

if (version.noLessThan(ProtocolVersion.MINECRAFT_26_2)) {
buf.writeBoolean(this.onlineMode);
}

if (version.noLessThan(ProtocolVersion.MINECRAFT_1_20_5)) {
buf.writeBoolean(this.enforcesSecureChat);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public class ServerLoginSuccessPacket implements MinecraftPacket {
private @Nullable UUID uuid;
private @Nullable String username;
private @Nullable List<GameProfile.Property> properties;
private @Nullable UUID sessionId;
private static final boolean strictErrorHandling = VelocityProperties
.readBoolean("velocity.strictErrorHandling", true);

Expand Down Expand Up @@ -68,6 +69,10 @@ public void setProperties(List<GameProfile.Property> properties) {
this.properties = properties;
}

public void setSessionId(@Nullable UUID sessionId) {
this.sessionId = sessionId;
}

@Override
public String toString() {
return "ServerLoginSuccess{"
Expand Down Expand Up @@ -96,6 +101,10 @@ public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersi
if (version == ProtocolVersion.MINECRAFT_1_20_5 || version == ProtocolVersion.MINECRAFT_1_21) {
buf.readBoolean();
}

if (version.noLessThan(ProtocolVersion.MINECRAFT_26_2)) {
this.sessionId = ProtocolUtils.readUuid(buf);
}
}

@Override
Expand Down Expand Up @@ -127,6 +136,10 @@ public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersi
if (version == ProtocolVersion.MINECRAFT_1_20_5 || version == ProtocolVersion.MINECRAFT_1_21) {
buf.writeBoolean(strictErrorHandling);
}

if (version.noLessThan(ProtocolVersion.MINECRAFT_26_2)) {
ProtocolUtils.writeUuid(buf, this.sessionId);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_20_5;
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_21_5;
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_21_6;
import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_26_2;
import static com.velocitypowered.proxy.protocol.packet.brigadier.ArgumentIdentifier.id;
import static com.velocitypowered.proxy.protocol.packet.brigadier.ArgumentIdentifier.mapSet;
import static com.velocitypowered.proxy.protocol.packet.brigadier.DoubleArgumentPropertySerializer.DOUBLE;
Expand Down Expand Up @@ -207,7 +208,7 @@ public void serialize(BoolArgumentType object, ByteBuf buf,
empty(id("minecraft:block_predicate", mapSet(MINECRAFT_1_19, 13)));
empty(id("minecraft:item_stack", mapSet(MINECRAFT_1_19, 14)));
empty(id("minecraft:item_predicate", mapSet(MINECRAFT_1_19, 15)));
empty(id("minecraft:color", mapSet(MINECRAFT_1_19, 16)));
empty(id("minecraft:color", mapSet(MINECRAFT_26_2, -1), mapSet(MINECRAFT_1_19, 16))); // renamed to team_color in 26.2
empty(id("minecraft:component", mapSet(MINECRAFT_1_21_6, 18), mapSet(MINECRAFT_1_19, 17)));
empty(id("minecraft:style", mapSet(MINECRAFT_1_21_6, 19), mapSet(MINECRAFT_1_20_3, 18))); // added 1.20.3
empty(id("minecraft:message", mapSet(MINECRAFT_1_21_6, 20), mapSet(MINECRAFT_1_20_3, 19), mapSet(MINECRAFT_1_19, 18)));
Expand Down Expand Up @@ -281,6 +282,7 @@ public void serialize(BoolArgumentType object, ByteBuf buf,

empty(id("minecraft:hex_color", mapSet(MINECRAFT_1_21_6, 17))); // added in 1.21.6
empty(id("minecraft:dialog", mapSet(MINECRAFT_1_21_6, 55))); // added in 1.21.6
empty(id("minecraft:team_color", mapSet(MINECRAFT_26_2, 16))); // renamed from color in 26.2

// Crossstitch support
register(id("crossstitch:mod_argument", mapSet(MINECRAFT_1_19, -256)), ModArgumentProperty.class, MOD);
Expand Down