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 4d6dcd85d..07b35926b 100644 --- a/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java +++ b/api/src/main/java/com/velocitypowered/api/network/ProtocolVersion.java @@ -34,7 +34,8 @@ public enum ProtocolVersion { MINECRAFT_1_14_4(498, "1.14.4"), MINECRAFT_1_15(573, "1.15"), MINECRAFT_1_15_1(575, "1.15.1"), - MINECRAFT_1_15_2(578, "1.15.2"); + MINECRAFT_1_15_2(578, "1.15.2"), + MINECRAFT_1_16(718, "1.16"); private final int protocol; private final String name; diff --git a/proxy/build.gradle b/proxy/build.gradle index b4a59f90d..91a434a11 100644 --- a/proxy/build.gradle +++ b/proxy/build.gradle @@ -63,6 +63,7 @@ dependencies { compile 'it.unimi.dsi:fastutil:8.2.2' compile 'net.kyori:event-method-asm:3.0.0' + compile 'net.kyori:nbt:1.12-1.0.0-SNAPSHOT' compile 'com.mojang:brigadier:1.0.17' 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 aa5ff5329..d0d21cbd8 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 @@ -337,10 +337,14 @@ public class ClientPlaySessionHandler implements MinecraftSessionHandler { int tempDim = joinGame.getDimension() == 0 ? -1 : 0; player.getMinecraftConnection().delayedWrite( new Respawn(tempDim, joinGame.getPartialHashedSeed(), joinGame.getDifficulty(), - joinGame.getGamemode(), joinGame.getLevelType())); + joinGame.getGamemode(), joinGame.getLevelType(), joinGame.getShouldKeepPlayerData(), + joinGame.getIsDebug(), joinGame.getIsFlat(), + joinGame.getDimensionRegistryName())); player.getMinecraftConnection().delayedWrite( new Respawn(joinGame.getDimension(), joinGame.getPartialHashedSeed(), - joinGame.getDifficulty(), joinGame.getGamemode(), joinGame.getLevelType())); + joinGame.getDifficulty(), joinGame.getGamemode(), joinGame.getLevelType(), + joinGame.getShouldKeepPlayerData(), joinGame.getIsDebug(), joinGame.getIsFlat(), + joinGame.getDimensionRegistryName())); } // 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/ProtocolUtils.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolUtils.java index 907a8640f..c0cbc136d 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolUtils.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolUtils.java @@ -6,13 +6,20 @@ import static com.google.common.base.Preconditions.checkState; import com.velocitypowered.api.network.ProtocolVersion; import com.velocitypowered.api.util.GameProfile; import io.netty.buffer.ByteBuf; +import io.netty.buffer.ByteBufInputStream; +import io.netty.buffer.ByteBufOutputStream; import io.netty.buffer.ByteBufUtil; +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; import java.util.UUID; +import net.kyori.nbt.CompoundTag; + public enum ProtocolUtils { ; private static final int DEFAULT_MAX_STRING_SIZE = 65536; // 64KiB @@ -153,6 +160,81 @@ public enum ProtocolUtils { buf.writeLong(uuid.getLeastSignificantBits()); } + /** + * Reads an UUID stored as an Integer Array from the {@code buf}. + * @param buf the buffer to read from + * @return the UUID from the buffer + */ + public static UUID readUuidIntArray(ByteBuf buf) { + long msbHigh = (long) buf.readInt() << 32; + long msbLow = (long) buf.readInt() & 0xFFFFFFFFL; + long msb = msbHigh | msbLow; + long lsbHigh = (long) buf.readInt() << 32; + long lsbLow = (long) buf.readInt() & 0xFFFFFFFFL; + long lsb = lsbHigh | lsbLow; + return new UUID(msb, lsb); + } + + /** + * Writes an UUID as an Integer Array to the {@code buf}. + * @param buf the buffer to write to + * @param uuid the UUID to write + */ + public static void writeUuidIntArray(ByteBuf buf, UUID uuid) { + buf.writeInt((int) (uuid.getMostSignificantBits() >> 32)); + buf.writeInt((int) uuid.getMostSignificantBits()); + buf.writeInt((int) (uuid.getLeastSignificantBits() >> 32)); + buf.writeInt((int) uuid.getLeastSignificantBits()); + } + + /** + * Reads a {@link net.kyori.nbt.CompoundTag} from the {@code buf}. + * @param buf the buffer to read from + * @return {@link net.kyori.nbt.CompoundTag} the CompoundTag from the buffer + */ + public static CompoundTag readCompoundTag(ByteBuf buf) { + int indexBefore = buf.readerIndex(); + byte startType = buf.readByte(); + if (startType == 0) { + return null; + } else { + buf.readerIndex(indexBefore); + try { + DataInput input = new ByteBufInputStream(buf); + byte type = input.readByte(); + if (type != 10) { + return null; + } + input.readUTF(); + CompoundTag ret = new CompoundTag(); + ret.read(input, 0); + return ret; + } catch (IOException e) { + return null; + } + } + } + + /** + * Writes a CompoundTag to the {@code buf}. + * @param buf the buffer to write to + * @param compoundTag the CompoundTag to write + */ + public static void writeCompoundTag(ByteBuf buf, CompoundTag compoundTag) { + if (compoundTag == null) { + buf.writeByte(0); + } else { + try { + DataOutput output = new ByteBufOutputStream(buf); + output.writeByte(10); + output.writeUTF(""); + compoundTag.write(output); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + /** * Writes a list of {@link com.velocitypowered.api.util.GameProfile.Property} to the buffer. * @param buf the buffer to write 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 bae659122..07f174b51 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java @@ -6,6 +6,7 @@ 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_16; 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; @@ -113,13 +114,15 @@ public enum StateRegistry { map(0x0C, MINECRAFT_1_12, false), map(0x0B, MINECRAFT_1_12_1, false), map(0x0E, MINECRAFT_1_13, false), - map(0x0F, MINECRAFT_1_14, false)); + map(0x0F, MINECRAFT_1_14, false), + map(0x10, MINECRAFT_1_16, false)); serverbound.register(ResourcePackResponse.class, ResourcePackResponse::new, map(0x19, MINECRAFT_1_8, false), map(0x16, MINECRAFT_1_9, false), map(0x18, MINECRAFT_1_12, false), map(0x1D, MINECRAFT_1_13, false), - map(0x1F, MINECRAFT_1_14, false)); + map(0x1F, MINECRAFT_1_14, false), + map(0x20, MINECRAFT_1_16, false)); clientbound.register(BossBar.class, BossBar::new, map(0x0C, MINECRAFT_1_9, false), diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/Chat.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/Chat.java index c4761a667..b80e0f855 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/Chat.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/Chat.java @@ -10,20 +10,25 @@ import net.kyori.text.Component; import net.kyori.text.serializer.gson.GsonComponentSerializer; import org.checkerframework.checker.nullness.qual.Nullable; +import java.util.UUID; + public class Chat implements MinecraftPacket { public static final byte CHAT_TYPE = (byte) 0; public static final int MAX_SERVERBOUND_MESSAGE_LENGTH = 256; + public static final UUID EMPTY_SENDER = new UUID(0, 0); private @Nullable String message; private byte type; + private UUID sender; public Chat() { } - public Chat(String message, byte type) { + public Chat(String message, byte type, UUID sender) { this.message = message; this.type = type; + this.sender = sender; } public String getMessage() { @@ -45,11 +50,20 @@ public class Chat implements MinecraftPacket { this.type = type; } + public UUID getSenderUuid() { + return sender; + } + + public void setSenderUuid(UUID sender) { + this.sender = sender; + } + @Override public String toString() { return "Chat{" + "message='" + message + '\'' + ", type=" + type + + ", sender=" + sender + '}'; } @@ -58,6 +72,9 @@ public class Chat implements MinecraftPacket { message = ProtocolUtils.readString(buf); if (direction == ProtocolUtils.Direction.CLIENTBOUND) { type = buf.readByte(); + if(version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) { + sender = ProtocolUtils.readUuid(buf); + } } } @@ -69,6 +86,9 @@ public class Chat implements MinecraftPacket { ProtocolUtils.writeString(buf, message); if (direction == ProtocolUtils.Direction.CLIENTBOUND) { buf.writeByte(type); + if(version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) { + ProtocolUtils.writeUuid(buf, sender == null ? new UUID(0,0) : sender); + } } } @@ -78,15 +98,15 @@ public class Chat implements MinecraftPacket { } public static Chat createClientbound(Component component) { - return createClientbound(component, CHAT_TYPE); + return createClientbound(component, CHAT_TYPE, EMPTY_SENDER); } - public static Chat createClientbound(Component component, byte type) { + public static Chat createClientbound(Component component, byte type, UUID sender) { Preconditions.checkNotNull(component, "component"); - return new Chat(GsonComponentSerializer.INSTANCE.serialize(component), type); + return new Chat(GsonComponentSerializer.INSTANCE.serialize(component), type, sender); } public static Chat createServerbound(String message) { - return new Chat(message, CHAT_TYPE); + return new Chat(message, CHAT_TYPE, EMPTY_SENDER); } } 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 b422d9876..d036e6531 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 @@ -5,6 +5,7 @@ import com.velocitypowered.proxy.connection.MinecraftSessionHandler; import com.velocitypowered.proxy.protocol.MinecraftPacket; import com.velocitypowered.proxy.protocol.ProtocolUtils; import io.netty.buffer.ByteBuf; +import net.kyori.nbt.CompoundTag; import org.checkerframework.checker.nullness.qual.Nullable; public class JoinGame implements MinecraftPacket { @@ -19,6 +20,11 @@ public class JoinGame implements MinecraftPacket { private int viewDistance; //1.14+ private boolean reducedDebugInfo; private boolean showRespawnScreen; + private boolean shouldKeepPlayerData; + private boolean isDebug; + private boolean isFlat; + private String dimensionRegistryName; + private CompoundTag dimensionRegistry; public int getEntityId() { return entityId; @@ -91,6 +97,46 @@ public class JoinGame implements MinecraftPacket { this.reducedDebugInfo = reducedDebugInfo; } + public boolean getShouldKeepPlayerData() { + return shouldKeepPlayerData; + } + + public void setShouldKeepPlayerData(boolean shouldKeepPlayerData) { + this.shouldKeepPlayerData = shouldKeepPlayerData; + } + + public boolean getIsDebug() { + return isDebug; + } + + public void setIsDebug(boolean isDebug) { + this.isDebug = isDebug; + } + + public boolean getIsFlat() { + return isFlat; + } + + public void setIsFlat(boolean isFlat) { + this.isFlat = isFlat; + } + + public String getDimensionRegistryName() { + return dimensionRegistryName; + } + + public void setDimensionRegistryName(String dimensionRegistryName) { + this.dimensionRegistryName = dimensionRegistryName; + } + + public CompoundTag getDimensionRegistry() { + return dimensionRegistry; + } + + public void setDimensionRegistry(CompoundTag dimensionRegistry) { + this.dimensionRegistry = dimensionRegistry; + } + @Override public String toString() { return "JoinGame{" @@ -110,10 +156,15 @@ public class JoinGame implements MinecraftPacket { public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { this.entityId = buf.readInt(); this.gamemode = buf.readUnsignedByte(); - if (version.compareTo(ProtocolVersion.MINECRAFT_1_9_1) >= 0) { - this.dimension = buf.readInt(); + if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) { + this.dimensionRegistry = ProtocolUtils.readCompoundTag(buf); + this.dimensionRegistryName = ProtocolUtils.readString(buf); } else { - this.dimension = buf.readByte(); + if (version.compareTo(ProtocolVersion.MINECRAFT_1_9_1) >= 0) { + this.dimension = buf.readInt(); + } else { + this.dimension = buf.readByte(); + } } if (version.compareTo(ProtocolVersion.MINECRAFT_1_13_2) <= 0) { this.difficulty = buf.readUnsignedByte(); @@ -122,7 +173,11 @@ public class JoinGame implements MinecraftPacket { this.partialHashedSeed = buf.readLong(); } this.maxPlayers = buf.readUnsignedByte(); - this.levelType = ProtocolUtils.readString(buf, 16); + if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) < 0) { + this.levelType = ProtocolUtils.readString(buf, 16); + } else { + this.levelType = "default"; // I didn't have the courage to rework this yet. + } if (version.compareTo(ProtocolVersion.MINECRAFT_1_14) >= 0) { this.viewDistance = ProtocolUtils.readVarInt(buf); } @@ -130,16 +185,25 @@ public class JoinGame implements MinecraftPacket { if (version.compareTo(ProtocolVersion.MINECRAFT_1_15) >= 0) { this.showRespawnScreen = buf.readBoolean(); } + if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) { + isDebug = buf.readBoolean(); + isFlat = buf.readBoolean(); + } } @Override public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { buf.writeInt(entityId); buf.writeByte(gamemode); - if (version.compareTo(ProtocolVersion.MINECRAFT_1_9_1) >= 0) { - buf.writeInt(dimension); + if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) { + ProtocolUtils.writeCompoundTag(buf, dimensionRegistry); + ProtocolUtils.writeString(buf, dimensionRegistryName); } else { - buf.writeByte(dimension); + if (version.compareTo(ProtocolVersion.MINECRAFT_1_9_1) >= 0) { + buf.writeInt(dimension); + } else { + buf.writeByte(dimension); + } } if (version.compareTo(ProtocolVersion.MINECRAFT_1_13_2) <= 0) { buf.writeByte(difficulty); @@ -148,10 +212,12 @@ public class JoinGame implements MinecraftPacket { buf.writeLong(partialHashedSeed); } buf.writeByte(maxPlayers); - if (levelType == null) { - throw new IllegalStateException("No level type specified."); + if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) < 0) { + if (levelType == null) { + throw new IllegalStateException("No level type specified."); + } + ProtocolUtils.writeString(buf, levelType); } - ProtocolUtils.writeString(buf, levelType); if (version.compareTo(ProtocolVersion.MINECRAFT_1_14) >= 0) { ProtocolUtils.writeVarInt(buf,viewDistance); } @@ -159,6 +225,10 @@ public class JoinGame implements MinecraftPacket { if (version.compareTo(ProtocolVersion.MINECRAFT_1_15) >= 0) { buf.writeBoolean(showRespawnScreen); } + if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) { + buf.writeBoolean(isDebug); + buf.writeBoolean(isFlat); + } } @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 847a722c0..6829d0340 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 @@ -13,17 +13,25 @@ public class Respawn implements MinecraftPacket { private short difficulty; private short gamemode; private String levelType = ""; + private boolean shouldKeepPlayerData; + private boolean isDebug; + private boolean isFlat; + private String dimensionRegistryName; public Respawn() { } public Respawn(int dimension, long partialHashedSeed, short difficulty, short gamemode, - String levelType) { + String levelType, boolean shouldKeepPlayerData, boolean isDebug, boolean isFlat, String dimensionRegistryName) { this.dimension = dimension; this.partialHashedSeed = partialHashedSeed; this.difficulty = difficulty; this.gamemode = gamemode; this.levelType = levelType; + this.shouldKeepPlayerData = shouldKeepPlayerData; + this.isDebug = isDebug; + this.isFlat = isFlat; + this.dimensionRegistryName = dimensionRegistryName; } public int getDimension() { @@ -66,6 +74,38 @@ public class Respawn implements MinecraftPacket { this.levelType = levelType; } + public boolean getShouldKeepPlayerData() { + return shouldKeepPlayerData; + } + + public void setShouldKeepPlayerData(boolean shouldKeepPlayerData) { + this.shouldKeepPlayerData = shouldKeepPlayerData; + } + + public boolean getIsDebug() { + return isDebug; + } + + public void setIsDebug(boolean isDebug) { + this.isDebug = isDebug; + } + + public boolean getIsFlat() { + return isFlat; + } + + public void setIsFlat(boolean isFlat) { + this.isFlat = isFlat; + } + + public String getDimensionRegistryName() { + return dimensionRegistryName; + } + + public void setDimensionRegistryName(String dimensionRegistryName) { + this.dimensionRegistryName = dimensionRegistryName; + } + @Override public String toString() { return "Respawn{" @@ -74,12 +114,20 @@ public class Respawn implements MinecraftPacket { + ", difficulty=" + difficulty + ", gamemode=" + gamemode + ", levelType='" + levelType + '\'' + + ", shouldKeepPlayerData=" + shouldKeepPlayerData + + ", isDebug=" + isDebug + + ", isFlat='" + isFlat + + ", dimensionRegistryName='" + dimensionRegistryName + '\'' + '}'; } @Override public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { - this.dimension = buf.readInt(); + if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) { + this.dimensionRegistryName = ProtocolUtils.readString(buf); // Not sure what the cap on that is + } else { + this.dimension = buf.readInt(); + } if (version.compareTo(ProtocolVersion.MINECRAFT_1_13_2) <= 0) { this.difficulty = buf.readUnsignedByte(); } @@ -87,12 +135,22 @@ public class Respawn implements MinecraftPacket { this.partialHashedSeed = buf.readLong(); } this.gamemode = buf.readUnsignedByte(); - this.levelType = ProtocolUtils.readString(buf, 16); + if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) { + isDebug = buf.readBoolean(); + isFlat = buf.readBoolean(); + shouldKeepPlayerData = buf.readBoolean(); + } else { + this.levelType = ProtocolUtils.readString(buf, 16); + } } @Override public void encode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { - buf.writeInt(dimension); + if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) { + ProtocolUtils.writeString(buf, dimensionRegistryName); + } else { + buf.writeInt(dimension); + } if (version.compareTo(ProtocolVersion.MINECRAFT_1_13_2) <= 0) { buf.writeByte(difficulty); } @@ -100,7 +158,13 @@ public class Respawn implements MinecraftPacket { buf.writeLong(partialHashedSeed); } buf.writeByte(gamemode); - ProtocolUtils.writeString(buf, levelType); + if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) { + buf.writeBoolean(isDebug); + buf.writeBoolean(isFlat); + buf.writeBoolean(shouldKeepPlayerData); + } else { + ProtocolUtils.writeString(buf, levelType); + } } @Override diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerLoginSuccess.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerLoginSuccess.java index 0d068bd7a..4ff3e132b 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerLoginSuccess.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/ServerLoginSuccess.java @@ -45,7 +45,11 @@ public class ServerLoginSuccess implements MinecraftPacket { @Override public void decode(ByteBuf buf, ProtocolUtils.Direction direction, ProtocolVersion version) { - uuid = UUID.fromString(ProtocolUtils.readString(buf, 36)); + if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) { + uuid = ProtocolUtils.readUuidIntArray(buf); + } else { + uuid = UUID.fromString(ProtocolUtils.readString(buf, 36)); + } username = ProtocolUtils.readString(buf, 16); } @@ -54,7 +58,11 @@ public class ServerLoginSuccess implements MinecraftPacket { if (uuid == null) { throw new IllegalStateException("No UUID specified!"); } - ProtocolUtils.writeString(buf, uuid.toString()); + if (version.compareTo(ProtocolVersion.MINECRAFT_1_16) >= 0) { + ProtocolUtils.writeUuidIntArray(buf, uuid); + } else { + ProtocolUtils.writeString(buf, uuid.toString()); + } if (username == null) { throw new IllegalStateException("No username specified!"); } diff --git a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ArgumentPropertyRegistry.java b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ArgumentPropertyRegistry.java index e7847ec8e..56c2a06c5 100644 --- a/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ArgumentPropertyRegistry.java +++ b/proxy/src/main/java/com/velocitypowered/proxy/protocol/packet/brigadier/ArgumentPropertyRegistry.java @@ -134,5 +134,6 @@ public class ArgumentPropertyRegistry { dummy("minecraft:int_range", DUMMY); dummy("minecraft:float_range", DUMMY); dummy("minecraft:time", DUMMY); // added in 1.14 + dummy("minecraft:uuid", DUMMY); } }