diff --git a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java index d1764a5c6..8b5b45f15 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -31,7 +31,8 @@ public enum ProtocolVersion { MINECRAFT_1_14_1(480, "1.14.1"), MINECRAFT_1_14_2(485, "1.14.2"), MINECRAFT_1_14_3(490, "1.14.3"), - MINECRAFT_1_14_4(498, "1.14.4"); + MINECRAFT_1_14_4(498, "1.14.4"), + MINECRAFT_1_15(573, "1.15"); private final int protocol; private final String name; diff --git a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java index 8defbdda8..e9d099d68 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java @@ -336,11 +336,11 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler { player.getMinecraftConnection().delayedWrite(joinGame); int tempDim = joinGame.getDimension() == 0 ? -1 : 0; player.getMinecraftConnection().delayedWrite( - new Respawn(tempDim, joinGame.getDifficulty(), joinGame.getGamemode(), - joinGame.getLevelType())); + new Respawn(tempDim, joinGame.getPartialHashedSeed(), joinGame.getDifficulty(), + joinGame.getGamemode(), joinGame.getLevelType())); player.getMinecraftConnection().delayedWrite( - new Respawn(joinGame.getDimension(), joinGame.getDifficulty(), joinGame.getGamemode(), - joinGame.getLevelType())); + new Respawn(joinGame.getDimension(), joinGame.getPartialHashedSeed(), + joinGame.getDifficulty(), joinGame.getGamemode(), joinGame.getLevelType())); } // Remove previous boss bars. These don't get cleared when sending JoinGame, thus the need to diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java index fd5c268b2..bae659122 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java @@ -5,6 +5,7 @@ import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_12; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_12_1; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_13; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_14; +import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_15; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_8; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_9; import static com.velocitypowered.api.network.ProtocolVersion.MINECRAFT_1_9_4; @@ -121,51 +122,61 @@ public enum StateRegistry { map(0x1F, MINECRAFT_1_14, false)); clientbound.register(BossBar.class, BossBar::new, - map(0x0C, MINECRAFT_1_9, false)); + map(0x0C, MINECRAFT_1_9, false), + map(0x0D, MINECRAFT_1_15, false)); clientbound.register(Chat.class, Chat::new, map(0x02, MINECRAFT_1_8, true), map(0x0F, MINECRAFT_1_9, true), - map(0x0E, MINECRAFT_1_13, true)); + map(0x0E, MINECRAFT_1_13, true), + map(0x0F, MINECRAFT_1_15, true)); clientbound.register(TabCompleteResponse.class, TabCompleteResponse::new, map(0x3A, MINECRAFT_1_8, false), map(0x0E, MINECRAFT_1_9, false), - map(0x10, MINECRAFT_1_13, false)); + map(0x10, MINECRAFT_1_13, false), + map(0x11, MINECRAFT_1_15, false)); clientbound.register(AvailableCommands.class, AvailableCommands::new, - map(0x11, MINECRAFT_1_13, false)); + map(0x11, MINECRAFT_1_13, false), + map(0x12, MINECRAFT_1_15, false)); clientbound.register(PluginMessage.class, PluginMessage::new, map(0x3F, MINECRAFT_1_8, false), map(0x18, MINECRAFT_1_9, false), map(0x19, MINECRAFT_1_13, false), - map(0x18, MINECRAFT_1_14, false)); + map(0x18, MINECRAFT_1_14, false), + map(0x19, MINECRAFT_1_15, false)); clientbound.register(Disconnect.class, Disconnect::new, map(0x40, MINECRAFT_1_8, false), map(0x1A, MINECRAFT_1_9, false), map(0x1B, MINECRAFT_1_13, false), - map(0x1A, MINECRAFT_1_14, false)); + map(0x1A, MINECRAFT_1_14, false), + map(0x1B, MINECRAFT_1_15, false)); clientbound.register(KeepAlive.class, KeepAlive::new, map(0x00, MINECRAFT_1_8, false), map(0x1F, MINECRAFT_1_9, false), map(0x21, MINECRAFT_1_13, false), - map(0x20, MINECRAFT_1_14, false)); + map(0x20, MINECRAFT_1_14, false), + map(0x21, MINECRAFT_1_15, false)); clientbound.register(JoinGame.class, JoinGame::new, map(0x01, MINECRAFT_1_8, false), map(0x23, MINECRAFT_1_9, false), map(0x25, MINECRAFT_1_13, false), - map(0x25, MINECRAFT_1_14, false)); + map(0x25, MINECRAFT_1_14, false), + map(0x26, MINECRAFT_1_15, false)); clientbound.register(Respawn.class, Respawn::new, map(0x07, MINECRAFT_1_8, true), map(0x33, MINECRAFT_1_9, true), map(0x34, MINECRAFT_1_12, true), map(0x35, MINECRAFT_1_12_1, true), map(0x38, MINECRAFT_1_13, true), - map(0x3A, MINECRAFT_1_14, true)); + map(0x3A, MINECRAFT_1_14, true), + map(0x3B, MINECRAFT_1_15, true)); clientbound.register(ResourcePackRequest.class, ResourcePackRequest::new, map(0x48, MINECRAFT_1_8, true), map(0x32, MINECRAFT_1_9, true), map(0x33, MINECRAFT_1_12, true), map(0x34, MINECRAFT_1_12_1, true), map(0x37, MINECRAFT_1_13, true), - map(0x39, MINECRAFT_1_14, true)); + map(0x39, MINECRAFT_1_14, true), + map(0x3A, MINECRAFT_1_15, true)); clientbound.register(HeaderAndFooter.class, HeaderAndFooter::new, map(0x47, MINECRAFT_1_8, true), map(0x48, MINECRAFT_1_9, true), @@ -173,20 +184,23 @@ public enum StateRegistry { map(0x49, MINECRAFT_1_12, true), map(0x4A, MINECRAFT_1_12_1, true), map(0x4E, MINECRAFT_1_13, true), - map(0x53, MINECRAFT_1_14, true)); + map(0x53, MINECRAFT_1_14, true), + map(0x54, MINECRAFT_1_15, true)); clientbound.register(TitlePacket.class, TitlePacket::new, map(0x45, MINECRAFT_1_8, true), map(0x45, MINECRAFT_1_9, true), map(0x47, MINECRAFT_1_12, true), map(0x48, MINECRAFT_1_12_1, true), map(0x4B, MINECRAFT_1_13, true), - map(0x4F, MINECRAFT_1_14, true)); + map(0x4F, MINECRAFT_1_14, true), + map(0x50, MINECRAFT_1_15, true)); clientbound.register(PlayerListItem.class, PlayerListItem::new, map(0x38, MINECRAFT_1_8, false), map(0x2D, MINECRAFT_1_9, false), map(0x2E, MINECRAFT_1_12_1, false), map(0x30, MINECRAFT_1_13, false), - map(0x33, MINECRAFT_1_14, false)); + map(0x33, MINECRAFT_1_14, false), + map(0x34, MINECRAFT_1_15, false)); } }, LOGIN { diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/JoinGame.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/JoinGame.java index af5eb6774..b249bcf9c 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/JoinGame.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/JoinGame.java @@ -12,11 +12,13 @@ public class JoinGame implements MinecraftPacket { private int entityId; private short gamemode; private int dimension; + private long partialHashedSeed; // 1.15+ private short difficulty; private short maxPlayers; private @Nullable String levelType; private int viewDistance; //1.14+ private boolean reducedDebugInfo; + private boolean mystery; public int getEntityId() { return entityId; @@ -42,6 +44,10 @@ public class JoinGame implements MinecraftPacket { this.dimension = dimension; } + public long getPartialHashedSeed() { + return partialHashedSeed; + } + public short getDifficulty() { return difficulty; } @@ -91,6 +97,7 @@ public class JoinGame implements MinecraftPacket { + "entityId=" + entityId + ", gamemode=" + gamemode + ", dimension=" + dimension + + ", partialHashedSeed=" + partialHashedSeed + ", difficulty=" + difficulty + ", maxPlayers=" + maxPlayers + ", levelType='" + levelType + '\'' @@ -111,12 +118,18 @@ public class JoinGame implements MinecraftPacket { if (version.compareTo(ProtocolVersion.MINECRAFT_1_13_2) <= 0) { this.difficulty = buf.readUnsignedByte(); } + if (version.compareTo(ProtocolVersion.MINECRAFT_1_15) >= 0) { + this.partialHashedSeed = buf.readLong(); + } this.maxPlayers = buf.readUnsignedByte(); this.levelType = ProtocolUtils.readString(buf, 16); if (version.compareTo(ProtocolVersion.MINECRAFT_1_14) >= 0) { this.viewDistance = ProtocolUtils.readVarInt(buf); } this.reducedDebugInfo = buf.readBoolean(); + if (version.compareTo(ProtocolVersion.MINECRAFT_1_15) >= 0) { + this.mystery = buf.readBoolean(); + } } @Override @@ -131,6 +144,9 @@ public class JoinGame implements MinecraftPacket { if (version.compareTo(ProtocolVersion.MINECRAFT_1_13_2) <= 0) { buf.writeByte(difficulty); } + if (version.compareTo(ProtocolVersion.MINECRAFT_1_15) >= 0) { + buf.writeLong(partialHashedSeed); + } buf.writeByte(maxPlayers); if (levelType == null) { throw new IllegalStateException("No level type specified."); @@ -140,6 +156,9 @@ public class JoinGame implements MinecraftPacket { ProtocolUtils.writeVarInt(buf,viewDistance); } buf.writeBoolean(reducedDebugInfo); + if (version.compareTo(ProtocolVersion.MINECRAFT_1_15) >= 0) { + buf.writeBoolean(mystery); + } } @Override diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/Respawn.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/Respawn.java index 4979954fe..847a722c0 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/Respawn.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/Respawn.java @@ -9,6 +9,7 @@ import io.netty.buffer.ByteBuf; public class Respawn implements MinecraftPacket { private int dimension; + private long partialHashedSeed; private short difficulty; private short gamemode; private String levelType = ""; @@ -16,8 +17,10 @@ public class Respawn implements MinecraftPacket { public Respawn() { } - public Respawn(int dimension, short difficulty, short gamemode, String levelType) { + public Respawn(int dimension, long partialHashedSeed, short difficulty, short gamemode, + String levelType) { this.dimension = dimension; + this.partialHashedSeed = partialHashedSeed; this.difficulty = difficulty; this.gamemode = gamemode; this.levelType = levelType; @@ -31,6 +34,14 @@ public class Respawn implements MinecraftPacket { this.dimension = dimension; } + public long getPartialHashedSeed() { + return partialHashedSeed; + } + + public void setPartialHashedSeed(long partialHashedSeed) { + this.partialHashedSeed = partialHashedSeed; + } + public short getDifficulty() { return difficulty; } @@ -59,6 +70,7 @@ public class Respawn implements MinecraftPacket { public String toString() { return "Respawn{" + "dimension=" + dimension + + ", partialHashedSeed=" + partialHashedSeed + ", difficulty=" + difficulty + ", gamemode=" + gamemode + ", levelType='" + levelType + '\'' @@ -71,6 +83,9 @@ public class Respawn implements MinecraftPacket { if (version.compareTo(ProtocolVersion.MINECRAFT_1_13_2) <= 0) { this.difficulty = buf.readUnsignedByte(); } + if (version.compareTo(ProtocolVersion.MINECRAFT_1_15) >= 0) { + this.partialHashedSeed = buf.readLong(); + } this.gamemode = buf.readUnsignedByte(); this.levelType = ProtocolUtils.readString(buf, 16); } @@ -81,6 +96,9 @@ public class Respawn implements MinecraftPacket { if (version.compareTo(ProtocolVersion.MINECRAFT_1_13_2) <= 0) { buf.writeByte(difficulty); } + if (version.compareTo(ProtocolVersion.MINECRAFT_1_15) >= 0) { + buf.writeLong(partialHashedSeed); + } buf.writeByte(gamemode); ProtocolUtils.writeString(buf, levelType); }