diff --git a/example/src/main/java/org/geysermc/mcprotocollib/network/example/TestProtocol.java b/example/src/main/java/org/geysermc/mcprotocollib/network/example/TestProtocol.java index 012af0ab..6d9af24c 100644 --- a/example/src/main/java/org/geysermc/mcprotocollib/network/example/TestProtocol.java +++ b/example/src/main/java/org/geysermc/mcprotocollib/network/example/TestProtocol.java @@ -67,7 +67,7 @@ public class TestProtocol extends PacketProtocol { } @Override - public void newClientSession(Session session) { + public void newClientSession(Session session, boolean transferring) { session.addListener(new ClientSessionListener()); } diff --git a/example/src/main/java/org/geysermc/mcprotocollib/protocol/example/MinecraftProtocolTest.java b/example/src/main/java/org/geysermc/mcprotocollib/protocol/example/MinecraftProtocolTest.java index e278fa32..ffe75daa 100644 --- a/example/src/main/java/org/geysermc/mcprotocollib/protocol/example/MinecraftProtocolTest.java +++ b/example/src/main/java/org/geysermc/mcprotocollib/protocol/example/MinecraftProtocolTest.java @@ -85,7 +85,7 @@ public class MinecraftProtocolTest { false, false, new PlayerSpawnInfo( - "minecraft:overworld", + 0, "minecraft:world", 100, GameMode.SURVIVAL, @@ -94,7 +94,8 @@ public class MinecraftProtocolTest { false, null, 100 - ) + ), + true )) ); diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/network/Session.java b/protocol/src/main/java/org/geysermc/mcprotocollib/network/Session.java index cf8655d4..0ffab82d 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/network/Session.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/network/Session.java @@ -30,6 +30,14 @@ public interface Session { */ void connect(boolean wait); + /** + * Connects this session to its host and port. + * + * @param wait Whether to wait for the connection to be established before returning. + * @param transferring Whether the session is a client being transferred. + */ + public void connect(boolean wait, boolean transferring); + /** * Gets the host the session is connected to. * @@ -124,6 +132,13 @@ public interface Session { */ void setFlag(Flag flag, T value); + /** + * Sets the values for a collection of flags. + * + * @param flags Collection of flags + */ + public void setFlags(Map flags); + /** * Gets the listeners listening on this session. * diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/network/packet/PacketProtocol.java b/protocol/src/main/java/org/geysermc/mcprotocollib/network/packet/PacketProtocol.java index b1809fde..7e3df73f 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/network/packet/PacketProtocol.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/network/packet/PacketProtocol.java @@ -49,8 +49,9 @@ public abstract class PacketProtocol { * Called when a client session is created with this protocol. * * @param session The created session. + * @param transferring If the client is being transferred between servers. */ - public abstract void newClientSession(Session session); + public abstract void newClientSession(Session session, boolean transferring); /** * Called when a server session is created with this protocol. diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/network/tcp/TcpClientSession.java b/protocol/src/main/java/org/geysermc/mcprotocollib/network/tcp/TcpClientSession.java index 8f290ddd..da310925 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/network/tcp/TcpClientSession.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/network/tcp/TcpClientSession.java @@ -81,7 +81,7 @@ public class TcpClientSession extends TcpSession { } @Override - public void connect(boolean wait) { + public void connect(boolean wait, boolean transferring) { if(this.disconnected) { throw new IllegalStateException("Session has already been disconnected."); } @@ -99,7 +99,7 @@ public class TcpClientSession extends TcpSession { @Override public void initChannel(Channel channel) { PacketProtocol protocol = getPacketProtocol(); - protocol.newClientSession(TcpClientSession.this); + protocol.newClientSession(TcpClientSession.this, transferring); channel.config().setOption(ChannelOption.IP_TOS, 0x18); try { diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/network/tcp/TcpPacketCompression.java b/protocol/src/main/java/org/geysermc/mcprotocollib/network/tcp/TcpPacketCompression.java index e5e980a0..8af73f98 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/network/tcp/TcpPacketCompression.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/network/tcp/TcpPacketCompression.java @@ -6,6 +6,7 @@ import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.handler.codec.ByteToMessageCodec; import io.netty.handler.codec.DecoderException; +import io.netty.handler.codec.EncoderException; import java.util.List; import java.util.zip.Deflater; @@ -36,6 +37,9 @@ public class TcpPacketCompression extends ByteToMessageCodec { @Override public void encode(ChannelHandlerContext ctx, ByteBuf in, ByteBuf out) { int readable = in.readableBytes(); + if (readable > MAX_UNCOMPRESSED_SIZE) { + throw new EncoderException("Packet too big: size of " + readable + " is larger than the protocol maximum of " + MAX_UNCOMPRESSED_SIZE + "."); + } if(readable < this.session.getCompressionThreshold()) { this.session.getCodecHelper().writeVarInt(out, 0); out.writeBytes(in); diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/network/tcp/TcpSession.java b/protocol/src/main/java/org/geysermc/mcprotocollib/network/tcp/TcpSession.java index fd04053e..b7e37a6e 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/network/tcp/TcpSession.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/network/tcp/TcpSession.java @@ -67,6 +67,11 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp @Override public void connect(boolean wait) { + this.connect(wait, false); + } + + @Override + public void connect(boolean wait, boolean transferring) { } @Override @@ -128,6 +133,11 @@ public abstract class TcpSession extends SimpleChannelInboundHandler imp this.flags.put(flag.key(), value); } + @Override + public void setFlags(Map flags) { + this.flags.putAll(flags); + } + @Override public List getListeners() { return Collections.unmodifiableList(this.listeners); diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/ClientListener.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/ClientListener.java index 8fddaa1c..78e6a40b 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/ClientListener.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/ClientListener.java @@ -11,8 +11,11 @@ import org.geysermc.mcprotocollib.protocol.data.handshake.HandshakeIntent; import org.geysermc.mcprotocollib.protocol.data.status.ServerStatusInfo; import org.geysermc.mcprotocollib.protocol.data.status.handler.ServerInfoHandler; import org.geysermc.mcprotocollib.protocol.data.status.handler.ServerPingTimeHandler; +import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundTransferPacket; import org.geysermc.mcprotocollib.protocol.packet.configuration.clientbound.ClientboundFinishConfigurationPacket; +import org.geysermc.mcprotocollib.protocol.packet.configuration.clientbound.ClientboundSelectKnownPacks; import org.geysermc.mcprotocollib.protocol.packet.configuration.serverbound.ServerboundFinishConfigurationPacket; +import org.geysermc.mcprotocollib.protocol.packet.configuration.serverbound.ServerboundSelectKnownPacks; import org.geysermc.mcprotocollib.protocol.packet.handshake.serverbound.ClientIntentionPacket; import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundDisconnectPacket; import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundKeepAlivePacket; @@ -34,6 +37,7 @@ import org.geysermc.mcprotocollib.network.Session; import org.geysermc.mcprotocollib.network.event.session.ConnectedEvent; import org.geysermc.mcprotocollib.network.event.session.SessionAdapter; import org.geysermc.mcprotocollib.network.packet.Packet; +import org.geysermc.mcprotocollib.network.tcp.TcpClientSession; import lombok.AllArgsConstructor; import lombok.NonNull; import lombok.SneakyThrows; @@ -41,6 +45,7 @@ import lombok.SneakyThrows; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; /** * Handles making initial login and status requests for clients. @@ -48,6 +53,7 @@ import java.security.NoSuchAlgorithmException; @AllArgsConstructor public class ClientListener extends SessionAdapter { private final @NonNull ProtocolState targetState; + private final boolean transferring; @SneakyThrows @Override @@ -120,10 +126,22 @@ public class ClientListener extends SessionAdapter { session.disconnect(disconnectPacket.getReason()); } else if (packet instanceof ClientboundStartConfigurationPacket) { session.send(new ServerboundConfigurationAcknowledgedPacket()); + } else if (packet instanceof ClientboundTransferPacket transferPacket) { + TcpClientSession newSession = new TcpClientSession(transferPacket.getHost(), transferPacket.getPort(), session.getPacketProtocol()); + newSession.setFlags(session.getFlags()); + session.disconnect("Transferring"); + newSession.connect(true, true); } } else if (protocol.getState() == ProtocolState.CONFIGURATION) { if (packet instanceof ClientboundFinishConfigurationPacket) { session.send(new ServerboundFinishConfigurationPacket()); + } else if (packet instanceof ClientboundSelectKnownPacks) { + session.send(new ServerboundSelectKnownPacks(new ArrayList<>())); + } else if (packet instanceof ClientboundTransferPacket transferPacket) { + TcpClientSession newSession = new TcpClientSession(transferPacket.getHost(), transferPacket.getPort(), session.getPacketProtocol()); + newSession.setFlags(session.getFlags()); + session.disconnect("Transferring"); + newSession.connect(true, true); } } } @@ -153,15 +171,14 @@ public class ClientListener extends SessionAdapter { @Override public void connected(ConnectedEvent event) { MinecraftProtocol protocol = (MinecraftProtocol) event.getSession().getPacketProtocol(); - event.getSession().send(new ClientIntentionPacket( - protocol.getCodec().getProtocolVersion(), - event.getSession().getHost(), - event.getSession().getPort(), - switch (this.targetState) { - case LOGIN -> HandshakeIntent.LOGIN; - case STATUS -> HandshakeIntent.STATUS; - default -> throw new IllegalArgumentException("Invalid target state: " + this.targetState); + if (this.targetState == ProtocolState.LOGIN) { + if (this.transferring) { + event.getSession().send(new ClientIntentionPacket(protocol.getCodec().getProtocolVersion(), event.getSession().getHost(), event.getSession().getPort(), HandshakeIntent.TRANSFER)); + } else { + event.getSession().send(new ClientIntentionPacket(protocol.getCodec().getProtocolVersion(), event.getSession().getHost(), event.getSession().getPort(), HandshakeIntent.LOGIN)); } - )); + } else if (this.targetState == ProtocolState.STATUS) { + event.getSession().send(new ClientIntentionPacket(protocol.getCodec().getProtocolVersion(), event.getSession().getHost(), event.getSession().getPort(), HandshakeIntent.STATUS)); + } } } diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/MinecraftConstants.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/MinecraftConstants.java index 74404e07..530be182 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/MinecraftConstants.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/MinecraftConstants.java @@ -57,6 +57,11 @@ public final class MinecraftConstants { */ public static final Flag VERIFY_USERS_KEY = new Flag<>("verify-users", Boolean.class); + /** + * Session flag for determining whether to accept transferred connections. Server only. + */ + public static final Flag ACCEPT_TRANSFERS_KEY = new Flag<>("accept-transfers", Boolean.class); + /** * Session flag for providing a custom server info response builder. Server only. */ diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/MinecraftProtocol.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/MinecraftProtocol.java index 0cf3e988..7c18f6fa 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/MinecraftProtocol.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/MinecraftProtocol.java @@ -155,14 +155,14 @@ public class MinecraftProtocol extends PacketProtocol { } @Override - public void newClientSession(Session session) { + public void newClientSession(Session session, boolean transferring) { session.setFlag(MinecraftConstants.PROFILE_KEY, this.profile); session.setFlag(MinecraftConstants.ACCESS_TOKEN_KEY, this.accessToken); this.setState(ProtocolState.HANDSHAKE); if (this.useDefaultListeners) { - session.addListener(new ClientListener(this.targetState)); + session.addListener(new ClientListener(this.targetState, transferring)); } } diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/ServerListener.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/ServerListener.java index 5acc8c8a..2de06986 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/ServerListener.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/ServerListener.java @@ -4,6 +4,7 @@ import com.github.steveice10.mc.auth.data.GameProfile; import com.github.steveice10.mc.auth.exception.request.RequestException; import com.github.steveice10.mc.auth.service.SessionService; import org.geysermc.mcprotocollib.protocol.data.ProtocolState; +import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry; import org.geysermc.mcprotocollib.protocol.data.status.PlayerInfo; import org.geysermc.mcprotocollib.protocol.data.status.ServerStatusInfo; import org.geysermc.mcprotocollib.protocol.data.status.VersionInfo; @@ -28,6 +29,10 @@ import org.geysermc.mcprotocollib.protocol.packet.status.clientbound.Clientbound import org.geysermc.mcprotocollib.protocol.packet.status.serverbound.ServerboundPingRequestPacket; import org.geysermc.mcprotocollib.protocol.packet.status.serverbound.ServerboundStatusRequestPacket; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.IntTag; +import com.github.steveice10.opennbt.tag.builtin.ListTag; +import com.github.steveice10.opennbt.tag.builtin.StringTag; +import com.github.steveice10.opennbt.tag.builtin.Tag; import org.geysermc.mcprotocollib.network.Session; import org.geysermc.mcprotocollib.network.event.session.ConnectedEvent; import org.geysermc.mcprotocollib.network.event.session.DisconnectingEvent; @@ -41,8 +46,11 @@ import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; +import java.util.AbstractList; import java.util.ArrayList; import java.util.Arrays; +import java.util.List; +import java.util.Map; import java.util.Random; import java.util.UUID; @@ -91,6 +99,11 @@ public class ServerListener extends SessionAdapter { if (packet instanceof ClientIntentionPacket intentionPacket) { switch (intentionPacket.getIntent()) { case STATUS -> protocol.setState(ProtocolState.STATUS); + case TRANSFER -> { + if (!session.getFlag(MinecraftConstants.ACCEPT_TRANSFERS_KEY, false)) { + session.disconnect("Server does not accept transfers."); + } + } case LOGIN -> { protocol.setState(ProtocolState.LOGIN); if (intentionPacket.getProtocolVersion() > protocol.getCodec().getProtocolVersion()) { @@ -99,8 +112,7 @@ public class ServerListener extends SessionAdapter { session.disconnect("Outdated client! Please use " + protocol.getCodec().getMinecraftVersion() + "."); } } - default -> - throw new UnsupportedOperationException("Invalid client intent: " + intentionPacket.getIntent()); + default -> throw new UnsupportedOperationException("Invalid client intent: " + intentionPacket.getIntent()); } } } else if (protocol.getState() == ProtocolState.LOGIN) { @@ -108,7 +120,7 @@ public class ServerListener extends SessionAdapter { this.username = helloPacket.getUsername(); if (session.getFlag(MinecraftConstants.VERIFY_USERS_KEY, true)) { - session.send(new ClientboundHelloPacket(SERVER_ID, KEY_PAIR.getPublic(), this.challenge)); + session.send(new ClientboundHelloPacket(SERVER_ID, KEY_PAIR.getPublic(), this.challenge, true)); } else { new Thread(new UserAuthTask(session, null)).start(); } @@ -124,8 +136,24 @@ public class ServerListener extends SessionAdapter { session.enableEncryption(protocol.enableEncryption(key)); new Thread(new UserAuthTask(session, key)).start(); } else if (packet instanceof ServerboundLoginAcknowledgedPacket) { - ((MinecraftProtocol) session.getPacketProtocol()).setState(ProtocolState.CONFIGURATION); - session.send(new ClientboundRegistryDataPacket(networkCodec)); + protocol.setState(ProtocolState.CONFIGURATION); + + // Credit ViaVersion: https://github.com/ViaVersion/ViaVersion/blob/dev/common/src/main/java/com/viaversion/viaversion/protocols/protocol1_20_5to1_20_3/rewriter/EntityPacketRewriter1_20_5.java + for (Map.Entry entry : networkCodec.getValue().entrySet()) { + CompoundTag entryTag = (CompoundTag) entry.getValue(); + StringTag typeTag = entryTag.get("type"); + ListTag valueTag = entryTag.get("value"); + List entries = new ArrayList<>(); + for (Tag tag : valueTag) { + CompoundTag compoundTag = (CompoundTag) tag; + StringTag nameTag = compoundTag.get("name"); + int id = ((IntTag) compoundTag.get("id")).getValue(); + entries.add(id, new RegistryEntry(nameTag.getValue(), compoundTag.get("element"))); + } + + session.send(new ClientboundRegistryDataPacket(typeTag.getValue(), entries)); + } + session.send(new ClientboundFinishConfigurationPacket()); } } else if (protocol.getState() == ProtocolState.STATUS) { @@ -176,7 +204,7 @@ public class ServerListener extends SessionAdapter { public void packetSent(Session session, Packet packet) { if (packet instanceof ClientboundLoginCompressionPacket loginCompressionPacket) { session.setCompressionThreshold(loginCompressionPacket.getThreshold(), true); - session.send(new ClientboundGameProfilePacket(session.getFlag(MinecraftConstants.PROFILE_KEY))); + session.send(new ClientboundGameProfilePacket(session.getFlag(MinecraftConstants.PROFILE_KEY), true)); } } diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/codec/MinecraftCodec.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/codec/MinecraftCodec.java index 6f30de9b..56d9120c 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/codec/MinecraftCodec.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/codec/MinecraftCodec.java @@ -3,13 +3,17 @@ package org.geysermc.mcprotocollib.protocol.codec; import org.geysermc.mcprotocollib.protocol.data.ProtocolState; import org.geysermc.mcprotocollib.protocol.data.game.level.event.LevelEventType; import org.geysermc.mcprotocollib.protocol.data.game.level.sound.BuiltinSound; +import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundCookieRequestPacket; import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundCustomPayloadPacket; import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundDisconnectPacket; import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundKeepAlivePacket; import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundPingPacket; import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundResourcePackPopPacket; import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundResourcePackPushPacket; +import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundStoreCookiePacket; +import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundTransferPacket; import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundUpdateTagsPacket; +import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ServerboundCookieResponsePacket; import org.geysermc.mcprotocollib.protocol.packet.common.serverbound.ServerboundClientInformationPacket; import org.geysermc.mcprotocollib.protocol.packet.common.serverbound.ServerboundCustomPayloadPacket; import org.geysermc.mcprotocollib.protocol.packet.common.serverbound.ServerboundKeepAlivePacket; @@ -17,8 +21,11 @@ import org.geysermc.mcprotocollib.protocol.packet.common.serverbound.Serverbound import org.geysermc.mcprotocollib.protocol.packet.common.serverbound.ServerboundResourcePackPacket; import org.geysermc.mcprotocollib.protocol.packet.configuration.clientbound.ClientboundFinishConfigurationPacket; import org.geysermc.mcprotocollib.protocol.packet.configuration.clientbound.ClientboundRegistryDataPacket; +import org.geysermc.mcprotocollib.protocol.packet.configuration.clientbound.ClientboundResetChatPacket; +import org.geysermc.mcprotocollib.protocol.packet.configuration.clientbound.ClientboundSelectKnownPacks; import org.geysermc.mcprotocollib.protocol.packet.configuration.clientbound.ClientboundUpdateEnabledFeaturesPacket; import org.geysermc.mcprotocollib.protocol.packet.configuration.serverbound.ServerboundFinishConfigurationPacket; +import org.geysermc.mcprotocollib.protocol.packet.configuration.serverbound.ServerboundSelectKnownPacks; import org.geysermc.mcprotocollib.protocol.packet.handshake.serverbound.ClientIntentionPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundAwardStatsPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundBossEventPacket; @@ -27,6 +34,7 @@ import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.Clientbound import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundCommandsPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundCooldownPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundCustomChatCompletionsPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundDebugSamplePacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundDeleteChatPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundDelimiterPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundDisguisedChatPacket; @@ -56,6 +64,7 @@ import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.Clie import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundMoveEntityPosRotPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundMoveEntityRotPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundMoveVehiclePacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundProjectilePowerPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundRemoveEntitiesPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundRemoveMobEffectPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundRotateHeadPacket; @@ -132,11 +141,13 @@ import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.title.Clien import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundChangeDifficultyPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundChatAckPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundChatCommandPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundChatCommandSignedPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundChatPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundChatSessionUpdatePacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundClientCommandPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundCommandSuggestionPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundConfigurationAcknowledgedPacket; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundDebugSampleSubscriptionPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundLockDifficultyPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerButtonClickPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundContainerClickPacket; @@ -157,7 +168,7 @@ import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.S import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundSetJigsawBlockPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory.ServerboundSetStructureBlockPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.level.ServerboundAcceptTeleportationPacket; -import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.level.ServerboundBlockEntityTagQuery; +import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.level.ServerboundBlockEntityTagQueryPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.level.ServerboundChunkBatchReceivedPacket; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.level.ServerboundEntityTagQuery; import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.level.ServerboundJigsawGeneratePacket; @@ -212,9 +223,9 @@ public class MinecraftCodec { } public static final PacketCodec CODEC = PacketCodec.builder() - .protocolVersion(765) + .protocolVersion(766) .helper(() -> new MinecraftCodecHelper(LEVEL_EVENTS, SOUND_NAMES)) - .minecraftVersion("1.20.4") + .minecraftVersion("1.20.5") .state(ProtocolState.HANDSHAKE, PacketStateCodec.builder() .registerServerboundPacket(ClientIntentionPacket.class, ClientIntentionPacket::new) ) @@ -224,32 +235,41 @@ public class MinecraftCodec { .registerClientboundPacket(ClientboundGameProfilePacket.class, ClientboundGameProfilePacket::new) .registerClientboundPacket(ClientboundLoginCompressionPacket.class, ClientboundLoginCompressionPacket::new) .registerClientboundPacket(ClientboundCustomQueryPacket.class, ClientboundCustomQueryPacket::new) + .registerClientboundPacket(ClientboundCookieRequestPacket.class, ClientboundCookieRequestPacket::new) .registerServerboundPacket(ServerboundHelloPacket.class, ServerboundHelloPacket::new) .registerServerboundPacket(ServerboundKeyPacket.class, ServerboundKeyPacket::new) .registerServerboundPacket(ServerboundCustomQueryAnswerPacket.class, ServerboundCustomQueryAnswerPacket::new) .registerServerboundPacket(ServerboundLoginAcknowledgedPacket.class, ServerboundLoginAcknowledgedPacket::new) + .registerServerboundPacket(ServerboundCookieResponsePacket.class, ServerboundCookieResponsePacket::new) ).state(ProtocolState.STATUS, PacketStateCodec.builder() .registerClientboundPacket(ClientboundStatusResponsePacket.class, ClientboundStatusResponsePacket::new) .registerClientboundPacket(ClientboundPongResponsePacket.class, ClientboundPongResponsePacket::new) .registerServerboundPacket(ServerboundStatusRequestPacket.class, ServerboundStatusRequestPacket::new) .registerServerboundPacket(ServerboundPingRequestPacket.class, ServerboundPingRequestPacket::new) ).state(ProtocolState.CONFIGURATION, PacketStateCodec.builder() + .registerClientboundPacket(ClientboundCookieRequestPacket.class, ClientboundCookieRequestPacket::new) .registerClientboundPacket(ClientboundCustomPayloadPacket.class, ClientboundCustomPayloadPacket::new) .registerClientboundPacket(ClientboundDisconnectPacket.class, ClientboundDisconnectPacket::new) .registerClientboundPacket(ClientboundFinishConfigurationPacket.class, ClientboundFinishConfigurationPacket::new) .registerClientboundPacket(ClientboundKeepAlivePacket.class, ClientboundKeepAlivePacket::new) .registerClientboundPacket(ClientboundPingPacket.class, ClientboundPingPacket::new) + .registerClientboundPacket(ClientboundResetChatPacket.class, ClientboundResetChatPacket::new) .registerClientboundPacket(ClientboundRegistryDataPacket.class, ClientboundRegistryDataPacket::new) .registerClientboundPacket(ClientboundResourcePackPopPacket.class, ClientboundResourcePackPopPacket::new) .registerClientboundPacket(ClientboundResourcePackPushPacket.class, ClientboundResourcePackPushPacket::new) + .registerClientboundPacket(ClientboundStoreCookiePacket.class, ClientboundStoreCookiePacket::new) + .registerClientboundPacket(ClientboundTransferPacket.class, ClientboundTransferPacket::new) .registerClientboundPacket(ClientboundUpdateEnabledFeaturesPacket.class, ClientboundUpdateEnabledFeaturesPacket::new) .registerClientboundPacket(ClientboundUpdateTagsPacket.class, ClientboundUpdateTagsPacket::new) + .registerClientboundPacket(ClientboundSelectKnownPacks.class, ClientboundSelectKnownPacks::new) .registerServerboundPacket(ServerboundClientInformationPacket.class, ServerboundClientInformationPacket::new) + .registerServerboundPacket(ServerboundCookieResponsePacket.class, ServerboundCookieResponsePacket::new) .registerServerboundPacket(ServerboundCustomPayloadPacket.class, ServerboundCustomPayloadPacket::new) .registerServerboundPacket(ServerboundFinishConfigurationPacket.class, ServerboundFinishConfigurationPacket::new) .registerServerboundPacket(ServerboundKeepAlivePacket.class, ServerboundKeepAlivePacket::new) .registerServerboundPacket(ServerboundPongPacket.class, ServerboundPongPacket::new) .registerServerboundPacket(ServerboundResourcePackPacket.class, ServerboundResourcePackPacket::new) + .registerServerboundPacket(ServerboundSelectKnownPacks.class, ServerboundSelectKnownPacks::new) ).state(ProtocolState.GAME, PacketStateCodec.builder() .registerClientboundPacket(ClientboundDelimiterPacket.class, ClientboundDelimiterPacket::new) .registerClientboundPacket(ClientboundAddEntityPacket.class, ClientboundAddEntityPacket::new) @@ -273,10 +293,12 @@ public class MinecraftCodec { .registerClientboundPacket(ClientboundContainerSetContentPacket.class, ClientboundContainerSetContentPacket::new) .registerClientboundPacket(ClientboundContainerSetDataPacket.class, ClientboundContainerSetDataPacket::new) .registerClientboundPacket(ClientboundContainerSetSlotPacket.class, ClientboundContainerSetSlotPacket::new) + .registerClientboundPacket(ClientboundCookieRequestPacket.class, ClientboundCookieRequestPacket::new) .registerClientboundPacket(ClientboundCooldownPacket.class, ClientboundCooldownPacket::new) .registerClientboundPacket(ClientboundCustomChatCompletionsPacket.class, ClientboundCustomChatCompletionsPacket::new) .registerClientboundPacket(ClientboundCustomPayloadPacket.class, ClientboundCustomPayloadPacket::new) .registerClientboundPacket(ClientboundDamageEventPacket.class, ClientboundDamageEventPacket::new) + .registerClientboundPacket(ClientboundDebugSamplePacket.class, ClientboundDebugSamplePacket::new) .registerClientboundPacket(ClientboundDeleteChatPacket.class, ClientboundDeleteChatPacket::new) .registerClientboundPacket(ClientboundDisconnectPacket.class, ClientboundDisconnectPacket::new) .registerClientboundPacket(ClientboundDisguisedChatPacket.class, ClientboundDisguisedChatPacket::new) @@ -356,6 +378,7 @@ public class MinecraftCodec { .registerClientboundPacket(ClientboundSoundPacket.class, ClientboundSoundPacket::new) .registerClientboundPacket(ClientboundStartConfigurationPacket.class, ClientboundStartConfigurationPacket::new) .registerClientboundPacket(ClientboundStopSoundPacket.class, ClientboundStopSoundPacket::new) + .registerClientboundPacket(ClientboundStoreCookiePacket.class, ClientboundStoreCookiePacket::new) .registerClientboundPacket(ClientboundSystemChatPacket.class, ClientboundSystemChatPacket::new) .registerClientboundPacket(ClientboundTabListPacket.class, ClientboundTabListPacket::new) .registerClientboundPacket(ClientboundTagQueryPacket.class, ClientboundTagQueryPacket::new) @@ -363,16 +386,19 @@ public class MinecraftCodec { .registerClientboundPacket(ClientboundTeleportEntityPacket.class, ClientboundTeleportEntityPacket::new) .registerClientboundPacket(ClientboundTickingStatePacket.class, ClientboundTickingStatePacket::new) .registerClientboundPacket(ClientboundTickingStepPacket.class, ClientboundTickingStepPacket::new) + .registerClientboundPacket(ClientboundTransferPacket.class, ClientboundTransferPacket::new) .registerClientboundPacket(ClientboundUpdateAdvancementsPacket.class, ClientboundUpdateAdvancementsPacket::new) .registerClientboundPacket(ClientboundUpdateAttributesPacket.class, ClientboundUpdateAttributesPacket::new) .registerClientboundPacket(ClientboundUpdateMobEffectPacket.class, ClientboundUpdateMobEffectPacket::new) .registerClientboundPacket(ClientboundUpdateRecipesPacket.class, ClientboundUpdateRecipesPacket::new) .registerClientboundPacket(ClientboundUpdateTagsPacket.class, ClientboundUpdateTagsPacket::new) + .registerClientboundPacket(ClientboundProjectilePowerPacket.class, ClientboundProjectilePowerPacket::new) .registerServerboundPacket(ServerboundAcceptTeleportationPacket.class, ServerboundAcceptTeleportationPacket::new) - .registerServerboundPacket(ServerboundBlockEntityTagQuery.class, ServerboundBlockEntityTagQuery::new) + .registerServerboundPacket(ServerboundBlockEntityTagQueryPacket.class, ServerboundBlockEntityTagQueryPacket::new) .registerServerboundPacket(ServerboundChangeDifficultyPacket.class, ServerboundChangeDifficultyPacket::new) .registerServerboundPacket(ServerboundChatAckPacket.class, ServerboundChatAckPacket::new) .registerServerboundPacket(ServerboundChatCommandPacket.class, ServerboundChatCommandPacket::new) + .registerServerboundPacket(ServerboundChatCommandSignedPacket.class, ServerboundChatCommandSignedPacket::new) .registerServerboundPacket(ServerboundChatPacket.class, ServerboundChatPacket::new) .registerServerboundPacket(ServerboundChatSessionUpdatePacket.class, ServerboundChatSessionUpdatePacket::new) .registerServerboundPacket(ServerboundChunkBatchReceivedPacket.class, ServerboundChunkBatchReceivedPacket::new) @@ -384,7 +410,9 @@ public class MinecraftCodec { .registerServerboundPacket(ServerboundContainerClickPacket.class, ServerboundContainerClickPacket::new) .registerServerboundPacket(ServerboundContainerClosePacket.class, ServerboundContainerClosePacket::new) .registerServerboundPacket(ServerboundContainerSlotStateChangedPacket.class, ServerboundContainerSlotStateChangedPacket::new) + .registerServerboundPacket(ServerboundCookieResponsePacket.class, ServerboundCookieResponsePacket::new) .registerServerboundPacket(ServerboundCustomPayloadPacket.class, ServerboundCustomPayloadPacket::new) + .registerServerboundPacket(ServerboundDebugSampleSubscriptionPacket.class, ServerboundDebugSampleSubscriptionPacket::new) .registerServerboundPacket(ServerboundEditBookPacket.class, ServerboundEditBookPacket::new) .registerServerboundPacket(ServerboundEntityTagQuery.class, ServerboundEntityTagQuery::new) .registerServerboundPacket(ServerboundInteractPacket.class, ServerboundInteractPacket::new) diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/codec/MinecraftCodecHelper.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/codec/MinecraftCodecHelper.java index 5bd01937..6327cd37 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/codec/MinecraftCodecHelper.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/codec/MinecraftCodecHelper.java @@ -2,6 +2,7 @@ package org.geysermc.mcprotocollib.protocol.codec; import com.github.steveice10.mc.auth.data.GameProfile; import org.geysermc.mcprotocollib.protocol.data.DefaultComponentSerializer; +import org.geysermc.mcprotocollib.protocol.data.game.Holder; import org.geysermc.mcprotocollib.protocol.data.game.Identifier; import org.geysermc.mcprotocollib.protocol.data.game.chat.numbers.BlankFormat; import org.geysermc.mcprotocollib.protocol.data.game.chat.numbers.FixedFormat; @@ -20,9 +21,14 @@ import org.geysermc.mcprotocollib.protocol.data.game.chunk.palette.SingletonPale import org.geysermc.mcprotocollib.protocol.data.game.entity.Effect; import org.geysermc.mcprotocollib.protocol.data.game.entity.EntityEvent; import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.ModifierOperation; +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.ArmadilloState; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.EntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.GlobalPos; -import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.BannerPatternLayer; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponent; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.MetadataType; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Pose; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.SnifferState; @@ -32,6 +38,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.player.BlockBreakSta import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode; import org.geysermc.mcprotocollib.protocol.data.game.entity.player.PlayerSpawnInfo; import org.geysermc.mcprotocollib.protocol.data.game.entity.type.PaintingType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemCodecHelper; import org.geysermc.mcprotocollib.protocol.data.game.level.LightUpdateData; import org.geysermc.mcprotocollib.protocol.data.game.level.block.BlockEntityType; import org.geysermc.mcprotocollib.protocol.data.game.level.event.LevelEvent; @@ -40,7 +47,7 @@ import org.geysermc.mcprotocollib.protocol.data.game.level.event.UnknownLevelEve import org.geysermc.mcprotocollib.protocol.data.game.level.particle.BlockParticleData; import org.geysermc.mcprotocollib.protocol.data.game.level.particle.DustColorTransitionParticleData; import org.geysermc.mcprotocollib.protocol.data.game.level.particle.DustParticleData; -import org.geysermc.mcprotocollib.protocol.data.game.level.particle.FallingDustParticleData; +import org.geysermc.mcprotocollib.protocol.data.game.level.particle.EntityEffectParticleData; import org.geysermc.mcprotocollib.protocol.data.game.level.particle.ItemParticleData; import org.geysermc.mcprotocollib.protocol.data.game.level.particle.Particle; import org.geysermc.mcprotocollib.protocol.data.game.level.particle.ParticleData; @@ -73,6 +80,7 @@ import org.cloudburstmc.math.vector.Vector3f; import org.cloudburstmc.math.vector.Vector3i; import org.cloudburstmc.math.vector.Vector4f; import org.checkerframework.checker.nullness.qual.Nullable; +import org.jetbrains.annotations.NotNull; import java.io.IOException; import java.io.InputStream; @@ -81,6 +89,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.BitSet; import java.util.EnumSet; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; @@ -121,6 +130,20 @@ public class MinecraftCodecHelper extends BasePacketCodecHelper { } } + public Holder readHolder(ByteBuf buf, Function readCustom) { + int registryId = this.readVarInt(buf); + return registryId == 0 ? Holder.ofCustom(readCustom.apply(buf)) : Holder.ofId(registryId - 1); + } + + public void writeHolder(ByteBuf buf, Holder holder, BiConsumer writeCustom) { + if (holder.isCustom()) { + this.writeVarInt(buf, 0); + writeCustom.accept(buf, holder.custom()); + } else { + this.writeVarInt(buf, holder.id() + 1); + } + } + public String readResourceLocation(ByteBuf buf) { return Identifier.formalize(this.readString(buf)); } @@ -240,22 +263,121 @@ public class MinecraftCodecHelper extends BasePacketCodecHelper { } @Nullable - public ItemStack readItemStack(ByteBuf buf) { - boolean present = buf.readBoolean(); - if (!present) { + public ItemStack readOptionalItemStack(ByteBuf buf) { + byte count = buf.readByte(); + if (count <= 0) { return null; } int item = this.readVarInt(buf); - return new ItemStack(item, buf.readByte(), this.readAnyTag(buf)); + return new ItemStack(item, count, this.readDataComponentPatch(buf)); } - public void writeItemStack(ByteBuf buf, @Nullable ItemStack item) { - buf.writeBoolean(item != null); - if (item != null) { + public void writeOptionalItemStack(ByteBuf buf, ItemStack item) { + boolean empty = item == null || item.getAmount() <= 0; + buf.writeByte(!empty ? item.getAmount() : 0); + if (!empty) { this.writeVarInt(buf, item.getId()); - buf.writeByte(item.getAmount()); - this.writeAnyTag(buf, item.getNbt()); + this.writeDataComponentPatch(buf, item.getDataComponents()); + } + } + + @NotNull + public ItemStack readItemStack(ByteBuf buf) { + return this.readOptionalItemStack(buf); + } + + public void writeItemStack(ByteBuf buf, @NotNull ItemStack item) { + this.writeOptionalItemStack(buf, item); + } + + @Nullable + public DataComponents readDataComponentPatch(ByteBuf buf) { + int nonNullComponents = this.readVarInt(buf); + int nullComponents = this.readVarInt(buf); + if (nonNullComponents == 0 && nullComponents == 0) { + return null; + } + + Map, DataComponent> dataComponents = new HashMap<>(); + for (int k = 0; k < nonNullComponents; k++) { + DataComponentType dataComponentType = DataComponentType.from(this.readVarInt(buf)); + DataComponent dataComponent = dataComponentType.readDataComponent(ItemCodecHelper.INSTANCE, buf); + dataComponents.put(dataComponentType, dataComponent); + } + + for (int k = 0; k < nullComponents; k++) { + DataComponentType dataComponentType = DataComponentType.from(this.readVarInt(buf)); + DataComponent dataComponent = dataComponentType.readNullDataComponent(); + dataComponents.put(dataComponentType, dataComponent); + } + + return new DataComponents(dataComponents); + } + + public void writeDataComponentPatch(ByteBuf buf, DataComponents dataComponents) { + if (dataComponents == null) { + this.writeVarInt(buf, 0); + this.writeVarInt(buf, 0); + } else { + int i = 0; + int j = 0; + for (DataComponent component : dataComponents.getDataComponents().values()) { + if (component.getValue() != null) { + i++; + } else { + j++; + } + } + + this.writeVarInt(buf, i); + this.writeVarInt(buf, j); + + for (DataComponent component : dataComponents.getDataComponents().values()) { + if (component.getValue() != null) { + this.writeVarInt(buf, component.getType().getId()); + component.write(ItemCodecHelper.INSTANCE, buf); + } + } + + for (DataComponent component : dataComponents.getDataComponents().values()) { + if (component.getValue() == null) { + this.writeVarInt(buf, component.getType().getId()); + } + } + } + } + + @NotNull + public ItemStack readTradeItemStack(ByteBuf buf) { + int item = this.readVarInt(buf); + int count = this.readVarInt(buf); + int componentsLength = this.readVarInt(buf); + + Map, DataComponent> dataComponents = new HashMap<>(); + for (int i = 0; i < componentsLength; i++) { + DataComponentType dataComponentType = DataComponentType.from(this.readVarInt(buf)); + DataComponent dataComponent = dataComponentType.readDataComponent(ItemCodecHelper.INSTANCE, buf); + dataComponents.put(dataComponentType, dataComponent); + } + + return new ItemStack(item, count, new DataComponents(dataComponents)); + } + + public void writeTradeItemStack(ByteBuf buf, @NotNull ItemStack item) { + this.writeVarInt(buf, item.getId()); + this.writeVarInt(buf, item.getAmount()); + + DataComponents dataComponents = item.getDataComponents(); + if (item.getDataComponents() == null) { + this.writeVarInt(buf, 0); + return; + } + + this.writeVarInt(buf, dataComponents.getDataComponents().size()); + for (DataComponent component : dataComponents.getDataComponents().values()) { + this.writeVarInt(buf, component.getType().getId()); + component.write(ItemCodecHelper.INSTANCE, buf); } } @@ -339,6 +461,14 @@ public class MinecraftCodecHelper extends BasePacketCodecHelper { this.writeEnum(buf, state); } + public ArmadilloState readArmadilloState(ByteBuf buf) { + return ArmadilloState.from(this.readVarInt(buf)); + } + + public void writeArmadilloState(ByteBuf buf, ArmadilloState state) { + this.writeEnum(buf, state); + } + private void writeEnum(ByteBuf buf, Enum e) { this.writeVarInt(buf, e.ordinal()); } @@ -413,7 +543,7 @@ public class MinecraftCodecHelper extends BasePacketCodecHelper { } public PlayerSpawnInfo readPlayerSpawnInfo(ByteBuf buf) { - String dimension = this.readString(buf); + int dimension = this.readVarInt(buf); String worldName = this.readString(buf); long hashedSeed = buf.readLong(); GameMode gameMode = GameMode.byId(buf.readByte()); @@ -426,7 +556,7 @@ public class MinecraftCodecHelper extends BasePacketCodecHelper { } public void writePlayerSpawnInfo(ByteBuf buf, PlayerSpawnInfo info) { - this.writeString(buf, info.getDimension()); + this.writeVarInt(buf, info.getDimension()); this.writeString(buf, info.getWorldName()); buf.writeLong(info.getHashedSeed()); buf.writeByte(info.getGameMode().ordinal()); @@ -457,18 +587,8 @@ public class MinecraftCodecHelper extends BasePacketCodecHelper { public ParticleData readParticleData(ByteBuf buf, ParticleType type) { return switch (type) { - case BLOCK, BLOCK_MARKER -> { - int blockState = this.readVarInt(buf); - yield new BlockParticleData(blockState); - } + case BLOCK, BLOCK_MARKER, FALLING_DUST, DUST_PILLAR -> new BlockParticleData(this.readVarInt(buf)); case DUST -> { - float red = buf.readFloat(); - float green = buf.readFloat(); - float blue = buf.readFloat(); - float scale = buf.readFloat(); - yield new DustParticleData(red, green, blue, scale); - } - case DUST_COLOR_TRANSITION -> { float red = buf.readFloat(); float green = buf.readFloat(); float blue = buf.readFloat(); @@ -478,8 +598,8 @@ public class MinecraftCodecHelper extends BasePacketCodecHelper { float newBlue = buf.readFloat(); yield new DustColorTransitionParticleData(red, green, blue, scale, newRed, newGreen, newBlue); } - case FALLING_DUST -> new FallingDustParticleData(this.readVarInt(buf)); - case ITEM -> new ItemParticleData(this.readItemStack(buf)); + case ENTITY_EFFECT -> new EntityEffectParticleData(buf.readInt()); + case ITEM -> new ItemParticleData(this.readOptionalItemStack(buf)); case SCULK_CHARGE -> new SculkChargeParticleData(buf.readFloat()); case SHRIEK -> new ShriekParticleData(this.readVarInt(buf)); case VIBRATION -> new VibrationParticleData(this.readPositionSource(buf), this.readVarInt(buf)); @@ -489,48 +609,47 @@ public class MinecraftCodecHelper extends BasePacketCodecHelper { public void writeParticleData(ByteBuf buf, ParticleType type, ParticleData data) { switch (type) { - case BLOCK, BLOCK_MARKER -> { - BlockParticleData block = (BlockParticleData) data; - this.writeVarInt(buf, block.getBlockState()); + case BLOCK, BLOCK_MARKER, FALLING_DUST, DUST_PILLAR -> { + BlockParticleData blockData = (BlockParticleData) data; + this.writeVarInt(buf, blockData.getBlockState()); } case DUST -> { - DustParticleData dust = (DustParticleData) data; - buf.writeFloat(dust.getRed()); - buf.writeFloat(dust.getGreen()); - buf.writeFloat(dust.getBlue()); - buf.writeFloat(dust.getScale()); + DustParticleData dustData = (DustParticleData) data; + buf.writeFloat(dustData.getRed()); + buf.writeFloat(dustData.getGreen()); + buf.writeFloat(dustData.getBlue()); + buf.writeFloat(dustData.getScale()); } case DUST_COLOR_TRANSITION -> { - DustColorTransitionParticleData dust = (DustColorTransitionParticleData) data; - buf.writeFloat(dust.getRed()); - buf.writeFloat(dust.getGreen()); - buf.writeFloat(dust.getBlue()); - buf.writeFloat(dust.getScale()); - - buf.writeFloat(dust.getNewRed()); - buf.writeFloat(dust.getNewGreen()); - buf.writeFloat(dust.getNewBlue()); + DustColorTransitionParticleData dustData = (DustColorTransitionParticleData) data; + buf.writeFloat(dustData.getRed()); + buf.writeFloat(dustData.getGreen()); + buf.writeFloat(dustData.getBlue()); + buf.writeFloat(dustData.getScale()); + buf.writeFloat(dustData.getNewRed()); + buf.writeFloat(dustData.getNewGreen()); + buf.writeFloat(dustData.getNewBlue()); } - case FALLING_DUST -> { - FallingDustParticleData fallingDust = (FallingDustParticleData) data; - this.writeVarInt(buf, fallingDust.getBlockState()); + case ENTITY_EFFECT -> { + EntityEffectParticleData entityEffectData = (EntityEffectParticleData) data; + buf.writeInt(entityEffectData.getColor()); } case ITEM -> { - ItemParticleData item = (ItemParticleData) data; - this.writeItemStack(buf, item.getItemStack()); + ItemParticleData itemData = (ItemParticleData) data; + this.writeOptionalItemStack(buf, itemData.getItemStack()); } case SCULK_CHARGE -> { - SculkChargeParticleData sculkCharge = (SculkChargeParticleData) data; - buf.writeFloat(sculkCharge.getRoll()); + SculkChargeParticleData sculkData = (SculkChargeParticleData) data; + buf.writeFloat(sculkData.getRoll()); } case SHRIEK -> { - ShriekParticleData shriek = (ShriekParticleData) data; - this.writeVarInt(buf, shriek.getDelay()); + ShriekParticleData shriekData = (ShriekParticleData) data; + this.writeVarInt(buf, shriekData.getDelay()); } case VIBRATION -> { - VibrationParticleData vibration = (VibrationParticleData) data; - this.writePositionSource(buf, vibration.getPositionSource()); - this.writeVarInt(buf, vibration.getArrivalTicks()); + VibrationParticleData vibrationData = (VibrationParticleData) data; + this.writePositionSource(buf, vibrationData.getPositionSource()); + this.writeVarInt(buf, vibrationData.getArrivalTicks()); } } } @@ -622,15 +741,9 @@ public class MinecraftCodecHelper extends BasePacketCodecHelper { } } - @NonNull + @Nullable public BlockEntityType readBlockEntityType(ByteBuf buf) { - int id = this.readVarInt(buf); - BlockEntityType type = BlockEntityType.from(id); - - if (type == null) { - throw new IllegalArgumentException("Unknown BlockEntityType: " + id); - } - return type; + return BlockEntityType.from(this.readVarInt(buf)); } public void writeBlockEntityType(ByteBuf buf, BlockEntityType type) { @@ -725,7 +838,7 @@ public class MinecraftCodecHelper extends BasePacketCodecHelper { public Ingredient readRecipeIngredient(ByteBuf buf) { ItemStack[] options = new ItemStack[this.readVarInt(buf)]; for (int i = 0; i < options.length; i++) { - options[i] = this.readItemStack(buf); + options[i] = this.readOptionalItemStack(buf); } return new Ingredient(options); @@ -734,7 +847,7 @@ public class MinecraftCodecHelper extends BasePacketCodecHelper { public void writeRecipeIngredient(ByteBuf buf, Ingredient ingredient) { this.writeVarInt(buf, ingredient.getOptions().length); for (ItemStack option : ingredient.getOptions()) { - this.writeItemStack(buf, option); + this.writeOptionalItemStack(buf, option); } } diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/codec/PacketStateCodec.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/codec/PacketStateCodec.java index 3e097787..8e83a058 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/codec/PacketStateCodec.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/codec/PacketStateCodec.java @@ -32,7 +32,7 @@ public class PacketStateCodec extends PacketProtocol { } @Override - public void newClientSession(Session session) { + public void newClientSession(Session session, boolean transferring) { throw new UnsupportedOperationException("Not supported!"); } diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/Holder.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/Holder.java new file mode 100644 index 00000000..3c11577c --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/Holder.java @@ -0,0 +1,90 @@ +package org.geysermc.mcprotocollib.protocol.data.game; + +import java.util.function.Consumer; + +/** + * Represents an object that could either be a network ID, or a custom-defined one. + */ +public interface Holder { + static Holder ofId(int id) { + return new IdHolder<>(id); + } + + static Holder ofCustom(T object) { + return new CustomHolder<>(object); + } + + boolean isId(); + + int id(); + + boolean isCustom(); + + T custom(); + + Holder ifId(Consumer> action); + + Holder ifCustom(Consumer> action); + + record IdHolder(int id) implements Holder { + @Override + public boolean isId() { + return true; + } + + @Override + public boolean isCustom() { + return false; + } + + @Override + public T custom() { + throw new IllegalStateException("Check isCustom first!"); + } + + @Override + public Holder ifId(Consumer> action) { + action.accept(this); + return this; + } + + @Override + public Holder ifCustom(Consumer> action) { + // no-op + return this; + } + } + + record CustomHolder(T object) implements Holder { + @Override + public boolean isId() { + return false; + } + + @Override + public int id() { + throw new IllegalStateException("Check isId first!"); + } + + @Override + public boolean isCustom() { + return true; + } + + @Override + public T custom() { + return object; + } + + @Override + public Holder ifId(Consumer> action) { + return this; + } + + @Override + public Holder ifCustom(Consumer> action) { + action.accept(this); + return this; + } + } +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/KnownPack.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/KnownPack.java new file mode 100644 index 00000000..f8079e45 --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/KnownPack.java @@ -0,0 +1,12 @@ +package org.geysermc.mcprotocollib.protocol.data.game; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class KnownPack { + private String namespace; + private String id; + private String version; +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/RegistryEntry.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/RegistryEntry.java new file mode 100644 index 00000000..e5432522 --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/RegistryEntry.java @@ -0,0 +1,13 @@ +package org.geysermc.mcprotocollib.protocol.data.game; + +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import lombok.AllArgsConstructor; +import lombok.Data; +import org.jetbrains.annotations.Nullable; + +@Data +@AllArgsConstructor +public class RegistryEntry { + private final String id; + private final @Nullable CompoundTag data; +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/RemoteDebugSampleType.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/RemoteDebugSampleType.java new file mode 100644 index 00000000..81264db8 --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/RemoteDebugSampleType.java @@ -0,0 +1,11 @@ +package org.geysermc.mcprotocollib.protocol.data.game; + +public enum RemoteDebugSampleType { + TICK_TIME; + + private static final RemoteDebugSampleType[] VALUES = values(); + + public static RemoteDebugSampleType from(int id) { + return VALUES[id]; + } +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/advancement/Advancement.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/advancement/Advancement.java index a312252c..53e18085 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/advancement/Advancement.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/advancement/Advancement.java @@ -1,6 +1,6 @@ package org.geysermc.mcprotocollib.protocol.data.game.advancement; -import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NonNull; diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/command/CommandParser.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/command/CommandParser.java index c173e07e..7d541705 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/command/CommandParser.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/command/CommandParser.java @@ -35,6 +35,7 @@ public enum CommandParser { SWIZZLE, TEAM, ITEM_SLOT, + ITEM_SLOTS, RESOURCE_LOCATION, FUNCTION, ENTITY_ANCHOR, @@ -50,6 +51,9 @@ public enum CommandParser { TEMPLATE_MIRROR, TEMPLATE_ROTATION, HEIGHTMAP, + LOOT_TABLE, + LOOT_PREDICATE, + LOOT_MODIFIER, UUID; private static final CommandParser[] VALUES = values(); diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/EquipmentSlot.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/EquipmentSlot.java index 59ff1476..7f0b4ce5 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/EquipmentSlot.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/EquipmentSlot.java @@ -6,7 +6,8 @@ public enum EquipmentSlot { BOOTS, LEGGINGS, CHESTPLATE, - HELMET; + HELMET, + BODY; private static final EquipmentSlot[] VALUES = values(); diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/attribute/AttributeType.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/attribute/AttributeType.java index caa89d86..cb17b2d3 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/attribute/AttributeType.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/attribute/AttributeType.java @@ -1,5 +1,7 @@ package org.geysermc.mcprotocollib.protocol.data.game.entity.attribute; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import lombok.AllArgsConstructor; import lombok.EqualsAndHashCode; import lombok.Getter; @@ -11,65 +13,71 @@ public interface AttributeType { String getIdentifier(); - /** - * Used when MCProtocolLib gets an attribute not in its built-in registry. - */ - @Getter - @EqualsAndHashCode - class Custom implements AttributeType { - private final String identifier; + int getId(); - public Custom(String identifier) { - this.identifier = identifier; - } - - public String getIdentifier() { - return identifier; - } - } + // TODO: Reimplement once new format is finalized +// /** +// * Used when MCProtocolLib gets an attribute not in its built-in registry. +// */ +// @Getter +// @EqualsAndHashCode +// class Custom implements AttributeType { +// private final String identifier; +// +// public Custom(String identifier) { +// this.identifier = identifier; +// } +// +// public String getIdentifier() { +// return identifier; +// } +// } @Getter @AllArgsConstructor enum Builtin implements AttributeType { - GENERIC_MAX_HEALTH("minecraft:generic.max_health", 20, 0, 1024), - GENERIC_FOLLOW_RANGE("minecraft:generic.follow_range", 32, 0, 2048), - GENERIC_KNOCKBACK_RESISTANCE("minecraft:generic.knockback_resistance", 0, 0, 1), - GENERIC_MOVEMENT_SPEED("minecraft:generic.movement_speed", 0.699999988079071, 0, 1024), - GENERIC_ATTACK_DAMAGE("minecraft:generic.attack_damage", 2, 0, 2048), - GENERIC_ATTACK_SPEED("minecraft:generic.attack_speed", 4, 0, 1024), - GENERIC_FLYING_SPEED("minecraft:generic.flying_speed", 0.4000000059604645, 0, 1024), GENERIC_ARMOR("minecraft:generic.armor", 0, 0, 30), GENERIC_ARMOR_TOUGHNESS("minecraft:generic.armor_toughness", 0, 0, 20), + GENERIC_ATTACK_DAMAGE("minecraft:generic.attack_damage", 2, 0, 2048), GENERIC_ATTACK_KNOCKBACK("minecraft:generic.attack_knockback", 0, 0, 5), + GENERIC_ATTACK_SPEED("minecraft:generic.attack_speed", 4, 0, 1024), + PLAYER_BLOCK_BREAK_SPEED("minecraft:player.block_break_speed", 1, 0, 1024), + PLAYER_BLOCK_INTERACTION_RANGE("minecraft:player.block_interaction_range", 4.5, 0, 64), + PLAYER_ENTITY_INTERACTION_RANGE("minecraft:player.entity_interaction_range", 3, 0, 64), + GENERIC_FALL_DAMAGE_MULTIPLIER("minecraft:generic.fall_damage_multiplier", 1, 0, 100), + GENERIC_FLYING_SPEED("minecraft:generic.flying_speed", 0.4F, 0, 1024), + GENERIC_FOLLOW_RANGE("minecraft:generic.follow_range", 32, 0, 2048), + GENERIC_GRAVITY("minecraft:generic.gravity", 0.08, -1, 1), + GENERIC_JUMP_STRENGTH("minecraft:generic.jump_strength", 0.42, 0, 32), + GENERIC_KNOCKBACK_RESISTANCE("minecraft:generic.knockback_resistance", 0, 0, 1), GENERIC_LUCK("minecraft:generic.luck", 0, -1024, 1024), - HORSE_JUMP_STRENGTH("minecraft:horse.jump_strength", 0.7, 0, 2), - ZOMBIE_SPAWN_REINFORCEMENTS("minecraft:zombie.spawn_reinforcements", 0, 0, 1); + GENERIC_MAX_ABSORPTION("minecraft:generic.max_absorption", 0, 0, 2048), + GENERIC_MAX_HEALTH("minecraft:generic.max_health", 20, 1, 1024), + GENERIC_MOVEMENT_SPEED("minecraft:generic.movement_speed", 0.7F, 0, 1024), + GENERIC_SAFE_FALL_DISTANCE("minecraft:generic.safe_fall_distance", 3, -1024, 1024), + GENERIC_SCALE("minecraft:generic.scale", 1, 0.0625, 16), + ZOMBIE_SPAWN_REINFORCEMENTS("minecraft:zombie.spawn_reinforcements", 0, 0, 1), + GENERIC_STEP_HEIGHT("minecraft:generic.step_height", 0.6, 0, 10); private final String identifier; private final double def; private final double min; private final double max; - public static final Map BUILTIN = new HashMap<>(); - - static { - register(GENERIC_MAX_HEALTH); - register(GENERIC_FOLLOW_RANGE); - register(GENERIC_KNOCKBACK_RESISTANCE); - register(GENERIC_MOVEMENT_SPEED); - register(GENERIC_ATTACK_DAMAGE); - register(GENERIC_ATTACK_SPEED); - register(GENERIC_FLYING_SPEED); - register(GENERIC_ARMOR); - register(GENERIC_ARMOR_TOUGHNESS); - register(GENERIC_ATTACK_KNOCKBACK); - register(GENERIC_LUCK); - register(HORSE_JUMP_STRENGTH); - register(ZOMBIE_SPAWN_REINFORCEMENTS); + public int getId() { + return this.ordinal(); } - private static void register(AttributeType attributeType) { - BUILTIN.put(attributeType.getIdentifier(), attributeType); + public static final Int2ObjectMap BUILTIN = new Int2ObjectOpenHashMap<>(); + + public static AttributeType from(int id) { + return BUILTIN.get(id); + } + + static { + for (Builtin attribute : values()) { + BUILTIN.put(attribute.ordinal(), attribute); + } } } } diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/attribute/ModifierOperation.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/attribute/ModifierOperation.java index 5471cc3a..82029bb5 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/attribute/ModifierOperation.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/attribute/ModifierOperation.java @@ -2,8 +2,8 @@ package org.geysermc.mcprotocollib.protocol.data.game.entity.attribute; public enum ModifierOperation { ADD, - ADD_MULTIPLIED, - MULTIPLY; + ADD_MULTIPLIED_BASE, + ADD_MULTIPLIED_TOTAL; private static final ModifierOperation[] VALUES = values(); diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/attribute/ModifierType.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/attribute/ModifierType.java index 8a70623a..01c9309d 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/attribute/ModifierType.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/attribute/ModifierType.java @@ -2,7 +2,7 @@ package org.geysermc.mcprotocollib.protocol.data.game.entity.attribute; import java.util.UUID; -public final class ModifierType { +public final class ModifierType { // TODO: out of date public static final UUID CREATURE_FLEE_SPEED_BONUS = UUID.fromString("E199AD21-BA8A-4C53-8D13-6182D5C69D3A"); public static final UUID ENDERMAN_ATTACK_SPEED_BOOST = UUID.fromString("020E0DFB-87AE-4653-9556-831010E291A0"); public static final UUID SPRINT_SPEED_BOOST = UUID.fromString("662A6B8D-DA3E-4C1C-8813-96EA6097278D"); @@ -24,5 +24,6 @@ public final class ModifierType { public static final UUID LEGGINGS_MODIFIER = UUID.fromString("D8499B04-0E66-4726-AB29-64469D734E0D"); public static final UUID CHESTPLATE_MODIFIER = UUID.fromString("9F3D476D-C118-4544-8365-64846904B48E"); public static final UUID HELMET_MODIFIER = UUID.fromString("2AD3F246-FEE1-4E67-B886-69FD380BB150"); + public static final UUID BODY_MODIFIER = UUID.fromString("C1C72771-8B8E-BA4A-ACE0-81A93C8928B2"); public static final UUID COVERED_ARMOR_BONUS = UUID.fromString("7E0292F2-9434-48D5-A29F-9583AF7DF27F"); } diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/metadata/ArmadilloState.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/metadata/ArmadilloState.java new file mode 100644 index 00000000..afd0bca8 --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/metadata/ArmadilloState.java @@ -0,0 +1,13 @@ +package org.geysermc.mcprotocollib.protocol.data.game.entity.metadata; + +public enum ArmadilloState { + IDLE, + ROLLING, + SCARED; + + private static final ArmadilloState[] VALUES = values(); + + public static ArmadilloState from(int id) { + return VALUES[id]; + } +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/metadata/Equipment.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/metadata/Equipment.java index 9d36c42e..96504a1f 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/metadata/Equipment.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/metadata/Equipment.java @@ -1,6 +1,7 @@ package org.geysermc.mcprotocollib.protocol.data.game.entity.metadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.EquipmentSlot; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NonNull; diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/metadata/MetadataType.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/metadata/MetadataType.java index d3cc2e52..f6427638 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/metadata/MetadataType.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/metadata/MetadataType.java @@ -9,6 +9,8 @@ import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.LongEn import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.type.ObjectEntityMetadata; import org.geysermc.mcprotocollib.protocol.data.game.entity.object.Direction; import org.geysermc.mcprotocollib.protocol.data.game.entity.type.PaintingType; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; import org.geysermc.mcprotocollib.protocol.data.game.level.particle.Particle; import com.github.steveice10.opennbt.tag.builtin.CompoundTag; import io.netty.buffer.ByteBuf; @@ -34,7 +36,7 @@ public class MetadataType { public static final MetadataType STRING = new MetadataType<>(MinecraftCodecHelper::readString, MinecraftCodecHelper::writeString, ObjectEntityMetadata::new); public static final MetadataType CHAT = new MetadataType<>(MinecraftCodecHelper::readComponent, MinecraftCodecHelper::writeComponent, ObjectEntityMetadata::new); public static final MetadataType> OPTIONAL_CHAT = new MetadataType<>(optionalReader(MinecraftCodecHelper::readComponent), optionalWriter(MinecraftCodecHelper::writeComponent), ObjectEntityMetadata::new); - public static final MetadataType ITEM = new MetadataType<>(MinecraftCodecHelper::readItemStack, MinecraftCodecHelper::writeItemStack, ObjectEntityMetadata::new); + public static final MetadataType ITEM = new MetadataType<>(MinecraftCodecHelper::readOptionalItemStack, MinecraftCodecHelper::writeOptionalItemStack, ObjectEntityMetadata::new); public static final BooleanMetadataType BOOLEAN = new BooleanMetadataType(ByteBuf::readBoolean, ByteBuf::writeBoolean, BooleanEntityMetadata::new); public static final MetadataType ROTATION = new MetadataType<>(MinecraftCodecHelper::readRotation, MinecraftCodecHelper::writeRotation, ObjectEntityMetadata::new); public static final MetadataType POSITION = new MetadataType<>(MinecraftCodecHelper::readPosition, MinecraftCodecHelper::writePosition, ObjectEntityMetadata::new); @@ -45,14 +47,17 @@ public class MetadataType { public static final IntMetadataType OPTIONAL_BLOCK_STATE = new IntMetadataType(MinecraftCodecHelper::readVarInt, MinecraftCodecHelper::writeVarInt, IntEntityMetadata::new); public static final MetadataType NBT_TAG = new MetadataType<>(MinecraftCodecHelper::readAnyTag, MinecraftCodecHelper::writeAnyTag, ObjectEntityMetadata::new); public static final MetadataType PARTICLE = new MetadataType<>(MinecraftCodecHelper::readParticle, MinecraftCodecHelper::writeParticle, ObjectEntityMetadata::new); + public static final MetadataType> PARTICLES = new MetadataType<>(listReader(MinecraftCodecHelper::readParticle), listWriter(MinecraftCodecHelper::writeParticle), ObjectEntityMetadata::new); public static final MetadataType VILLAGER_DATA = new MetadataType<>(MinecraftCodecHelper::readVillagerData, MinecraftCodecHelper::writeVillagerData, ObjectEntityMetadata::new); public static final OptionalIntMetadataType OPTIONAL_VARINT = new OptionalIntMetadataType(ObjectEntityMetadata::new); public static final MetadataType POSE = new MetadataType<>(MinecraftCodecHelper::readPose, MinecraftCodecHelper::writePose, ObjectEntityMetadata::new); public static final IntMetadataType CAT_VARIANT = new IntMetadataType(MinecraftCodecHelper::readVarInt, MinecraftCodecHelper::writeVarInt, IntEntityMetadata::new); + public static final IntMetadataType WOLF_VARIANT = new IntMetadataType(MinecraftCodecHelper::readVarInt, MinecraftCodecHelper::writeVarInt, IntEntityMetadata::new); public static final IntMetadataType FROG_VARIANT = new IntMetadataType(MinecraftCodecHelper::readVarInt, MinecraftCodecHelper::writeVarInt, IntEntityMetadata::new); public static final MetadataType> OPTIONAL_GLOBAL_POS = new MetadataType<>(optionalReader(MinecraftCodecHelper::readGlobalPos), optionalWriter(MinecraftCodecHelper::writeGlobalPos), ObjectEntityMetadata::new); public static final MetadataType PAINTING_VARIANT = new MetadataType<>(MinecraftCodecHelper::readPaintingType, MinecraftCodecHelper::writePaintingType, ObjectEntityMetadata::new); public static final MetadataType SNIFFER_STATE = new MetadataType<>(MinecraftCodecHelper::readSnifferState, MinecraftCodecHelper::writeSnifferState, ObjectEntityMetadata::new); + public static final MetadataType ARMADILLO_STATE = new MetadataType<>(MinecraftCodecHelper::readArmadilloState, MinecraftCodecHelper::writeArmadilloState, ObjectEntityMetadata::new); public static final MetadataType VECTOR3 = new MetadataType<>(MinecraftCodecHelper::readRotation, MinecraftCodecHelper::writeRotation, ObjectEntityMetadata::new); public static final MetadataType QUATERNION = new MetadataType<>(MinecraftCodecHelper::readQuaternion, MinecraftCodecHelper::writeQuaternion, ObjectEntityMetadata::new); @@ -145,6 +150,26 @@ public class MetadataType { }; } + private static Reader> listReader(Reader reader) { + return (helper, input) -> { + List ret = new ArrayList<>(); + for (int i = 0; i < helper.readVarInt(input); i++) { + ret.add(reader.read(helper, input)); + } + + return ret; + }; + } + + private static Writer> listWriter(Writer writer) { + return (helper, output, value) -> { + helper.writeVarInt(output, value.size()); + for (T object : value) { + writer.write(helper, output, object); + } + }; + } + public static MetadataType read(ByteBuf in, MinecraftCodecHelper helper) { int id = helper.readVarInt(in); if (id >= VALUES.size()) { diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/player/PlayerSpawnInfo.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/player/PlayerSpawnInfo.java index a784016a..0b0924d8 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/player/PlayerSpawnInfo.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/player/PlayerSpawnInfo.java @@ -9,7 +9,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; @Data @AllArgsConstructor public class PlayerSpawnInfo { - private final @NonNull String dimension; + private final int dimension; private final @NonNull String worldName; private final long hashedSeed; private final @NonNull GameMode gameMode; diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/type/EntityType.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/type/EntityType.java index 0e41a069..d435c6e6 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/type/EntityType.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/type/EntityType.java @@ -3,6 +3,7 @@ package org.geysermc.mcprotocollib.protocol.data.game.entity.type; public enum EntityType { ALLAY, AREA_EFFECT_CLOUD, + ARMADILLO, ARMOR_STAND, ARROW, AXOLOTL, @@ -11,7 +12,9 @@ public enum EntityType { BLAZE, BLOCK_DISPLAY, BOAT, + BOGGED, BREEZE, + BREEZE_WIND_CHARGE, CAMEL, CAT, CAVE_SPIDER, @@ -59,6 +62,7 @@ public enum EntityType { ITEM, ITEM_DISPLAY, ITEM_FRAME, + OMINOUS_ITEM_SPAWNER, FIREBALL, LEASH_KNOT, LIGHTNING_BOLT, diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/inventory/VillagerTrade.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/inventory/VillagerTrade.java index befdf691..1f6286c7 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/inventory/VillagerTrade.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/inventory/VillagerTrade.java @@ -1,14 +1,15 @@ package org.geysermc.mcprotocollib.protocol.data.game.inventory; -import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import lombok.AllArgsConstructor; import lombok.Data; +import lombok.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @Data @AllArgsConstructor public class VillagerTrade { - private final @Nullable ItemStack firstInput; + private final @NonNull ItemStack firstInput; private final @Nullable ItemStack secondInput; private final @Nullable ItemStack output; private final boolean tradeDisabled; diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/metadata/ItemStack.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/ItemStack.java similarity index 64% rename from protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/metadata/ItemStack.java rename to protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/ItemStack.java index 2f4dfa2d..17bfdd68 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/entity/metadata/ItemStack.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/ItemStack.java @@ -1,6 +1,6 @@ -package org.geysermc.mcprotocollib.protocol.data.game.entity.metadata; +package org.geysermc.mcprotocollib.protocol.data.game.item; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponents; import lombok.AllArgsConstructor; import lombok.Data; import org.checkerframework.checker.nullness.qual.Nullable; @@ -10,7 +10,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; public class ItemStack { private final int id; private final int amount; - private final @Nullable CompoundTag nbt; + private final @Nullable DataComponents dataComponents; public ItemStack(int id) { this(id, 1); diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/AdventureModePredicate.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/AdventureModePredicate.java new file mode 100644 index 00000000..9cdf5c62 --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/AdventureModePredicate.java @@ -0,0 +1,33 @@ +package org.geysermc.mcprotocollib.protocol.data.game.item.component; + +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import lombok.AllArgsConstructor; +import lombok.Data; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +@Data +@AllArgsConstructor +public class AdventureModePredicate { + private final List predicates; + private final boolean showInTooltip; + + @Data + @AllArgsConstructor + public static class BlockPredicate { + private final @Nullable String location; + private final int @Nullable[] holders; + private final @Nullable List properties; + private final @Nullable CompoundTag nbt; + } + + @Data + @AllArgsConstructor + public static class PropertyMatcher { + private final String name; + private final @Nullable String value; + private final @Nullable String minValue; + private final @Nullable String maxValue; + } +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/ArmorTrim.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/ArmorTrim.java new file mode 100644 index 00000000..3c24027d --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/ArmorTrim.java @@ -0,0 +1,16 @@ +package org.geysermc.mcprotocollib.protocol.data.game.item.component; + +import org.geysermc.mcprotocollib.protocol.data.game.Holder; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import lombok.AllArgsConstructor; +import lombok.Data; +import net.kyori.adventure.text.Component; + +public record ArmorTrim(Holder material, Holder pattern, boolean showInTooltip) { + public record TrimMaterial(String assetName, int ingredientId, float itemModelIndex, + Int2ObjectMap overrideArmorMaterials, Component description) { + } + + public record TrimPattern(String assetId, int templateItemId, Component description, boolean decal) { + } +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/BannerPatternLayer.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/BannerPatternLayer.java new file mode 100644 index 00000000..623f0ed2 --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/BannerPatternLayer.java @@ -0,0 +1,20 @@ +package org.geysermc.mcprotocollib.protocol.data.game.item.component; + +import org.geysermc.mcprotocollib.protocol.data.game.Holder; +import lombok.AllArgsConstructor; +import lombok.Data; +import org.jetbrains.annotations.Nullable; + +@Data +@AllArgsConstructor +public class BannerPatternLayer { + private final Holder pattern; + private final int colorId; + + @Data + @AllArgsConstructor + public static class BannerPattern { + private final String assetId; + private final String translationKey; + } +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/BeehiveOccupant.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/BeehiveOccupant.java new file mode 100644 index 00000000..d8392c7e --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/BeehiveOccupant.java @@ -0,0 +1,13 @@ +package org.geysermc.mcprotocollib.protocol.data.game.item.component; + +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class BeehiveOccupant { + private final CompoundTag entityData; + private final int ticksInHive; + private final int minTicksInHive; +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/BlockStateProperties.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/BlockStateProperties.java new file mode 100644 index 00000000..803198ef --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/BlockStateProperties.java @@ -0,0 +1,12 @@ +package org.geysermc.mcprotocollib.protocol.data.game.item.component; + +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.util.Map; + +@Data +@AllArgsConstructor +public class BlockStateProperties { + private final Map properties; +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/BooleanComponentType.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/BooleanComponentType.java new file mode 100644 index 00000000..498535f0 --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/BooleanComponentType.java @@ -0,0 +1,60 @@ +package org.geysermc.mcprotocollib.protocol.data.game.item.component; + +import org.geysermc.mcprotocollib.protocol.data.game.item.component.type.BooleanDataComponent; +import io.netty.buffer.ByteBuf; + +public class BooleanComponentType extends DataComponentType { + protected final BooleanReader primitiveReader; + protected final BooleanWriter primitiveWriter; + protected final BooleanDataComponentFactory primitiveFactory; + + protected BooleanComponentType(BooleanReader reader, BooleanWriter writer, BooleanDataComponentFactory metadataFactory) { + super(reader, writer, metadataFactory); + + this.primitiveReader = reader; + this.primitiveWriter = writer; + this.primitiveFactory = metadataFactory; + } + + @Override + public DataComponent readDataComponent(ItemCodecHelper helper, ByteBuf input) { + return this.primitiveFactory.createPrimitive(this, this.primitiveReader.readPrimitive(input)); + } + + public void writeDataComponentPrimitive(ByteBuf output, boolean value) { + this.primitiveWriter.writePrimitive(output, value); + } + + @FunctionalInterface + public interface BooleanReader extends BasicReader { + boolean readPrimitive(ByteBuf input); + + @Deprecated + @Override + default Boolean read(ByteBuf input) { + return this.readPrimitive(input); + } + } + + @FunctionalInterface + public interface BooleanWriter extends BasicWriter { + void writePrimitive(ByteBuf output, boolean value); + + @Deprecated + @Override + default void write(ByteBuf output, Boolean value) { + this.writePrimitive(output, value); + } + } + + @FunctionalInterface + public interface BooleanDataComponentFactory extends DataComponentFactory { + BooleanDataComponent createPrimitive(BooleanComponentType type, boolean value); + + @Deprecated + @Override + default DataComponent create(DataComponentType type, Boolean value) { + throw new UnsupportedOperationException("Unsupported read method! Use primitive createPrimitive!"); + } + } +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/DataComponent.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/DataComponent.java new file mode 100644 index 00000000..f59dc034 --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/DataComponent.java @@ -0,0 +1,50 @@ +package org.geysermc.mcprotocollib.protocol.data.game.item.component; + +import org.geysermc.mcprotocollib.protocol.data.game.item.component.type.ObjectDataComponent; +import io.netty.buffer.ByteBuf; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NonNull; + +import java.util.Objects; + +@Data +@AllArgsConstructor +public abstract class DataComponent> { + protected final @NonNull T type; + + /** + * May be null depending on type + */ + public abstract V getValue(); + + /** + * Overridden for primitive classes. This write method still checks for these primitives in the event + * they are manually created using {@link ObjectDataComponent}. + */ + public void write(ItemCodecHelper helper, ByteBuf out) { + this.type.writeDataComponent(helper, out, this.getValue()); + } + + @Override + public String toString() { + return "DataComponent(type=" + type + ", value=" + getValue().toString() + ")"; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof DataComponent)) { + return false; + } + DataComponent that = (DataComponent) o; + return this.type == that.type && Objects.equals(this.getValue(), that.getValue()); + } + + @Override + public int hashCode() { + return Objects.hash(type, getValue()); + } +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/DataComponentType.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/DataComponentType.java new file mode 100644 index 00000000..cdd645ba --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/DataComponentType.java @@ -0,0 +1,185 @@ +package org.geysermc.mcprotocollib.protocol.data.game.item.component; + +import com.github.steveice10.mc.auth.data.GameProfile; +import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper; +import org.geysermc.mcprotocollib.protocol.data.game.Holder; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.type.BooleanDataComponent; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.type.IntDataComponent; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.type.ObjectDataComponent; +import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import com.github.steveice10.opennbt.tag.builtin.ListTag; +import com.github.steveice10.opennbt.tag.builtin.StringTag; +import io.netty.buffer.ByteBuf; +import lombok.Getter; +import net.kyori.adventure.text.Component; + +import java.util.ArrayList; +import java.util.List; + +@Getter +public class DataComponentType { + private static final List> VALUES = new ArrayList<>(); + + public static final DataComponentType CUSTOM_DATA = new DataComponentType<>(ItemCodecHelper::readAnyTag, ItemCodecHelper::writeAnyTag, ObjectDataComponent::new); + public static final IntComponentType MAX_STACK_SIZE = new IntComponentType(ItemCodecHelper::readVarInt, ItemCodecHelper::writeVarInt, IntDataComponent::new); + public static final IntComponentType MAX_DAMAGE = new IntComponentType(ItemCodecHelper::readVarInt, ItemCodecHelper::writeVarInt, IntDataComponent::new); + public static final IntComponentType DAMAGE = new IntComponentType(ItemCodecHelper::readVarInt, ItemCodecHelper::writeVarInt, IntDataComponent::new); + public static final BooleanComponentType UNBREAKABLE = new BooleanComponentType(ByteBuf::readBoolean, ByteBuf::writeBoolean, BooleanDataComponent::new); + public static final DataComponentType CUSTOM_NAME = new DataComponentType<>(ItemCodecHelper::readComponent, ItemCodecHelper::writeComponent, ObjectDataComponent::new); + public static final DataComponentType ITEM_NAME = new DataComponentType<>(ItemCodecHelper::readComponent, ItemCodecHelper::writeComponent, ObjectDataComponent::new); + public static final DataComponentType> LORE = new DataComponentType<>(listReader(ItemCodecHelper::readComponent), listWriter(ItemCodecHelper::writeComponent), ObjectDataComponent::new); + public static final IntComponentType RARITY = new IntComponentType(ItemCodecHelper::readVarInt, ItemCodecHelper::writeVarInt, IntDataComponent::new); + public static final DataComponentType ENCHANTMENTS = new DataComponentType<>(ItemCodecHelper::readItemEnchantments, ItemCodecHelper::writeItemEnchantments, ObjectDataComponent::new); + public static final DataComponentType CAN_PLACE_ON = new DataComponentType<>(ItemCodecHelper::readAdventureModePredicate, ItemCodecHelper::writeAdventureModePredicate, ObjectDataComponent::new); + public static final DataComponentType CAN_BREAK = new DataComponentType<>(ItemCodecHelper::readAdventureModePredicate, ItemCodecHelper::writeAdventureModePredicate, ObjectDataComponent::new); + public static final DataComponentType ATTRIBUTE_MODIFIERS = new DataComponentType<>(ItemCodecHelper::readItemAttributeModifiers, ItemCodecHelper::writeItemAttributeModifiers, ObjectDataComponent::new); + public static final IntComponentType CUSTOM_MODEL_DATA = new IntComponentType(ItemCodecHelper::readVarInt, ItemCodecHelper::writeVarInt, IntDataComponent::new); + public static final DataComponentType HIDE_ADDITIONAL_TOOLTIP = new DataComponentType<>(unitReader(), unitWriter(), ObjectDataComponent::new); + public static final DataComponentType HIDE_TOOLTIP = new DataComponentType<>(unitReader(), unitWriter(), ObjectDataComponent::new); + public static final IntComponentType REPAIR_COST = new IntComponentType(ItemCodecHelper::readVarInt, ItemCodecHelper::writeVarInt, IntDataComponent::new); + public static final DataComponentType CREATIVE_SLOT_LOCK = new DataComponentType<>(unitReader(), unitWriter(), ObjectDataComponent::new); + public static final BooleanComponentType ENCHANTMENT_GLINT_OVERRIDE = new BooleanComponentType(ByteBuf::readBoolean, ByteBuf::writeBoolean, BooleanDataComponent::new); + public static final DataComponentType INTANGIBLE_PROJECTILE = new DataComponentType<>(ItemCodecHelper::readAnyTag, ItemCodecHelper::writeAnyTag, ObjectDataComponent::new); + public static final DataComponentType FOOD = new DataComponentType<>(ItemCodecHelper::readFoodProperties, ItemCodecHelper::writeFoodProperties, ObjectDataComponent::new); + public static final DataComponentType FIRE_RESISTANT = new DataComponentType<>(unitReader(), unitWriter(), ObjectDataComponent::new); + public static final DataComponentType TOOL = new DataComponentType<>(ItemCodecHelper::readToolData, ItemCodecHelper::writeToolData, ObjectDataComponent::new); + public static final DataComponentType STORED_ENCHANTMENTS = new DataComponentType<>(ItemCodecHelper::readItemEnchantments, ItemCodecHelper::writeItemEnchantments, ObjectDataComponent::new); + public static final DataComponentType DYED_COLOR = new DataComponentType<>(ItemCodecHelper::readDyedItemColor, ItemCodecHelper::writeDyedItemColor, ObjectDataComponent::new); + public static final IntComponentType MAP_COLOR = new IntComponentType((helper, input) -> input.readInt(), (helper, output, value) -> output.writeInt(value), IntDataComponent::new); + public static final IntComponentType MAP_ID = new IntComponentType(ItemCodecHelper::readVarInt, ItemCodecHelper::writeVarInt, IntDataComponent::new); + public static final DataComponentType MAP_DECORATIONS = new DataComponentType<>(ItemCodecHelper::readAnyTag, ItemCodecHelper::writeAnyTag, ObjectDataComponent::new); + public static final IntComponentType MAP_POST_PROCESSING = new IntComponentType(ItemCodecHelper::readVarInt, ItemCodecHelper::writeVarInt, IntDataComponent::new); + public static final DataComponentType> CHARGED_PROJECTILES = new DataComponentType<>(listReader(ItemCodecHelper::readItemStack), listWriter(ItemCodecHelper::writeItemStack), ObjectDataComponent::new); + public static final DataComponentType> BUNDLE_CONTENTS = new DataComponentType<>(listReader(ItemCodecHelper::readItemStack), listWriter(ItemCodecHelper::writeItemStack), ObjectDataComponent::new); + public static final DataComponentType POTION_CONTENTS = new DataComponentType<>(ItemCodecHelper::readPotionContents, ItemCodecHelper::writePotionContents, ObjectDataComponent::new); + public static final DataComponentType> SUSPICIOUS_STEW_EFFECTS = new DataComponentType<>(listReader(ItemCodecHelper::readStewEffect), listWriter(ItemCodecHelper::writeStewEffect), ObjectDataComponent::new); + public static final DataComponentType WRITABLE_BOOK_CONTENT = new DataComponentType<>(ItemCodecHelper::readWritableBookContent, ItemCodecHelper::writeWritableBookContent, ObjectDataComponent::new); + public static final DataComponentType WRITTEN_BOOK_CONTENT = new DataComponentType<>(ItemCodecHelper::readWrittenBookContent, ItemCodecHelper::writeWrittenBookContent, ObjectDataComponent::new); + public static final DataComponentType TRIM = new DataComponentType<>(ItemCodecHelper::readArmorTrim, ItemCodecHelper::writeArmorTrim, ObjectDataComponent::new); + public static final DataComponentType DEBUG_STICK_STATE = new DataComponentType<>(ItemCodecHelper::readAnyTag, ItemCodecHelper::writeAnyTag, ObjectDataComponent::new); + public static final DataComponentType ENTITY_DATA = new DataComponentType<>(ItemCodecHelper::readAnyTag, ItemCodecHelper::writeAnyTag, ObjectDataComponent::new); + public static final DataComponentType BUCKET_ENTITY_DATA = new DataComponentType<>(ItemCodecHelper::readAnyTag, ItemCodecHelper::writeAnyTag, ObjectDataComponent::new); + public static final DataComponentType BLOCK_ENTITY_DATA = new DataComponentType<>(ItemCodecHelper::readAnyTag, ItemCodecHelper::writeAnyTag, ObjectDataComponent::new); + public static final DataComponentType> INSTRUMENT = new DataComponentType<>(ItemCodecHelper::readInstrument, ItemCodecHelper::writeInstrument, ObjectDataComponent::new); + public static final IntComponentType OMINOUS_BOTTLE_AMPLIFIER = new IntComponentType(ItemCodecHelper::readVarInt, ItemCodecHelper::writeVarInt, IntDataComponent::new); + public static final DataComponentType RECIPES = new DataComponentType<>(ItemCodecHelper::readRecipes, ItemCodecHelper::writeRecipes, ObjectDataComponent::new); + public static final DataComponentType LODESTONE_TRACKER = new DataComponentType<>(ItemCodecHelper::readLodestoneTarget, ItemCodecHelper::writeLodestoneTarget, ObjectDataComponent::new); + public static final DataComponentType FIREWORK_EXPLOSION = new DataComponentType<>(ItemCodecHelper::readFireworkExplosion, ItemCodecHelper::writeFireworkExplosion, ObjectDataComponent::new); + public static final DataComponentType FIREWORKS = new DataComponentType<>(ItemCodecHelper::readFireworks, ItemCodecHelper::writeFireworks, ObjectDataComponent::new); + public static final DataComponentType PROFILE = new DataComponentType<>(ItemCodecHelper::readResolvableProfile, ItemCodecHelper::writeResolvableProfile, ObjectDataComponent::new); + public static final DataComponentType NOTE_BLOCK_SOUND = new DataComponentType<>(ItemCodecHelper::readResourceLocation, ItemCodecHelper::writeResourceLocation, ObjectDataComponent::new); + public static final DataComponentType> BANNER_PATTERNS = new DataComponentType<>(listReader(ItemCodecHelper::readBannerPatternLayer), listWriter(ItemCodecHelper::writeBannerPatternLayer), ObjectDataComponent::new); + public static final IntComponentType BASE_COLOR = new IntComponentType(ItemCodecHelper::readVarInt, ItemCodecHelper::writeVarInt, IntDataComponent::new); + public static final DataComponentType> POT_DECORATIONS = new DataComponentType<>(listReader(ItemCodecHelper::readVarInt), listWriter(ItemCodecHelper::writeVarInt), ObjectDataComponent::new); + public static final DataComponentType> CONTAINER = new DataComponentType<>(listReader(ItemCodecHelper::readOptionalItemStack), listWriter(MinecraftCodecHelper::writeOptionalItemStack), ObjectDataComponent::new); + public static final DataComponentType BLOCK_STATE = new DataComponentType<>(ItemCodecHelper::readBlockStateProperties, ItemCodecHelper::writeBlockStateProperties, ObjectDataComponent::new); + public static final DataComponentType> BEES = new DataComponentType<>(listReader(ItemCodecHelper::readBeehiveOccupant), listWriter(ItemCodecHelper::writeBeehiveOccupant), ObjectDataComponent::new); + public static final DataComponentType LOCK = new DataComponentType<>(ItemCodecHelper::readLock, ItemCodecHelper::writeLock, ObjectDataComponent::new); + public static final DataComponentType CONTAINER_LOOT = new DataComponentType<>(ItemCodecHelper::readAnyTag, ItemCodecHelper::writeAnyTag, ObjectDataComponent::new); + + protected final int id; + protected final Reader reader; + protected final Writer writer; + protected final DataComponentFactory dataComponentFactory; + + protected DataComponentType(Reader reader, Writer writer, DataComponentFactory dataComponentFactory) { + this.id = VALUES.size(); + this.reader = reader; + this.writer = writer; + this.dataComponentFactory = dataComponentFactory; + + VALUES.add(this); + } + + public DataComponent> readDataComponent(ItemCodecHelper helper, ByteBuf input) { + return this.dataComponentFactory.create(this, this.reader.read(helper, input)); + } + + public DataComponent> readNullDataComponent() { + return this.dataComponentFactory.create(this, null); + } + + public void writeDataComponent(ItemCodecHelper helper, ByteBuf output, T value) { + this.writer.write(helper, output, value); + } + + @FunctionalInterface + public interface Reader { + V read(ItemCodecHelper helper, ByteBuf input); + } + + @FunctionalInterface + public interface Writer { + void write(ItemCodecHelper helper, ByteBuf output, V value); + } + + @FunctionalInterface + public interface BasicReader extends Reader { + V read(ByteBuf input); + + default V read(ItemCodecHelper helper, ByteBuf input) { + return this.read(input); + } + } + + @FunctionalInterface + public interface BasicWriter extends Writer { + void write(ByteBuf output, V Value); + + default void write(ItemCodecHelper helper, ByteBuf output, V value) { + this.write(output, value); + } + } + + @FunctionalInterface + public interface DataComponentFactory { + DataComponent> create(DataComponentType type, V value); + } + + private static Reader> listReader(Reader reader) { + return (helper, input) -> { + List ret = new ArrayList<>(); + int size = helper.readVarInt(input); + for (int i = 0; i < size; i++) { + ret.add(reader.read(helper, input)); + } + + return ret; + }; + } + + private static Writer> listWriter(Writer writer) { + return (helper, output, value) -> { + helper.writeVarInt(output, value.size()); + for (T object : value) { + writer.write(helper, output, object); + } + }; + } + + private static Reader unitReader() { + return (helper, input) -> Unit.INSTANCE; + } + + private static Writer unitWriter() { + return (helper, output, value) -> {}; + } + + public static DataComponentType read(ByteBuf in, MinecraftCodecHelper helper) { + int id = helper.readVarInt(in); + if (id >= VALUES.size()) { + throw new IllegalArgumentException("Received id " + id + " for DataComponentType when the maximum was " + VALUES.size() + "!"); + } + + return VALUES.get(id); + } + + public static DataComponentType from(int id) { + return VALUES.get(id); + } + + public static int size() { + return VALUES.size(); + } +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/DataComponents.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/DataComponents.java new file mode 100644 index 00000000..d29501e9 --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/DataComponents.java @@ -0,0 +1,40 @@ +package org.geysermc.mcprotocollib.protocol.data.game.item.component; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NonNull; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.Map; + +@Data +@AllArgsConstructor +public class DataComponents { + private final Map, DataComponent> dataComponents; + + @Nullable + public T get(DataComponentType type) { + DataComponent component = dataComponents.get(type); + return component == null ? null : (T) component.getValue(); + } + + public T getOrDefault(DataComponentType type, T def) { + T value = get(type); + return value != null ? value : def; + } + + public void put(DataComponentType type, @NonNull T value) { + if (type instanceof IntComponentType intType) { + dataComponents.put(intType, intType.primitiveFactory.createPrimitive(intType, (Integer) value)); + } else if (type instanceof BooleanComponentType boolType) { + dataComponents.put(boolType, boolType.primitiveFactory.createPrimitive(boolType, (Boolean) value)); + } else { + dataComponents.put(type, type.dataComponentFactory.create(type, value)); + } + } + + public DataComponents clone() { + return new DataComponents(new HashMap<>(dataComponents)); + } +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/DyedItemColor.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/DyedItemColor.java new file mode 100644 index 00000000..99e57fc6 --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/DyedItemColor.java @@ -0,0 +1,11 @@ +package org.geysermc.mcprotocollib.protocol.data.game.item.component; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class DyedItemColor { + private final int rgb; + private final boolean showInTooltip; +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/Filterable.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/Filterable.java new file mode 100644 index 00000000..43e319bf --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/Filterable.java @@ -0,0 +1,12 @@ +package org.geysermc.mcprotocollib.protocol.data.game.item.component; + +import lombok.AllArgsConstructor; +import lombok.Data; +import org.jetbrains.annotations.Nullable; + +@Data +@AllArgsConstructor +public class Filterable { + private final T raw; + private final @Nullable T optional; +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/Fireworks.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/Fireworks.java new file mode 100644 index 00000000..da0ac7ce --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/Fireworks.java @@ -0,0 +1,23 @@ +package org.geysermc.mcprotocollib.protocol.data.game.item.component; + +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.util.List; + +@Data +@AllArgsConstructor +public class Fireworks { + private final int flightDuration; + private final List explosions; + + @Data + @AllArgsConstructor + public static class FireworkExplosion { + private final int shapeId; + private final int[] colors; + private final int[] fadeColors; + private final boolean hasTrail; + private final boolean hasTwinkle; + } +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/FoodProperties.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/FoodProperties.java new file mode 100644 index 00000000..8a3614ee --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/FoodProperties.java @@ -0,0 +1,23 @@ +package org.geysermc.mcprotocollib.protocol.data.game.item.component; + +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.util.List; + +@Data +@AllArgsConstructor +public class FoodProperties { + private final int nutrition; + private final float saturationModifier; + private final boolean canAlwaysEat; + private final float eatSeconds; + private final List effects; + + @Data + @AllArgsConstructor + public static class PossibleEffect { + private final MobEffectDetails effect; + private final float probability; + } +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/Instrument.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/Instrument.java new file mode 100644 index 00000000..19bac8be --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/Instrument.java @@ -0,0 +1,13 @@ +package org.geysermc.mcprotocollib.protocol.data.game.item.component; + +import org.geysermc.mcprotocollib.protocol.data.game.level.sound.Sound; +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class Instrument { + private final Sound soundEvent; + private final int useDuration; + private final float range; +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/IntComponentType.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/IntComponentType.java new file mode 100644 index 00000000..66c4173c --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/IntComponentType.java @@ -0,0 +1,60 @@ +package org.geysermc.mcprotocollib.protocol.data.game.item.component; + +import org.geysermc.mcprotocollib.protocol.data.game.item.component.type.IntDataComponent; +import io.netty.buffer.ByteBuf; + +public class IntComponentType extends DataComponentType { + protected final IntReader primitiveReader; + protected final IntWriter primitiveWriter; + protected final IntDataComponentFactory primitiveFactory; + + protected IntComponentType(IntReader reader, IntWriter writer, IntDataComponentFactory metadataFactory) { + super(reader, writer, metadataFactory); + + this.primitiveReader = reader; + this.primitiveWriter = writer; + this.primitiveFactory = metadataFactory; + } + + @Override + public DataComponent readDataComponent(ItemCodecHelper helper, ByteBuf input) { + return this.primitiveFactory.createPrimitive(this, this.primitiveReader.readPrimitive(helper, input)); + } + + public void writeDataComponentPrimitive(ItemCodecHelper helper, ByteBuf output, int value) { + this.primitiveWriter.writePrimitive(helper, output, value); + } + + @FunctionalInterface + public interface IntReader extends Reader { + int readPrimitive(ItemCodecHelper helper, ByteBuf input); + + @Deprecated + @Override + default Integer read(ItemCodecHelper helper, ByteBuf input) { + return this.readPrimitive(helper, input); + } + } + + @FunctionalInterface + public interface IntWriter extends Writer { + void writePrimitive(ItemCodecHelper helper, ByteBuf output, int value); + + @Deprecated + @Override + default void write(ItemCodecHelper helper, ByteBuf output, Integer value) { + this.writePrimitive(helper, output, value); + } + } + + @FunctionalInterface + public interface IntDataComponentFactory extends DataComponentFactory { + IntDataComponent createPrimitive(IntComponentType type, int value); + + @Deprecated + @Override + default DataComponent create(DataComponentType type, Integer value) { + throw new UnsupportedOperationException("Unsupported read method! Use primitive createPrimitive!"); + } + } +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/ItemAttributeModifiers.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/ItemAttributeModifiers.java new file mode 100644 index 00000000..5d40aadf --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/ItemAttributeModifiers.java @@ -0,0 +1,51 @@ +package org.geysermc.mcprotocollib.protocol.data.game.item.component; + +import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.ModifierOperation; +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.util.List; +import java.util.UUID; + +@Data +@AllArgsConstructor +public class ItemAttributeModifiers { + private final List modifiers; + private final boolean showInTooltip; + + @Data + @AllArgsConstructor + public static class Entry { + private final int attribute; + private final AttributeModifier modifier; + private final EquipmentSlotGroup slot; + } + + @Data + @AllArgsConstructor + public static class AttributeModifier { + private final UUID id; + private final String name; + private final double amount; + private final ModifierOperation operation; + } + + public enum EquipmentSlotGroup { + ANY, + MAIN_HAND, + OFF_HAND, + HAND, + FEET, + LEGS, + CHEST, + HEAD, + ARMOR, + BODY; + + private static final EquipmentSlotGroup[] VALUES = values(); + + public static EquipmentSlotGroup from(int id) { + return VALUES[id]; + } + } +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/ItemCodecHelper.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/ItemCodecHelper.java new file mode 100644 index 00000000..2409c8b3 --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/ItemCodecHelper.java @@ -0,0 +1,620 @@ +package org.geysermc.mcprotocollib.protocol.data.game.item.component; + +import com.github.steveice10.mc.auth.data.GameProfile; +import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper; +import org.geysermc.mcprotocollib.protocol.data.game.Holder; +import org.geysermc.mcprotocollib.protocol.data.game.entity.attribute.ModifierOperation; +import org.geysermc.mcprotocollib.protocol.data.game.level.sound.BuiltinSound; +import org.geysermc.mcprotocollib.protocol.data.game.level.sound.CustomSound; +import org.geysermc.mcprotocollib.protocol.data.game.level.sound.Sound; +import com.github.steveice10.opennbt.tag.builtin.ListTag; +import com.github.steveice10.opennbt.tag.builtin.StringTag; +import io.netty.buffer.ByteBuf; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import net.kyori.adventure.text.Component; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.function.BiConsumer; +import java.util.function.Function; + + +public class ItemCodecHelper extends MinecraftCodecHelper { + public static ItemCodecHelper INSTANCE = new ItemCodecHelper(); + + public ItemCodecHelper() { + super(Int2ObjectMaps.emptyMap(), Collections.emptyMap()); + } + + public Filterable readFilterable(ByteBuf buf, Function reader) { + T raw = reader.apply(buf); + T filtered = null; + if (buf.readBoolean()) { + filtered = reader.apply(buf); + } + return new Filterable<>(raw, filtered); + } + + public void writeFilterable(ByteBuf buf, Filterable filterable, BiConsumer writer) { + writer.accept(buf, filterable.getRaw()); + if (filterable.getOptional() != null) { + buf.writeBoolean(true); + writer.accept(buf, filterable.getOptional()); + } else { + buf.writeBoolean(false); + } + } + + public ItemEnchantments readItemEnchantments(ByteBuf buf) { + Map enchantments = new HashMap<>(); + int enchantmentCount = this.readVarInt(buf); + for (int i = 0; i < enchantmentCount; i++) { + enchantments.put(this.readVarInt(buf), this.readVarInt(buf)); + } + + return new ItemEnchantments(enchantments, buf.readBoolean()); + } + + public void writeItemEnchantments(ByteBuf buf, ItemEnchantments itemEnchantments) { + this.writeVarInt(buf, itemEnchantments.getEnchantments().size()); + for (Map.Entry entry : itemEnchantments.getEnchantments().entrySet()) { + this.writeVarInt(buf, entry.getKey()); + this.writeVarInt(buf, entry.getValue()); + } + + buf.writeBoolean(itemEnchantments.isShowInTooltip()); + } + + public AdventureModePredicate readAdventureModePredicate(ByteBuf buf) { + List predicates = new ArrayList<>(); + int predicateCount = this.readVarInt(buf); + for (int i = 0; i < predicateCount; i++) { + predicates.add(this.readBlockPredicate(buf)); + } + + return new AdventureModePredicate(predicates, buf.readBoolean()); + } + + public void writeAdventureModePredicate(ByteBuf buf, AdventureModePredicate adventureModePredicate) { + this.writeVarInt(buf, adventureModePredicate.getPredicates().size()); + for (AdventureModePredicate.BlockPredicate predicate : adventureModePredicate.getPredicates()) { + this.writeBlockPredicate(buf, predicate); + } + + buf.writeBoolean(adventureModePredicate.isShowInTooltip()); + } + + public AdventureModePredicate.BlockPredicate readBlockPredicate(ByteBuf buf) { + String location = null; + int[] holders = null; + List propertyMatchers = null; + + if (buf.readBoolean()) { + int length = this.readVarInt(buf) - 1; + if (length == -1) { + location = this.readResourceLocation(buf); + } else { + holders = new int[length]; + for (int i = 0; i < length; i++) { + holders[i] = this.readVarInt(buf); + } + } + } + + if (buf.readBoolean()) { + propertyMatchers = new ArrayList<>(); + int matcherCount = this.readVarInt(buf); + for (int i = 0; i < matcherCount; i++) { + String name = this.readString(buf); + if (buf.readBoolean()) { + propertyMatchers.add(new AdventureModePredicate.PropertyMatcher(name, this.readString(buf), null, null)); + } else { + propertyMatchers.add(new AdventureModePredicate.PropertyMatcher(name, null, this.readString(buf), this.readString(buf))); + } + } + } + + return new AdventureModePredicate.BlockPredicate(location, holders, propertyMatchers, this.readNullable(buf, this::readAnyTag)); + } + + public void writeBlockPredicate(ByteBuf buf, AdventureModePredicate.BlockPredicate blockPredicate) { + if (blockPredicate.getLocation() == null && blockPredicate.getHolders() == null) { + buf.writeBoolean(false); + } else { + buf.writeBoolean(true); + if (blockPredicate.getLocation() != null) { + this.writeVarInt(buf, 0); + this.writeResourceLocation(buf, blockPredicate.getLocation()); + } else { + this.writeVarInt(buf, blockPredicate.getHolders().length + 1); + for (int holder : blockPredicate.getHolders()) { + this.writeVarInt(buf, holder); + } + } + } + + if (blockPredicate.getProperties() == null) { + buf.writeBoolean(false); + } else { + buf.writeBoolean(true); + for (AdventureModePredicate.PropertyMatcher matcher : blockPredicate.getProperties()) { + this.writeString(buf, matcher.getName()); + if (matcher.getValue() != null) { + buf.writeBoolean(true); + this.writeString(buf, matcher.getValue()); + } else { + buf.writeBoolean(false); + this.writeString(buf, matcher.getMinValue()); + this.writeString(buf, matcher.getMaxValue()); + } + } + } + + this.writeNullable(buf, blockPredicate.getNbt(), this::writeAnyTag); + } + + public ToolData readToolData(ByteBuf buf) { + List rules = new ArrayList<>(); + int ruleCount = this.readVarInt(buf); + for (int i = 0; i < ruleCount; i++) { + String location = null; + int[] holders = null; + + int length = this.readVarInt(buf) - 1; + if (length == -1) { + location = this.readResourceLocation(buf); + } else { + holders = new int[length]; + for (int j = 0; j < length; j++) { + holders[j] = this.readVarInt(buf); + } + } + + Float speed = this.readNullable(buf, ByteBuf::readFloat); + Boolean correctForDrops = this.readNullable(buf, ByteBuf::readBoolean); + rules.add(new ToolData.Rule(location, holders, speed, correctForDrops)); + } + + float defaultMiningSpeed = buf.readFloat(); + int damagePerBlock = this.readVarInt(buf); + return new ToolData(rules, defaultMiningSpeed, damagePerBlock); + } + + public void writeToolData(ByteBuf buf, ToolData data) { + this.writeVarInt(buf, data.getRules().size()); + for (ToolData.Rule rule : data.getRules()) { + if (rule.getLocation() != null) { + this.writeVarInt(buf, 0); + this.writeResourceLocation(buf, rule.getLocation()); + } else { + this.writeVarInt(buf, rule.getHolders().length + 1); + for (int holder : rule.getHolders()) { + this.writeVarInt(buf, holder); + } + } + + this.writeNullable(buf, rule.getSpeed(), ByteBuf::writeFloat); + this.writeNullable(buf, rule.getCorrectForDrops(), ByteBuf::writeBoolean); + } + + buf.writeFloat(data.getDefaultMiningSpeed()); + this.writeVarInt(buf, data.getDamagePerBlock()); + } + + public ItemAttributeModifiers readItemAttributeModifiers(ByteBuf buf) { + List modifiers = new ArrayList<>(); + int modifierCount = this.readVarInt(buf); + for (int i = 0; i < modifierCount; i++) { + int attribute = this.readVarInt(buf); + + UUID id = this.readUUID(buf); + String name = this.readString(buf); + double amount = buf.readDouble(); + ModifierOperation operation = ModifierOperation.from(this.readVarInt(buf)); + ItemAttributeModifiers.AttributeModifier modifier = new ItemAttributeModifiers.AttributeModifier(id, name, amount, operation); + + ItemAttributeModifiers.EquipmentSlotGroup slot = ItemAttributeModifiers.EquipmentSlotGroup.from(this.readVarInt(buf)); + modifiers.add(new ItemAttributeModifiers.Entry(attribute, modifier, slot)); + } + + return new ItemAttributeModifiers(modifiers, buf.readBoolean()); + } + + public void writeItemAttributeModifiers(ByteBuf buf, ItemAttributeModifiers modifiers) { + this.writeVarInt(buf, modifiers.getModifiers().size()); + for (ItemAttributeModifiers.Entry modifier : modifiers.getModifiers()) { + this.writeVarInt(buf, modifier.getAttribute()); + + this.writeUUID(buf, modifier.getModifier().getId()); + this.writeString(buf, modifier.getModifier().getName()); + buf.writeDouble(modifier.getModifier().getAmount()); + this.writeVarInt(buf, modifier.getModifier().getOperation().ordinal()); + + this.writeVarInt(buf, modifier.getSlot().ordinal()); + } + + buf.writeBoolean(modifiers.isShowInTooltip()); + } + + public DyedItemColor readDyedItemColor(ByteBuf buf) { + return new DyedItemColor(buf.readInt(), buf.readBoolean()); + } + + public void writeDyedItemColor(ByteBuf buf, DyedItemColor itemColor) { + buf.writeInt(itemColor.getRgb()); + buf.writeBoolean(itemColor.isShowInTooltip()); + } + + public PotionContents readPotionContents(ByteBuf buf) { + int potionId = buf.readBoolean() ? this.readVarInt(buf) : -1; + int customColor = buf.readBoolean() ? buf.readInt() : -1; + + Int2ObjectMap customEffects = new Int2ObjectOpenHashMap<>(); + int effectCount = this.readVarInt(buf); + for (int i = 0; i < effectCount; i++) { + customEffects.put(this.readVarInt(buf), this.readEffectDetails(buf)); + } + return new PotionContents(potionId, customColor, customEffects); + } + + public void writePotionContents(ByteBuf buf, PotionContents contents) { + if (contents.getPotionId() < 0) { + buf.writeBoolean(false); + } else { + buf.writeBoolean(true); + this.writeVarInt(buf, contents.getPotionId()); + } + + if (contents.getCustomColor() < 0) { + buf.writeBoolean(false); + } else { + buf.writeBoolean(true); + buf.writeInt(contents.getCustomColor()); + } + + this.writeVarInt(buf, contents.getCustomEffects().size()); + for (Int2ObjectMap.Entry entry : contents.getCustomEffects().int2ObjectEntrySet()) { + this.writeVarInt(buf, entry.getIntKey()); + this.writeEffectDetails(buf, entry.getValue()); + } + } + + public FoodProperties readFoodProperties(ByteBuf buf) { + int nutrition = this.readVarInt(buf); + float saturationModifier = buf.readFloat(); + boolean canAlwaysEat = buf.readBoolean(); + float eatSeconds = buf.readFloat(); + + List effects = new ArrayList<>(); + int effectCount = this.readVarInt(buf); + for (int i = 0; i < effectCount; i++) { + effects.add(new FoodProperties.PossibleEffect(this.readEffectDetails(buf), buf.readFloat())); + } + + return new FoodProperties(nutrition, saturationModifier, canAlwaysEat, eatSeconds, effects); + } + + public void writeFoodProperties(ByteBuf buf, FoodProperties properties) { + this.writeVarInt(buf, properties.getNutrition()); + buf.writeFloat(properties.getSaturationModifier()); + buf.writeBoolean(properties.isCanAlwaysEat()); + buf.writeFloat(properties.getEatSeconds()); + + this.writeVarInt(buf, properties.getEffects().size()); + for (FoodProperties.PossibleEffect effect : properties.getEffects()) { + this.writeEffectDetails(buf, effect.getEffect()); + buf.writeFloat(effect.getProbability()); + } + } + + public MobEffectDetails readEffectDetails(ByteBuf buf) { + int amplifier = this.readVarInt(buf); + int duration = this.readVarInt(buf); + boolean ambient = buf.readBoolean(); + boolean showParticles = buf.readBoolean(); + boolean showIcon = buf.readBoolean(); + MobEffectDetails hiddenEffect = this.readNullable(buf, this::readEffectDetails); + return new MobEffectDetails(amplifier, duration, ambient, showParticles, showIcon, hiddenEffect); + } + + public void writeEffectDetails(ByteBuf buf, MobEffectDetails details) { + this.writeVarInt(buf, details.getAmplifier()); + this.writeVarInt(buf, details.getDuration()); + buf.writeBoolean(details.isAmbient()); + buf.writeBoolean(details.isShowParticles()); + buf.writeBoolean(details.isShowIcon()); + this.writeNullable(buf, details.getHiddenEffect(), this::writeEffectDetails); + } + + public SuspiciousStewEffect readStewEffect(ByteBuf buf) { + return new SuspiciousStewEffect(this.readVarInt(buf), this.readVarInt(buf)); + } + + public void writeStewEffect(ByteBuf buf, SuspiciousStewEffect effect) { + this.writeVarInt(buf, effect.getMobEffectId()); + this.writeVarInt(buf, effect.getDuration()); + } + + public WritableBookContent readWritableBookContent(ByteBuf buf) { + List> pages = new ArrayList<>(); + int pageCount = this.readVarInt(buf); + for (int i = 0; i < pageCount; i++) { + pages.add(this.readFilterable(buf, this::readString)); + } + + return new WritableBookContent(pages); + } + + public void writeWritableBookContent(ByteBuf buf, WritableBookContent content) { + this.writeVarInt(buf, content.getPages().size()); + for (Filterable page : content.getPages()) { + this.writeFilterable(buf, page, this::writeString); + } + } + + public WrittenBookContent readWrittenBookContent(ByteBuf buf) { + Filterable title = this.readFilterable(buf, this::readString); + String author = this.readString(buf); + int generation = this.readVarInt(buf); + + List> pages = new ArrayList<>(); + int pageCount = this.readVarInt(buf); + for (int i = 0; i < pageCount; i++) { + pages.add(this.readFilterable(buf, this::readComponent)); + } + + boolean resolved = buf.readBoolean(); + return new WrittenBookContent(title, author, generation, pages, resolved); + } + + public void writeWrittenBookContent(ByteBuf buf, WrittenBookContent content) { + this.writeFilterable(buf, content.getTitle(), this::writeString); + this.writeString(buf, content.getAuthor()); + this.writeVarInt(buf, content.getGeneration()); + + this.writeVarInt(buf, content.getPages().size()); + for (Filterable page : content.getPages()) { + this.writeFilterable(buf, page, this::writeComponent); + } + + buf.writeBoolean(content.isResolved()); + } + + public ArmorTrim readArmorTrim(ByteBuf buf) { + Holder material = this.readHolder(buf, this::readTrimMaterial); + Holder pattern = this.readHolder(buf, this::readTrimPattern); + boolean showInTooltip = buf.readBoolean(); + return new ArmorTrim(material, pattern, showInTooltip); + } + + public void writeArmorTrim(ByteBuf buf, ArmorTrim trim) { + this.writeHolder(buf, trim.material(), this::writeTrimMaterial); + this.writeHolder(buf, trim.pattern(), this::writeTrimPattern); + buf.writeBoolean(trim.showInTooltip()); + } + + public ArmorTrim.TrimMaterial readTrimMaterial(ByteBuf buf) { + String assetName = this.readString(buf); + int ingredientId = this.readVarInt(buf); + float itemModelIndex = buf.readFloat(); + + Int2ObjectMap overrideArmorMaterials = new Int2ObjectOpenHashMap<>(); + int overrideCount = this.readVarInt(buf); + for (int i = 0; i < overrideCount; i++) { + overrideArmorMaterials.put(this.readVarInt(buf), this.readString(buf)); + } + + Component description = this.readComponent(buf); + return new ArmorTrim.TrimMaterial(assetName, ingredientId, itemModelIndex, overrideArmorMaterials, description); + } + + public void writeTrimMaterial(ByteBuf buf, ArmorTrim.TrimMaterial material) { + this.writeString(buf, material.assetName()); + this.writeVarInt(buf, material.ingredientId()); + buf.writeFloat(material.itemModelIndex()); + + this.writeVarInt(buf, material.overrideArmorMaterials().size()); + for (Int2ObjectMap.Entry entry : material.overrideArmorMaterials().int2ObjectEntrySet()) { + this.writeVarInt(buf, entry.getIntKey()); + this.writeString(buf, entry.getValue()); + } + + this.writeComponent(buf, material.description()); + } + + public ArmorTrim.TrimPattern readTrimPattern(ByteBuf buf) { + String assetId = this.readResourceLocation(buf); + int templateItemId = this.readVarInt(buf); + Component description = this.readComponent(buf); + boolean decal = buf.readBoolean(); + return new ArmorTrim.TrimPattern(assetId, templateItemId, description, decal); + } + + public void writeTrimPattern(ByteBuf buf, ArmorTrim.TrimPattern pattern) { + this.writeResourceLocation(buf, pattern.assetId()); + this.writeVarInt(buf, pattern.templateItemId()); + this.writeComponent(buf, pattern.description()); + buf.writeBoolean(pattern.decal()); + } + + public Holder readInstrument(ByteBuf buf) { + return this.readHolder(buf, (input) -> { + Sound soundEvent = this.readById(input, BuiltinSound::from, this::readSoundEvent); + int useDuration = this.readVarInt(input); + float range = input.readFloat(); + return new Instrument(soundEvent, useDuration, range); + }); + } + + public void writeInstrument(ByteBuf buf, Holder instrumentHolder) { + this.writeHolder(buf, instrumentHolder, (output, instrument) -> { + if (instrument.getSoundEvent() instanceof CustomSound) { + this.writeVarInt(buf, 0); + this.writeSoundEvent(buf, instrument.getSoundEvent()); + } else { + this.writeVarInt(buf, ((BuiltinSound) instrument.getSoundEvent()).ordinal() + 1); + } + + this.writeVarInt(buf, instrument.getUseDuration()); + buf.writeFloat(instrument.getRange()); + }); + } + + public ListTag readRecipes(ByteBuf buf) { + return this.readAnyTag(buf, ListTag.class); + } + + public void writeRecipes(ByteBuf buf, ListTag recipes) { + this.writeAnyTag(buf, recipes); + } + + public LodestoneTracker readLodestoneTarget(ByteBuf buf) { + return new LodestoneTracker(this.readNullable(buf, this::readGlobalPos), buf.readBoolean()); + } + + public void writeLodestoneTarget(ByteBuf buf, LodestoneTracker target) { + this.writeNullable(buf, target.getPos(), this::writeGlobalPos); + buf.writeBoolean(target.isTracked()); + } + + public Fireworks readFireworks(ByteBuf buf) { + int flightDuration = this.readVarInt(buf); + + List explosions = new ArrayList<>(); + int explosionCount = this.readVarInt(buf); + for (int i = 0; i < explosionCount; i++) { + explosions.add(this.readFireworkExplosion(buf)); + } + + return new Fireworks(flightDuration, explosions); + } + + public void writeFireworks(ByteBuf buf, Fireworks fireworks) { + this.writeVarInt(buf, fireworks.getFlightDuration()); + + this.writeVarInt(buf, fireworks.getExplosions().size()); + for (Fireworks.FireworkExplosion explosion : fireworks.getExplosions()) { + this.writeFireworkExplosion(buf, explosion); + } + } + + public Fireworks.FireworkExplosion readFireworkExplosion(ByteBuf buf) { + int shapeId = this.readVarInt(buf); + + int[] colors = new int[this.readVarInt(buf)]; + for (int i = 0; i < colors.length; i++) { + colors[i] = buf.readInt(); + } + + int[] fadeColors = new int[this.readVarInt(buf)]; + for (int i = 0; i < fadeColors.length; i++) { + fadeColors[i] = buf.readInt(); + } + + boolean hasTrail = buf.readBoolean(); + boolean hasTwinkle = buf.readBoolean(); + return new Fireworks.FireworkExplosion(shapeId, colors, fadeColors, hasTrail, hasTwinkle); + } + + public void writeFireworkExplosion(ByteBuf buf, Fireworks.FireworkExplosion explosion) { + this.writeVarInt(buf, explosion.getShapeId()); + + this.writeVarInt(buf, explosion.getColors().length); + for (int color : explosion.getColors()) { + buf.writeInt(color); + } + + this.writeVarInt(buf, explosion.getFadeColors().length); + for (int fadeColor : explosion.getFadeColors()) { + buf.writeInt(fadeColor); + } + + buf.writeBoolean(explosion.isHasTrail()); + buf.writeBoolean(explosion.isHasTwinkle()); + } + + public GameProfile readResolvableProfile(ByteBuf buf) { + String name = this.readNullable(buf, this::readString); + UUID id = this.readNullable(buf, this::readUUID); + GameProfile profile = new GameProfile(id, name); + + List properties = new ArrayList<>(); + int propertyCount = this.readVarInt(buf); + for (int i = 0; i < propertyCount; i++) { + properties.add(this.readProperty(buf)); + } + profile.setProperties(properties); + + return profile; + } + + public void writeResolvableProfile(ByteBuf buf, GameProfile profile) { + this.writeNullable(buf, profile.getName(), this::writeString); + this.writeNullable(buf, profile.getId(), this::writeUUID); + + this.writeVarInt(buf, profile.getProperties().size()); + for (GameProfile.Property property : profile.getProperties()) { + this.writeProperty(buf, property); + } + } + + public BannerPatternLayer readBannerPatternLayer(ByteBuf buf) { + return new BannerPatternLayer(this.readHolder(buf, this::readBannerPattern), this.readVarInt(buf)); + } + + public void writeBannerPatternLayer(ByteBuf buf, BannerPatternLayer patternLayer) { + this.writeHolder(buf, patternLayer.getPattern(), this::writeBannerPattern); + this.writeVarInt(buf, patternLayer.getColorId()); + } + + public BannerPatternLayer.BannerPattern readBannerPattern(ByteBuf buf) { + return new BannerPatternLayer.BannerPattern(this.readResourceLocation(buf), this.readString(buf)); + } + + public void writeBannerPattern(ByteBuf buf, BannerPatternLayer.BannerPattern pattern) { + this.writeResourceLocation(buf, pattern.getAssetId()); + this.writeString(buf, pattern.getTranslationKey()); + } + + public BlockStateProperties readBlockStateProperties(ByteBuf buf) { + Map properties = new HashMap<>(); + int propertyCount = this.readVarInt(buf); + for (int i = 0; i < propertyCount; i++) { + properties.put(this.readString(buf), this.readString(buf)); + } + + return new BlockStateProperties(properties); + } + + public void writeBlockStateProperties(ByteBuf buf, BlockStateProperties props) { + this.writeVarInt(buf, props.getProperties().size()); + for (Map.Entry prop : props.getProperties().entrySet()) { + this.writeString(buf, prop.getKey()); + this.writeString(buf, prop.getValue()); + } + } + + public BeehiveOccupant readBeehiveOccupant(ByteBuf buf) { + return new BeehiveOccupant(this.readAnyTag(buf), this.readVarInt(buf), this.readVarInt(buf)); + } + + public void writeBeehiveOccupant(ByteBuf buf, BeehiveOccupant occupant) { + this.writeAnyTag(buf, occupant.getEntityData()); + this.writeVarInt(buf, occupant.getTicksInHive()); + this.writeVarInt(buf, occupant.getMinTicksInHive()); + } + + public StringTag readLock(ByteBuf buf) { + return this.readAnyTag(buf, StringTag.class); + } + + public void writeLock(ByteBuf buf, StringTag key) { + this.writeAnyTag(buf, key); + } +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/ItemEnchantments.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/ItemEnchantments.java new file mode 100644 index 00000000..db85a00b --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/ItemEnchantments.java @@ -0,0 +1,13 @@ +package org.geysermc.mcprotocollib.protocol.data.game.item.component; + +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.util.Map; + +@Data +@AllArgsConstructor +public class ItemEnchantments { + private final Map enchantments; + private final boolean showInTooltip; +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/LodestoneTracker.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/LodestoneTracker.java new file mode 100644 index 00000000..69b2611c --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/LodestoneTracker.java @@ -0,0 +1,13 @@ +package org.geysermc.mcprotocollib.protocol.data.game.item.component; + +import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.GlobalPos; +import lombok.AllArgsConstructor; +import lombok.Data; +import org.jetbrains.annotations.Nullable; + +@Data +@AllArgsConstructor +public class LodestoneTracker { + private final @Nullable GlobalPos pos; + private final boolean tracked; +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/MobEffectDetails.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/MobEffectDetails.java new file mode 100644 index 00000000..4669f6cf --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/MobEffectDetails.java @@ -0,0 +1,16 @@ +package org.geysermc.mcprotocollib.protocol.data.game.item.component; + +import lombok.AllArgsConstructor; +import lombok.Data; +import org.jetbrains.annotations.Nullable; + +@Data +@AllArgsConstructor +public class MobEffectDetails { + private final int amplifier; + private final int duration; + private final boolean ambient; + private final boolean showParticles; + private final boolean showIcon; + private final @Nullable MobEffectDetails hiddenEffect; +} \ No newline at end of file diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/PotionContents.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/PotionContents.java new file mode 100644 index 00000000..b1eab367 --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/PotionContents.java @@ -0,0 +1,13 @@ +package org.geysermc.mcprotocollib.protocol.data.game.item.component; + +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class PotionContents { + private final int potionId; + private final int customColor; + private final Int2ObjectMap customEffects; +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/SuspiciousStewEffect.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/SuspiciousStewEffect.java new file mode 100644 index 00000000..53479b77 --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/SuspiciousStewEffect.java @@ -0,0 +1,11 @@ +package org.geysermc.mcprotocollib.protocol.data.game.item.component; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class SuspiciousStewEffect { + private final int mobEffectId; + private final int duration; +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/ToolData.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/ToolData.java new file mode 100644 index 00000000..bd1bb9d1 --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/ToolData.java @@ -0,0 +1,24 @@ +package org.geysermc.mcprotocollib.protocol.data.game.item.component; + +import lombok.AllArgsConstructor; +import lombok.Data; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +@Data +@AllArgsConstructor +public class ToolData { + private final List rules; + private final float defaultMiningSpeed; + private final int damagePerBlock; + + @Data + @AllArgsConstructor + public static class Rule { + private final @Nullable String location; + private final int @Nullable[] holders; + private final @Nullable Float speed; + private final @Nullable Boolean correctForDrops; + } +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/Unit.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/Unit.java new file mode 100644 index 00000000..8e8d3263 --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/Unit.java @@ -0,0 +1,5 @@ +package org.geysermc.mcprotocollib.protocol.data.game.item.component; + +public enum Unit { + INSTANCE; +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/WritableBookContent.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/WritableBookContent.java new file mode 100644 index 00000000..6ee38c53 --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/WritableBookContent.java @@ -0,0 +1,12 @@ +package org.geysermc.mcprotocollib.protocol.data.game.item.component; + +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.util.List; + +@Data +@AllArgsConstructor +public class WritableBookContent { + private final List> pages; +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/WrittenBookContent.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/WrittenBookContent.java new file mode 100644 index 00000000..947d9ce1 --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/WrittenBookContent.java @@ -0,0 +1,17 @@ +package org.geysermc.mcprotocollib.protocol.data.game.item.component; + +import lombok.AllArgsConstructor; +import lombok.Data; +import net.kyori.adventure.text.Component; + +import java.util.List; + +@Data +@AllArgsConstructor +public class WrittenBookContent { + private final Filterable title; + private final String author; + private final int generation; + private final List> pages; + private final boolean resolved; +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/type/BooleanDataComponent.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/type/BooleanDataComponent.java new file mode 100644 index 00000000..80fcd10f --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/type/BooleanDataComponent.java @@ -0,0 +1,31 @@ +package org.geysermc.mcprotocollib.protocol.data.game.item.component.type; + +import org.geysermc.mcprotocollib.protocol.data.game.item.component.BooleanComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponent; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemCodecHelper; +import io.netty.buffer.ByteBuf; +import lombok.NonNull; + +public class BooleanDataComponent extends DataComponent { + private final Boolean value; + + public BooleanDataComponent(@NonNull BooleanComponentType type, Boolean value) { + super(type); + this.value = value; + } + + public boolean getPrimitiveValue() { + return this.value; + } + + @Override + @Deprecated + public Boolean getValue() { + return this.value; + } + + @Override + public void write(ItemCodecHelper helper, ByteBuf out) { + this.type.writeDataComponentPrimitive(out, this.value); + } +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/type/IntDataComponent.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/type/IntDataComponent.java new file mode 100644 index 00000000..77c011bf --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/type/IntDataComponent.java @@ -0,0 +1,32 @@ +package org.geysermc.mcprotocollib.protocol.data.game.item.component.type; + +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponent; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.IntComponentType; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.ItemCodecHelper; +import io.netty.buffer.ByteBuf; +import lombok.NonNull; + + +public class IntDataComponent extends DataComponent { + private final Integer value; + + public IntDataComponent(@NonNull IntComponentType type, Integer value) { + super(type); + this.value = value; + } + + public int getPrimitiveValue() { + return this.value; + } + + @Override + @Deprecated + public Integer getValue() { + return this.value; + } + + @Override + public void write(ItemCodecHelper helper, ByteBuf out) { + this.type.writeDataComponentPrimitive(helper, out, this.value); + } +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/type/ObjectDataComponent.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/type/ObjectDataComponent.java new file mode 100644 index 00000000..94a5b128 --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/item/component/type/ObjectDataComponent.java @@ -0,0 +1,19 @@ +package org.geysermc.mcprotocollib.protocol.data.game.item.component.type; + +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponent; +import org.geysermc.mcprotocollib.protocol.data.game.item.component.DataComponentType; +import lombok.NonNull; + +public class ObjectDataComponent extends DataComponent> { + private final T value; + + public ObjectDataComponent(@NonNull DataComponentType type, T value) { + super(type); + this.value = value; + } + + @Override + public T getValue() { + return value; + } +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/level/block/BlockEntityType.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/level/block/BlockEntityType.java index bc83b115..7a026d46 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/level/block/BlockEntityType.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/level/block/BlockEntityType.java @@ -45,7 +45,8 @@ public enum BlockEntityType { BRUSHABLE_BLOCK, DECORATED_POT, CRAFTER, - TRIAL_SPAWNER; + TRIAL_SPAWNER, + VAULT; private static final BlockEntityType[] VALUES = values(); diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/level/event/LevelEventType.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/level/event/LevelEventType.java index bc3cba8a..bcd9c1e0 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/level/event/LevelEventType.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/level/event/LevelEventType.java @@ -65,6 +65,9 @@ public enum LevelEventType implements LevelEvent { EXPLOSION(2008), EVAPORATE(2009), WHITE_SMOKE(2010), + BEE_GROWTH(2011), + TURTLE_EGG_PLACEMENT(2012), + SMASH_ATTACK(2013), END_GATEWAY_SPAWN(3000), ENTITY_ENDERDRAGON_GROWL(3001), @@ -80,7 +83,14 @@ public enum LevelEventType implements LevelEvent { TRIAL_SPAWNER_SPAWN(3011), TRIAL_SPAWNER_MOB_AT(3012), TRIAL_SPAWNER_DETECT_PLAYER(3013), - TRIAL_SPAWNER_EJECT_ITEM(3014); + TRIAL_SPAWNER_EJECT_ITEM(3014), + VAULT_ACTIVATE(3015), + VAULT_DEACTIVATE(3016), + VAULT_EJECT_ITEM(3017), + SPAWN_COBWEB(3018), + TRIAL_SPAWNER_DETECT_PLAYER_OMINOUS(3019), + TRIAL_SPAWNER_BECOME_OMINOUS(3020), + TRIAL_SPAWNER_SPAWN_ITEM(3021); private final int id; diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/level/particle/FallingDustParticleData.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/level/particle/EntityEffectParticleData.java similarity index 61% rename from protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/level/particle/FallingDustParticleData.java rename to protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/level/particle/EntityEffectParticleData.java index a5f69638..f442f75e 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/level/particle/FallingDustParticleData.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/level/particle/EntityEffectParticleData.java @@ -5,6 +5,6 @@ import lombok.Data; @Data @AllArgsConstructor -public class FallingDustParticleData implements ParticleData { - private final int blockState; +public class EntityEffectParticleData implements ParticleData { + private final int color; } diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/level/particle/ItemParticleData.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/level/particle/ItemParticleData.java index f23346c3..ec153f07 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/level/particle/ItemParticleData.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/level/particle/ItemParticleData.java @@ -1,6 +1,6 @@ package org.geysermc.mcprotocollib.protocol.data.game.level.particle; -import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import lombok.AllArgsConstructor; import lombok.Data; import org.checkerframework.checker.nullness.qual.Nullable; diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/level/particle/ParticleType.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/level/particle/ParticleType.java index cf259d26..2c1d7a14 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/level/particle/ParticleType.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/level/particle/ParticleType.java @@ -1,7 +1,6 @@ package org.geysermc.mcprotocollib.protocol.data.game.level.particle; public enum ParticleType { - AMBIENT_ENTITY_EFFECT, ANGRY_VILLAGER, BLOCK, BLOCK_MARKER, @@ -26,12 +25,15 @@ public enum ParticleType { EXPLOSION_EMITTER, EXPLOSION, GUST, - GUST_EMITTER, + SMALL_GUST, + GUST_EMITTER_LARGE, + GUST_EMITTER_SMALL, SONIC_BOOM, FALLING_DUST, FIREWORK, FISHING, FLAME, + INFESTED, CHERRY_LEAVES, SCULK_SOUL, SCULK_CHARGE, @@ -46,6 +48,7 @@ public enum ParticleType { ITEM, VIBRATION, ITEM_SLIME, + ITEM_COBWEB, ITEM_SNOWBALL, LARGE_SMOKE, LAVA, @@ -100,8 +103,13 @@ public enum ParticleType { SHRIEK, EGG_CRACK, DUST_PLUME, - GUST_DUST, - TRIAL_SPAWNER_DETECTION; + TRIAL_SPAWNER_DETECTED_PLAYER, + TRIAL_SPAWNER_DETECTED_PLAYER_OMINOUS, + VAULT_CONNECTION, + DUST_PILLAR, + OMINOUS_SPAWNING, + RAID_OMEN, + TRIAL_OMEN; private static final ParticleType[] VALUES = values(); diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/level/sound/BuiltinSound.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/level/sound/BuiltinSound.java index be36d182..013a1015 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/level/sound/BuiltinSound.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/level/sound/BuiltinSound.java @@ -61,6 +61,19 @@ public enum BuiltinSound implements Sound { BLOCK_ANVIL_PLACE("block.anvil.place"), BLOCK_ANVIL_STEP("block.anvil.step"), BLOCK_ANVIL_USE("block.anvil.use"), + ENTITY_ARMADILLO_EAT("entity.armadillo.eat"), + ENTITY_ARMADILLO_HURT("entity.armadillo.hurt"), + ENTITY_ARMADILLO_HURT_REDUCED("entity.armadillo.hurt_reduced"), + ENTITY_ARMADILLO_AMBIENT("entity.armadillo.ambient"), + ENTITY_ARMADILLO_STEP("entity.armadillo.step"), + ENTITY_ARMADILLO_DEATH("entity.armadillo.death"), + ENTITY_ARMADILLO_ROLL("entity.armadillo.roll"), + ENTITY_ARMADILLO_LAND("entity.armadillo.land"), + ENTITY_ARMADILLO_SCUTE_DROP("entity.armadillo.scute_drop"), + ENTITY_ARMADILLO_UNROLL_FINISH("entity.armadillo.unroll_finish"), + ENTITY_ARMADILLO_PEEK("entity.armadillo.peek"), + ENTITY_ARMADILLO_UNROLL_START("entity.armadillo.unroll_start"), + ENTITY_ARMADILLO_BRUSH("entity.armadillo.brush"), ITEM_ARMOR_EQUIP_CHAIN("item.armor.equip_chain"), ITEM_ARMOR_EQUIP_DIAMOND("item.armor.equip_diamond"), ITEM_ARMOR_EQUIP_ELYTRA("item.armor.equip_elytra"), @@ -70,6 +83,8 @@ public enum BuiltinSound implements Sound { ITEM_ARMOR_EQUIP_LEATHER("item.armor.equip_leather"), ITEM_ARMOR_EQUIP_NETHERITE("item.armor.equip_netherite"), ITEM_ARMOR_EQUIP_TURTLE("item.armor.equip_turtle"), + ITEM_ARMOR_EQUIP_WOLF("item.armor.equip_wolf"), + ITEM_ARMOR_UNEQUIP_WOLF("item.armor.unequip_wolf"), ENTITY_ARMOR_STAND_BREAK("entity.armor_stand.break"), ENTITY_ARMOR_STAND_FALL("entity.armor_stand.fall"), ENTITY_ARMOR_STAND_HIT("entity.armor_stand.hit"), @@ -161,6 +176,11 @@ public enum BuiltinSound implements Sound { ENTITY_BLAZE_SHOOT("entity.blaze.shoot"), ENTITY_BOAT_PADDLE_LAND("entity.boat.paddle_land"), ENTITY_BOAT_PADDLE_WATER("entity.boat.paddle_water"), + ENTITY_BOGGED_AMBIENT("entity.bogged.ambient"), + ENTITY_BOGGED_DEATH("entity.bogged.death"), + ENTITY_BOGGED_HURT("entity.bogged.hurt"), + ENTITY_BOGGED_SHEAR("entity.bogged.shear"), + ENTITY_BOGGED_STEP("entity.bogged.step"), BLOCK_BONE_BLOCK_BREAK("block.bone_block.break"), BLOCK_BONE_BLOCK_FALL("block.bone_block.fall"), BLOCK_BONE_BLOCK_HIT("block.bone_block.hit"), @@ -173,6 +193,8 @@ public enum BuiltinSound implements Sound { ITEM_BOTTLE_EMPTY("item.bottle.empty"), ITEM_BOTTLE_FILL("item.bottle.fill"), ITEM_BOTTLE_FILL_DRAGONBREATH("item.bottle.fill_dragonbreath"), + ENTITY_BREEZE_CHARGE("entity.breeze.charge"), + ENTITY_BREEZE_DEFLECT("entity.breeze.deflect"), ENTITY_BREEZE_INHALE("entity.breeze.inhale"), ENTITY_BREEZE_IDLE_GROUND("entity.breeze.idle_ground"), ENTITY_BREEZE_IDLE_AIR("entity.breeze.idle_air"), @@ -182,6 +204,8 @@ public enum BuiltinSound implements Sound { ENTITY_BREEZE_SLIDE("entity.breeze.slide"), ENTITY_BREEZE_DEATH("entity.breeze.death"), ENTITY_BREEZE_HURT("entity.breeze.hurt"), + ENTITY_BREEZE_WHIRL("entity.breeze.whirl"), + ENTITY_BREEZE_WIND_BURST("entity.breeze.wind_burst"), BLOCK_BREWING_STAND_BREW("block.brewing_stand.brew"), ITEM_BRUSH_BRUSHING_GENERIC("item.brush.brushing.generic"), ITEM_BRUSH_BRUSHING_SAND("item.brush.brushing.sand"), @@ -303,6 +327,11 @@ public enum BuiltinSound implements Sound { BLOCK_CHORUS_FLOWER_DEATH("block.chorus_flower.death"), BLOCK_CHORUS_FLOWER_GROW("block.chorus_flower.grow"), ITEM_CHORUS_FRUIT_TELEPORT("item.chorus_fruit.teleport"), + BLOCK_COBWEB_BREAK("block.cobweb.break"), + BLOCK_COBWEB_STEP("block.cobweb.step"), + BLOCK_COBWEB_PLACE("block.cobweb.place"), + BLOCK_COBWEB_HIT("block.cobweb.hit"), + BLOCK_COBWEB_FALL("block.cobweb.fall"), ENTITY_COD_AMBIENT("entity.cod.ambient"), ENTITY_COD_DEATH("entity.cod.death"), ENTITY_COD_FLOP("entity.cod.flop"), @@ -405,6 +434,7 @@ public enum BuiltinSound implements Sound { ENTITY_DONKEY_DEATH("entity.donkey.death"), ENTITY_DONKEY_EAT("entity.donkey.eat"), ENTITY_DONKEY_HURT("entity.donkey.hurt"), + ENTITY_DONKEY_JUMP("entity.donkey.jump"), BLOCK_DRIPSTONE_BLOCK_BREAK("block.dripstone_block.break"), BLOCK_DRIPSTONE_BLOCK_STEP("block.dripstone_block.step"), BLOCK_DRIPSTONE_BLOCK_PLACE("block.dripstone_block.place"), @@ -635,6 +665,11 @@ public enum BuiltinSound implements Sound { BLOCK_HANGING_SIGN_FALL("block.hanging_sign.fall"), BLOCK_HANGING_SIGN_HIT("block.hanging_sign.hit"), BLOCK_HANGING_SIGN_PLACE("block.hanging_sign.place"), + BLOCK_HEAVY_CORE_BREAK("block.heavy_core.break"), + BLOCK_HEAVY_CORE_FALL("block.heavy_core.fall"), + BLOCK_HEAVY_CORE_HIT("block.heavy_core.hit"), + BLOCK_HEAVY_CORE_PLACE("block.heavy_core.place"), + BLOCK_HEAVY_CORE_STEP("block.heavy_core.step"), BLOCK_NETHER_WOOD_HANGING_SIGN_STEP("block.nether_wood_hanging_sign.step"), BLOCK_NETHER_WOOD_HANGING_SIGN_BREAK("block.nether_wood_hanging_sign.break"), BLOCK_NETHER_WOOD_HANGING_SIGN_FALL("block.nether_wood_hanging_sign.fall"), @@ -651,8 +686,13 @@ public enum BuiltinSound implements Sound { BLOCK_TRIAL_SPAWNER_HIT("block.trial_spawner.hit"), BLOCK_TRIAL_SPAWNER_FALL("block.trial_spawner.fall"), BLOCK_TRIAL_SPAWNER_SPAWN_MOB("block.trial_spawner.spawn_mob"), + BLOCK_TRIAL_SPAWNER_ABOUT_TO_SPAWN_ITEM("block.trial_spawner.about_to_spawn_item"), + BLOCK_TRIAL_SPAWNER_SPAWN_ITEM("block.trial_spawner.spawn_item"), + BLOCK_TRIAL_SPAWNER_SPAWN_ITEM_BEGIN("block.trial_spawner.spawn_item_begin"), BLOCK_TRIAL_SPAWNER_DETECT_PLAYER("block.trial_spawner.detect_player"), + BLOCK_TRIAL_SPAWNER_CHARGE_ACTIVATE("block.trial_spawner.charge_activate"), BLOCK_TRIAL_SPAWNER_AMBIENT("block.trial_spawner.ambient"), + BLOCK_TRIAL_SPAWNER_AMBIENT_CHARGED("block.trial_spawner.ambient_charged"), BLOCK_TRIAL_SPAWNER_OPEN_SHUTTER("block.trial_spawner.open_shutter"), BLOCK_TRIAL_SPAWNER_CLOSE_SHUTTER("block.trial_spawner.close_shutter"), BLOCK_TRIAL_SPAWNER_EJECT_ITEM("block.trial_spawner.eject_item"), @@ -767,6 +807,9 @@ public enum BuiltinSound implements Sound { BLOCK_LODESTONE_HIT("block.lodestone.hit"), BLOCK_LODESTONE_FALL("block.lodestone.fall"), ITEM_LODESTONE_COMPASS_LOCK("item.lodestone_compass.lock"), + ITEM_MACE_SMASH_AIR("item.mace.smash_air"), + ITEM_MACE_SMASH_GROUND("item.mace.smash_ground"), + ITEM_MACE_SMASH_GROUND_HEAVY("item.mace.smash_ground_heavy"), ENTITY_MAGMA_CUBE_DEATH("entity.magma_cube.death"), ENTITY_MAGMA_CUBE_HURT("entity.magma_cube.hurt"), ENTITY_MAGMA_CUBE_HURT_SMALL("entity.magma_cube.hurt_small"), @@ -831,6 +874,7 @@ public enum BuiltinSound implements Sound { ENTITY_MULE_DEATH("entity.mule.death"), ENTITY_MULE_EAT("entity.mule.eat"), ENTITY_MULE_HURT("entity.mule.hurt"), + ENTITY_MULE_JUMP("entity.mule.jump"), MUSIC_CREATIVE("music.creative"), MUSIC_CREDITS("music.credits"), MUSIC_DISC_5("music_disc.5"), @@ -971,6 +1015,7 @@ public enum BuiltinSound implements Sound { ENTITY_OCELOT_HURT("entity.ocelot.hurt"), ENTITY_OCELOT_AMBIENT("entity.ocelot.ambient"), ENTITY_OCELOT_DEATH("entity.ocelot.death"), + ITEM_OMINOUS_BOTTLE_DISPOSE("item.ominous_bottle.dispose"), ENTITY_PAINTING_BREAK("entity.painting.break"), ENTITY_PAINTING_PLACE("entity.painting.place"), ENTITY_PANDA_PRE_SNEEZE("entity.panda.pre_sneeze"), @@ -990,6 +1035,7 @@ public enum BuiltinSound implements Sound { ENTITY_PARROT_FLY("entity.parrot.fly"), ENTITY_PARROT_HURT("entity.parrot.hurt"), ENTITY_PARROT_IMITATE_BLAZE("entity.parrot.imitate.blaze"), + ENTITY_PARROT_IMITATE_BOGGED("entity.parrot.imitate.bogged"), ENTITY_PARROT_IMITATE_BREEZE("entity.parrot.imitate.breeze"), ENTITY_PARROT_IMITATE_CREEPER("entity.parrot.imitate.creeper"), ENTITY_PARROT_IMITATE_DROWNED("entity.parrot.imitate.drowned"), @@ -1394,6 +1440,19 @@ public enum BuiltinSound implements Sound { UI_TOAST_CHALLENGE_COMPLETE("ui.toast.challenge_complete"), UI_TOAST_IN("ui.toast.in"), UI_TOAST_OUT("ui.toast.out"), + BLOCK_VAULT_ACTIVATE("block.vault.activate"), + BLOCK_VAULT_AMBIENT("block.vault.ambient"), + BLOCK_VAULT_BREAK("block.vault.break"), + BLOCK_VAULT_CLOSE_SHUTTER("block.vault.close_shutter"), + BLOCK_VAULT_DEACTIVATE("block.vault.deactivate"), + BLOCK_VAULT_EJECT_ITEM("block.vault.eject_item"), + BLOCK_VAULT_FALL("block.vault.fall"), + BLOCK_VAULT_HIT("block.vault.hit"), + BLOCK_VAULT_INSERT_ITEM("block.vault.insert_item"), + BLOCK_VAULT_INSERT_ITEM_FAIL("block.vault.insert_item_fail"), + BLOCK_VAULT_OPEN_SHUTTER("block.vault.open_shutter"), + BLOCK_VAULT_PLACE("block.vault.place"), + BLOCK_VAULT_STEP("block.vault.step"), ENTITY_VEX_AMBIENT("entity.vex.ambient"), ENTITY_VEX_CHARGE("entity.vex.charge"), ENTITY_VEX_DEATH("entity.vex.death"), @@ -1469,11 +1528,13 @@ public enum BuiltinSound implements Sound { BLOCK_WET_GRASS_PLACE("block.wet_grass.place"), BLOCK_WET_GRASS_STEP("block.wet_grass.step"), BLOCK_WET_SPONGE_BREAK("block.wet_sponge.break"), + BLOCK_WET_SPONGE_DRIES("block.wet_sponge.dries"), BLOCK_WET_SPONGE_FALL("block.wet_sponge.fall"), BLOCK_WET_SPONGE_HIT("block.wet_sponge.hit"), BLOCK_WET_SPONGE_PLACE("block.wet_sponge.place"), BLOCK_WET_SPONGE_STEP("block.wet_sponge.step"), - ENTITY_GENERIC_WIND_BURST("entity.generic.wind_burst"), + ENTITY_WIND_CHARGE_WIND_BURST("entity.wind_charge.wind_burst"), + ENTITY_WIND_CHARGE_THROW("entity.wind_charge.throw"), ENTITY_WITCH_AMBIENT("entity.witch.ambient"), ENTITY_WITCH_CELEBRATE("entity.witch.celebrate"), ENTITY_WITCH_DEATH("entity.witch.death"), @@ -1490,6 +1551,10 @@ public enum BuiltinSound implements Sound { ENTITY_WITHER_SKELETON_HURT("entity.wither_skeleton.hurt"), ENTITY_WITHER_SKELETON_STEP("entity.wither_skeleton.step"), ENTITY_WITHER_SPAWN("entity.wither.spawn"), + ITEM_WOLF_ARMOR_BREAK("item.wolf_armor.break"), + ITEM_WOLF_ARMOR_CRACK("item.wolf_armor.crack"), + ITEM_WOLF_ARMOR_DAMAGE("item.wolf_armor.damage"), + ITEM_WOLF_ARMOR_REPAIR("item.wolf_armor.repair"), ENTITY_WOLF_AMBIENT("entity.wolf.ambient"), ENTITY_WOLF_DEATH("entity.wolf.death"), ENTITY_WOLF_GROWL("entity.wolf.growl"), @@ -1545,7 +1610,10 @@ public enum BuiltinSound implements Sound { ENTITY_ZOMBIE_VILLAGER_CURE("entity.zombie_villager.cure"), ENTITY_ZOMBIE_VILLAGER_DEATH("entity.zombie_villager.death"), ENTITY_ZOMBIE_VILLAGER_HURT("entity.zombie_villager.hurt"), - ENTITY_ZOMBIE_VILLAGER_STEP("entity.zombie_villager.step"); + ENTITY_ZOMBIE_VILLAGER_STEP("entity.zombie_villager.step"), + EVENT_MOB_EFFECT_BAD_OMEN("event.mob_effect.bad_omen"), + EVENT_MOB_EFFECT_TRIAL_OMEN("event.mob_effect.trial_omen"), + EVENT_MOB_EFFECT_RAID_OMEN("event.mob_effect.raid_omen"); private final @NonNull String name; diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/recipe/Ingredient.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/recipe/Ingredient.java index 6d676b35..dd53dfe5 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/recipe/Ingredient.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/recipe/Ingredient.java @@ -1,6 +1,6 @@ package org.geysermc.mcprotocollib.protocol.data.game.recipe; -import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NonNull; diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/recipe/RecipeType.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/recipe/RecipeType.java index e0ffb76f..b35d977a 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/recipe/RecipeType.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/recipe/RecipeType.java @@ -1,11 +1,5 @@ package org.geysermc.mcprotocollib.protocol.data.game.recipe; -import org.geysermc.mcprotocollib.protocol.data.game.Identifier; - -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; - public enum RecipeType { CRAFTING_SHAPED, CRAFTING_SHAPELESS, @@ -31,25 +25,9 @@ public enum RecipeType { SMITHING_TRIM, CRAFTING_DECORATED_POT; - private final String resourceLocation; + private static final RecipeType[] VALUES = values(); - RecipeType() { - this.resourceLocation = Identifier.formalize(name().toLowerCase(Locale.ROOT)); - } - - public String getResourceLocation() { - return resourceLocation; - } - - private static final Map VALUES = new HashMap<>(); - - public static RecipeType from(String resourceLocation) { - return VALUES.get(resourceLocation); - } - - static { - for (RecipeType type : values()) { - VALUES.put(type.resourceLocation, type); - } + public static RecipeType from(int id) { + return VALUES[id]; } } diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/recipe/data/CookedRecipeData.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/recipe/data/CookedRecipeData.java index 53ece5c8..823c52fe 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/recipe/data/CookedRecipeData.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/recipe/data/CookedRecipeData.java @@ -1,6 +1,6 @@ package org.geysermc.mcprotocollib.protocol.data.game.recipe.data; -import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import org.geysermc.mcprotocollib.protocol.data.game.recipe.CraftingBookCategory; import org.geysermc.mcprotocollib.protocol.data.game.recipe.Ingredient; import lombok.AllArgsConstructor; diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/recipe/data/ShapedRecipeData.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/recipe/data/ShapedRecipeData.java index 7708a425..522d3a10 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/recipe/data/ShapedRecipeData.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/recipe/data/ShapedRecipeData.java @@ -1,6 +1,6 @@ package org.geysermc.mcprotocollib.protocol.data.game.recipe.data; -import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import org.geysermc.mcprotocollib.protocol.data.game.recipe.CraftingBookCategory; import org.geysermc.mcprotocollib.protocol.data.game.recipe.Ingredient; import lombok.AllArgsConstructor; diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/recipe/data/ShapelessRecipeData.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/recipe/data/ShapelessRecipeData.java index bf590ebe..ea5da286 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/recipe/data/ShapelessRecipeData.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/recipe/data/ShapelessRecipeData.java @@ -1,6 +1,6 @@ package org.geysermc.mcprotocollib.protocol.data.game.recipe.data; -import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import org.geysermc.mcprotocollib.protocol.data.game.recipe.CraftingBookCategory; import org.geysermc.mcprotocollib.protocol.data.game.recipe.Ingredient; import lombok.AllArgsConstructor; diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/recipe/data/SmithingTransformRecipeData.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/recipe/data/SmithingTransformRecipeData.java index dd4b99ca..99298bb6 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/recipe/data/SmithingTransformRecipeData.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/recipe/data/SmithingTransformRecipeData.java @@ -1,6 +1,6 @@ package org.geysermc.mcprotocollib.protocol.data.game.recipe.data; -import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import org.geysermc.mcprotocollib.protocol.data.game.recipe.Ingredient; import lombok.AllArgsConstructor; import lombok.Data; diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/recipe/data/StoneCuttingRecipeData.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/recipe/data/StoneCuttingRecipeData.java index ad0897cc..6e5075a8 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/recipe/data/StoneCuttingRecipeData.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/game/recipe/data/StoneCuttingRecipeData.java @@ -1,6 +1,6 @@ package org.geysermc.mcprotocollib.protocol.data.game.recipe.data; -import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import org.geysermc.mcprotocollib.protocol.data.game.recipe.Ingredient; import lombok.AllArgsConstructor; import lombok.Data; diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/handshake/HandshakeIntent.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/handshake/HandshakeIntent.java index 660ec9db..1717372f 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/handshake/HandshakeIntent.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/data/handshake/HandshakeIntent.java @@ -2,7 +2,8 @@ package org.geysermc.mcprotocollib.protocol.data.handshake; public enum HandshakeIntent { STATUS, - LOGIN; + LOGIN, + TRANSFER; private static final HandshakeIntent[] VALUES = values(); diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/common/clientbound/ClientboundCookieRequestPacket.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/common/clientbound/ClientboundCookieRequestPacket.java new file mode 100644 index 00000000..f11e1c99 --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/common/clientbound/ClientboundCookieRequestPacket.java @@ -0,0 +1,24 @@ +package org.geysermc.mcprotocollib.protocol.packet.common.clientbound; + +import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper; +import org.geysermc.mcprotocollib.protocol.codec.MinecraftPacket; +import io.netty.buffer.ByteBuf; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.With; + +@Data +@With +@AllArgsConstructor +public class ClientboundCookieRequestPacket implements MinecraftPacket { + private final String key; + + public ClientboundCookieRequestPacket(ByteBuf in, MinecraftCodecHelper helper) { + this.key = helper.readResourceLocation(in); + } + + @Override + public void serialize(ByteBuf out, MinecraftCodecHelper helper) { + helper.writeResourceLocation(out, this.key); + } +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/common/clientbound/ClientboundStoreCookiePacket.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/common/clientbound/ClientboundStoreCookiePacket.java new file mode 100644 index 00000000..5de8a9f1 --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/common/clientbound/ClientboundStoreCookiePacket.java @@ -0,0 +1,27 @@ +package org.geysermc.mcprotocollib.protocol.packet.common.clientbound; + +import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper; +import org.geysermc.mcprotocollib.protocol.codec.MinecraftPacket; +import io.netty.buffer.ByteBuf; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.With; + +@Data +@With +@AllArgsConstructor +public class ClientboundStoreCookiePacket implements MinecraftPacket { + private final String key; + private final byte[] payload; + + public ClientboundStoreCookiePacket(ByteBuf in, MinecraftCodecHelper helper) { + this.key = helper.readResourceLocation(in); + this.payload = helper.readByteArray(in); + } + + @Override + public void serialize(ByteBuf out, MinecraftCodecHelper helper) { + helper.writeResourceLocation(out, this.key); + helper.writeByteArray(out, this.payload); + } +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/common/clientbound/ClientboundTransferPacket.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/common/clientbound/ClientboundTransferPacket.java new file mode 100644 index 00000000..a9430f19 --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/common/clientbound/ClientboundTransferPacket.java @@ -0,0 +1,27 @@ +package org.geysermc.mcprotocollib.protocol.packet.common.clientbound; + +import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper; +import org.geysermc.mcprotocollib.protocol.codec.MinecraftPacket; +import io.netty.buffer.ByteBuf; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.With; + +@Data +@With +@AllArgsConstructor +public class ClientboundTransferPacket implements MinecraftPacket { + private final String host; + private final int port; + + public ClientboundTransferPacket(ByteBuf in, MinecraftCodecHelper helper) { + this.host = helper.readString(in); + this.port = helper.readVarInt(in); + } + + @Override + public void serialize(ByteBuf out, MinecraftCodecHelper helper) { + helper.writeString(out, this.host); + helper.writeVarInt(out, this.port); + } +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/common/clientbound/ServerboundCookieResponsePacket.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/common/clientbound/ServerboundCookieResponsePacket.java new file mode 100644 index 00000000..8fbdb1a8 --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/common/clientbound/ServerboundCookieResponsePacket.java @@ -0,0 +1,28 @@ +package org.geysermc.mcprotocollib.protocol.packet.common.clientbound; + +import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper; +import org.geysermc.mcprotocollib.protocol.codec.MinecraftPacket; +import io.netty.buffer.ByteBuf; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.With; +import org.jetbrains.annotations.Nullable; + +@Data +@With +@AllArgsConstructor +public class ServerboundCookieResponsePacket implements MinecraftPacket { + private final String key; + private final byte @Nullable[] payload; + + public ServerboundCookieResponsePacket(ByteBuf in, MinecraftCodecHelper helper) { + this.key = helper.readResourceLocation(in); + this.payload = helper.readNullable(in, helper::readByteArray); + } + + @Override + public void serialize(ByteBuf out, MinecraftCodecHelper helper) { + helper.writeResourceLocation(out, this.key); + helper.writeNullable(out, this.payload, helper::writeByteArray); + } +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/configuration/clientbound/ClientboundRegistryDataPacket.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/configuration/clientbound/ClientboundRegistryDataPacket.java index 507d8fd4..95c4fadc 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/configuration/clientbound/ClientboundRegistryDataPacket.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/configuration/clientbound/ClientboundRegistryDataPacket.java @@ -2,24 +2,40 @@ package org.geysermc.mcprotocollib.protocol.packet.configuration.clientbound; import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper; import org.geysermc.mcprotocollib.protocol.codec.MinecraftPacket; -import com.github.steveice10.opennbt.tag.builtin.CompoundTag; +import org.geysermc.mcprotocollib.protocol.data.game.RegistryEntry; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; import lombok.Data; import lombok.With; +import java.util.ArrayList; +import java.util.List; + @Data @With @AllArgsConstructor public class ClientboundRegistryDataPacket implements MinecraftPacket { - private final CompoundTag registry; + private final String registry; + private final List entries; public ClientboundRegistryDataPacket(ByteBuf in, MinecraftCodecHelper helper) { - this.registry = helper.readAnyTag(in); + this.registry = helper.readResourceLocation(in); + this.entries = new ArrayList<>(); + + int entryCount = helper.readVarInt(in); + for (int i = 0; i < entryCount; i++) { + this.entries.add(new RegistryEntry(helper.readResourceLocation(in), helper.readNullable(in, helper::readAnyTag))); + } } @Override public void serialize(ByteBuf out, MinecraftCodecHelper helper) { - helper.writeAnyTag(out, this.registry); + helper.writeResourceLocation(out, this.registry); + + helper.writeVarInt(out, this.entries.size()); + for (RegistryEntry entry : this.entries) { + helper.writeResourceLocation(out, entry.getId()); + helper.writeNullable(out, entry.getData(), helper::writeAnyTag); + } } } diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/configuration/clientbound/ClientboundResetChatPacket.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/configuration/clientbound/ClientboundResetChatPacket.java new file mode 100644 index 00000000..b78b2a31 --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/configuration/clientbound/ClientboundResetChatPacket.java @@ -0,0 +1,18 @@ +package org.geysermc.mcprotocollib.protocol.packet.configuration.clientbound; + +import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper; +import org.geysermc.mcprotocollib.protocol.codec.MinecraftPacket; +import io.netty.buffer.ByteBuf; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +public class ClientboundResetChatPacket implements MinecraftPacket { + public ClientboundResetChatPacket(ByteBuf in, MinecraftCodecHelper helper) { + } + + @Override + public void serialize(ByteBuf out, MinecraftCodecHelper helper) { + } +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/configuration/clientbound/ClientboundSelectKnownPacks.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/configuration/clientbound/ClientboundSelectKnownPacks.java new file mode 100644 index 00000000..313e2e62 --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/configuration/clientbound/ClientboundSelectKnownPacks.java @@ -0,0 +1,37 @@ +package org.geysermc.mcprotocollib.protocol.packet.configuration.clientbound; + +import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper; +import org.geysermc.mcprotocollib.protocol.codec.MinecraftPacket; +import org.geysermc.mcprotocollib.protocol.data.game.KnownPack; +import io.netty.buffer.ByteBuf; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.With; + +import java.util.ArrayList; +import java.util.List; + +@Data +@With +@AllArgsConstructor +public class ClientboundSelectKnownPacks implements MinecraftPacket { + private final List knownPacks; + + public ClientboundSelectKnownPacks(ByteBuf in, MinecraftCodecHelper helper) { + this.knownPacks = new ArrayList<>(); + int entryCount = helper.readVarInt(in); + for (int i = 0; i < entryCount; i++) { + this.knownPacks.add(new KnownPack(helper.readString(in), helper.readString(in), helper.readString(in))); + } + } + + @Override + public void serialize(ByteBuf out, MinecraftCodecHelper helper) { + helper.writeVarInt(out, this.knownPacks.size()); + for (KnownPack entry : this.knownPacks) { + helper.writeString(out, entry.getNamespace()); + helper.writeString(out, entry.getId()); + helper.writeString(out, entry.getVersion()); + } + } +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/configuration/serverbound/ServerboundSelectKnownPacks.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/configuration/serverbound/ServerboundSelectKnownPacks.java new file mode 100644 index 00000000..ad963b60 --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/configuration/serverbound/ServerboundSelectKnownPacks.java @@ -0,0 +1,42 @@ +package org.geysermc.mcprotocollib.protocol.packet.configuration.serverbound; + +import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper; +import org.geysermc.mcprotocollib.protocol.codec.MinecraftPacket; +import org.geysermc.mcprotocollib.protocol.data.game.KnownPack; +import io.netty.buffer.ByteBuf; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.With; + +import java.util.ArrayList; +import java.util.List; + +@Data +@With +@AllArgsConstructor +public class ServerboundSelectKnownPacks implements MinecraftPacket { + private final List knownPacks; + + public ServerboundSelectKnownPacks(ByteBuf in, MinecraftCodecHelper helper) { + this.knownPacks = new ArrayList<>(); + + int entryCount = Math.min(helper.readVarInt(in), 64); + for (int i = 0; i < entryCount; i++) { + this.knownPacks.add(new KnownPack(helper.readString(in), helper.readString(in), helper.readString(in))); + } + } + + @Override + public void serialize(ByteBuf out, MinecraftCodecHelper helper) { + if (this.knownPacks.size() > 64) { + throw new IllegalArgumentException("KnownPacks is longer than maximum allowed length"); + } + + helper.writeVarInt(out, this.knownPacks.size()); + for (KnownPack entry : this.knownPacks) { + helper.writeString(out, entry.getNamespace()); + helper.writeString(out, entry.getId()); + helper.writeString(out, entry.getVersion()); + } + } +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/ClientboundDebugSamplePacket.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/ClientboundDebugSamplePacket.java new file mode 100644 index 00000000..675d33fe --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/ClientboundDebugSamplePacket.java @@ -0,0 +1,28 @@ +package org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound; + +import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper; +import org.geysermc.mcprotocollib.protocol.codec.MinecraftPacket; +import org.geysermc.mcprotocollib.protocol.data.game.RemoteDebugSampleType; +import io.netty.buffer.ByteBuf; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.With; + +@Data +@With +@AllArgsConstructor +public class ClientboundDebugSamplePacket implements MinecraftPacket { + private final long[] sample; + private final RemoteDebugSampleType debugSampleType; + + public ClientboundDebugSamplePacket(ByteBuf in, MinecraftCodecHelper helper) { + this.sample = helper.readLongArray(in); + this.debugSampleType = RemoteDebugSampleType.from(helper.readVarInt(in)); + } + + @Override + public void serialize(ByteBuf out, MinecraftCodecHelper helper) { + helper.writeLongArray(out, this.sample); + helper.writeVarInt(out, this.debugSampleType.ordinal()); + } +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/ClientboundLoginPacket.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/ClientboundLoginPacket.java index a4cb2815..54a13f99 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/ClientboundLoginPacket.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/ClientboundLoginPacket.java @@ -23,6 +23,7 @@ public class ClientboundLoginPacket implements MinecraftPacket { private final boolean enableRespawnScreen; private final boolean doLimitedCrafting; private final PlayerSpawnInfo commonPlayerSpawnInfo; + private final boolean enforcesSecureChat; public ClientboundLoginPacket(ByteBuf in, MinecraftCodecHelper helper) { this.entityId = in.readInt(); @@ -39,6 +40,7 @@ public class ClientboundLoginPacket implements MinecraftPacket { this.enableRespawnScreen = in.readBoolean(); this.doLimitedCrafting = in.readBoolean(); this.commonPlayerSpawnInfo = helper.readPlayerSpawnInfo(in); + this.enforcesSecureChat = in.readBoolean(); } @Override @@ -56,5 +58,6 @@ public class ClientboundLoginPacket implements MinecraftPacket { out.writeBoolean(this.enableRespawnScreen); out.writeBoolean(this.doLimitedCrafting); helper.writePlayerSpawnInfo(out, this.commonPlayerSpawnInfo); + out.writeBoolean(this.enforcesSecureChat); } } diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/ClientboundPlayerInfoUpdatePacket.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/ClientboundPlayerInfoUpdatePacket.java index 333c7a6e..4590b636 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/ClientboundPlayerInfoUpdatePacket.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/ClientboundPlayerInfoUpdatePacket.java @@ -94,13 +94,18 @@ public class ClientboundPlayerInfoUpdatePacket implements MinecraftPacket { helper.writeEnumSet(out, this.actions, PlayerListEntryAction.VALUES); helper.writeVarInt(out, this.entries.length); for (PlayerListEntry entry : this.entries) { - helper.writeUUID(out, entry.getProfile().getId()); + helper.writeUUID(out, entry.getProfileId()); for (PlayerListEntryAction action : this.actions) { switch (action) { case ADD_PLAYER -> { - helper.writeString(out, entry.getProfile().getName()); - helper.writeVarInt(out, entry.getProfile().getProperties().size()); - for (GameProfile.Property property : entry.getProfile().getProperties()) { + GameProfile profile = entry.getProfile(); + if (profile == null) { + throw new IllegalArgumentException("Cannot ADD " + entry.getProfileId() + " without a profile."); + } + + helper.writeString(out, profile.getName()); + helper.writeVarInt(out, profile.getProperties().size()); + for (GameProfile.Property property : profile.getProperties()) { helper.writeProperty(out, property); } } diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/ClientboundServerDataPacket.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/ClientboundServerDataPacket.java index 5bdef0a5..e1aaafb0 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/ClientboundServerDataPacket.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/ClientboundServerDataPacket.java @@ -15,18 +15,15 @@ import org.checkerframework.checker.nullness.qual.Nullable; public class ClientboundServerDataPacket implements MinecraftPacket { private final Component motd; private final byte @Nullable[] iconBytes; - private final boolean enforcesSecureChat; public ClientboundServerDataPacket(ByteBuf in, MinecraftCodecHelper helper) { this.motd = helper.readComponent(in); this.iconBytes = helper.readNullable(in, helper::readByteArray); - this.enforcesSecureChat = in.readBoolean(); } @Override public void serialize(ByteBuf out, MinecraftCodecHelper helper) { helper.writeComponent(out, this.motd); helper.writeNullable(out, this.iconBytes, helper::writeByteArray); - out.writeBoolean(this.enforcesSecureChat); } } diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/ClientboundUpdateAdvancementsPacket.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/ClientboundUpdateAdvancementsPacket.java index 2eb06736..44fdcafe 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/ClientboundUpdateAdvancementsPacket.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/ClientboundUpdateAdvancementsPacket.java @@ -5,7 +5,7 @@ import org.geysermc.mcprotocollib.protocol.codec.MinecraftPacket; import org.geysermc.mcprotocollib.protocol.data.game.advancement.Advancement; import org.geysermc.mcprotocollib.protocol.data.game.advancement.Advancement.DisplayData; import org.geysermc.mcprotocollib.protocol.data.game.advancement.Advancement.DisplayData.AdvancementType; -import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; import lombok.Data; @@ -55,7 +55,7 @@ public class ClientboundUpdateAdvancementsPacket implements MinecraftPacket { if (in.readBoolean()) { Component title = helper.readComponent(in); Component description = helper.readComponent(in); - ItemStack icon = helper.readItemStack(in); + ItemStack icon = helper.readOptionalItemStack(in); AdvancementType advancementType = AdvancementType.from(helper.readVarInt(in)); int flags = in.readInt(); @@ -128,7 +128,7 @@ public class ClientboundUpdateAdvancementsPacket implements MinecraftPacket { out.writeBoolean(true); helper.writeComponent(out, displayData.getTitle()); helper.writeComponent(out, displayData.getDescription()); - helper.writeItemStack(out, displayData.getIcon()); + helper.writeOptionalItemStack(out, displayData.getIcon()); helper.writeVarInt(out, displayData.getAdvancementType().ordinal()); String backgroundTexture = displayData.getBackgroundTexture(); diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/ClientboundUpdateRecipesPacket.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/ClientboundUpdateRecipesPacket.java index 62b6fe84..253e1be1 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/ClientboundUpdateRecipesPacket.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/ClientboundUpdateRecipesPacket.java @@ -2,7 +2,7 @@ package org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound; import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper; import org.geysermc.mcprotocollib.protocol.codec.MinecraftPacket; -import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import org.geysermc.mcprotocollib.protocol.data.game.recipe.CraftingBookCategory; import org.geysermc.mcprotocollib.protocol.data.game.recipe.Ingredient; import org.geysermc.mcprotocollib.protocol.data.game.recipe.Recipe; @@ -23,8 +23,8 @@ public class ClientboundUpdateRecipesPacket implements MinecraftPacket { public ClientboundUpdateRecipesPacket(ByteBuf in, MinecraftCodecHelper helper) { this.recipes = new Recipe[helper.readVarInt(in)]; for (int i = 0; i < this.recipes.length; i++) { - RecipeType type = RecipeType.from(helper.readResourceLocation(in)); String identifier = helper.readResourceLocation(in); + RecipeType type = RecipeType.from(helper.readVarInt(in)); RecipeData data; switch (type) { case CRAFTING_SHAPELESS -> { @@ -35,7 +35,7 @@ public class ClientboundUpdateRecipesPacket implements MinecraftPacket { ingredients[j] = helper.readRecipeIngredient(in); } - ItemStack result = helper.readItemStack(in); + ItemStack result = helper.readOptionalItemStack(in); data = new ShapelessRecipeData(group, category, ingredients, result); } @@ -51,7 +51,7 @@ public class ClientboundUpdateRecipesPacket implements MinecraftPacket { ingredients[j] = helper.readRecipeIngredient(in); } - ItemStack result = helper.readItemStack(in); + ItemStack result = helper.readOptionalItemStack(in); boolean showNotification = in.readBoolean(); data = new ShapedRecipeData(width, height, group, category, ingredients, result, showNotification); @@ -60,7 +60,7 @@ public class ClientboundUpdateRecipesPacket implements MinecraftPacket { String group = helper.readString(in); CraftingBookCategory category = CraftingBookCategory.from(helper.readVarInt(in)); Ingredient ingredient = helper.readRecipeIngredient(in); - ItemStack result = helper.readItemStack(in); + ItemStack result = helper.readOptionalItemStack(in); float experience = in.readFloat(); int cookingTime = helper.readVarInt(in); @@ -69,7 +69,7 @@ public class ClientboundUpdateRecipesPacket implements MinecraftPacket { case STONECUTTING -> { String group = helper.readString(in); Ingredient ingredient = helper.readRecipeIngredient(in); - ItemStack result = helper.readItemStack(in); + ItemStack result = helper.readOptionalItemStack(in); data = new StoneCuttingRecipeData(group, ingredient, result); } @@ -77,7 +77,7 @@ public class ClientboundUpdateRecipesPacket implements MinecraftPacket { Ingredient template = helper.readRecipeIngredient(in); Ingredient base = helper.readRecipeIngredient(in); Ingredient addition = helper.readRecipeIngredient(in); - ItemStack result = helper.readItemStack(in); + ItemStack result = helper.readOptionalItemStack(in); data = new SmithingTransformRecipeData(template, base, addition, result); } @@ -103,8 +103,8 @@ public class ClientboundUpdateRecipesPacket implements MinecraftPacket { public void serialize(ByteBuf out, MinecraftCodecHelper helper) { helper.writeVarInt(out, this.recipes.length); for (Recipe recipe : this.recipes) { - helper.writeResourceLocation(out, recipe.getType().getResourceLocation()); helper.writeResourceLocation(out, recipe.getIdentifier()); + helper.writeVarInt(out, recipe.getType().ordinal()); switch (recipe.getType()) { case CRAFTING_SHAPELESS -> { ShapelessRecipeData data = (ShapelessRecipeData) recipe.getData(); @@ -116,7 +116,7 @@ public class ClientboundUpdateRecipesPacket implements MinecraftPacket { helper.writeRecipeIngredient(out, ingredient); } - helper.writeItemStack(out, data.getResult()); + helper.writeOptionalItemStack(out, data.getResult()); } case CRAFTING_SHAPED -> { ShapedRecipeData data = (ShapedRecipeData) recipe.getData(); @@ -134,7 +134,7 @@ public class ClientboundUpdateRecipesPacket implements MinecraftPacket { helper.writeRecipeIngredient(out, ingredient); } - helper.writeItemStack(out, data.getResult()); + helper.writeOptionalItemStack(out, data.getResult()); out.writeBoolean(data.isShowNotification()); } case SMELTING, BLASTING, SMOKING, CAMPFIRE_COOKING -> { @@ -143,7 +143,7 @@ public class ClientboundUpdateRecipesPacket implements MinecraftPacket { helper.writeString(out, data.getGroup()); helper.writeVarInt(out, data.getCategory().ordinal()); helper.writeRecipeIngredient(out, data.getIngredient()); - helper.writeItemStack(out, data.getResult()); + helper.writeOptionalItemStack(out, data.getResult()); out.writeFloat(data.getExperience()); helper.writeVarInt(out, data.getCookingTime()); } @@ -152,7 +152,7 @@ public class ClientboundUpdateRecipesPacket implements MinecraftPacket { helper.writeString(out, data.getGroup()); helper.writeRecipeIngredient(out, data.getIngredient()); - helper.writeItemStack(out, data.getResult()); + helper.writeOptionalItemStack(out, data.getResult()); } case SMITHING_TRANSFORM -> { SmithingTransformRecipeData data = (SmithingTransformRecipeData) recipe.getData(); @@ -160,7 +160,7 @@ public class ClientboundUpdateRecipesPacket implements MinecraftPacket { helper.writeRecipeIngredient(out, data.getTemplate()); helper.writeRecipeIngredient(out, data.getBase()); helper.writeRecipeIngredient(out, data.getAddition()); - helper.writeItemStack(out, data.getResult()); + helper.writeOptionalItemStack(out, data.getResult()); } case SMITHING_TRIM -> { SmithingTrimRecipeData data = (SmithingTrimRecipeData) recipe.getData(); diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/entity/ClientboundProjectilePowerPacket.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/entity/ClientboundProjectilePowerPacket.java new file mode 100644 index 00000000..61be6839 --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/entity/ClientboundProjectilePowerPacket.java @@ -0,0 +1,33 @@ +package org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity; + +import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper; +import org.geysermc.mcprotocollib.protocol.codec.MinecraftPacket; +import io.netty.buffer.ByteBuf; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.With; + +@Data +@With +@AllArgsConstructor +public class ClientboundProjectilePowerPacket implements MinecraftPacket { + private final int id; + private final double xPower; + private final double yPower; + private final double zPower; + + public ClientboundProjectilePowerPacket(ByteBuf in, MinecraftCodecHelper helper) { + this.id = helper.readVarInt(in); + this.xPower = in.readDouble(); + this.yPower = in.readDouble(); + this.zPower = in.readDouble(); + } + + @Override + public void serialize(ByteBuf out, MinecraftCodecHelper helper) { + helper.writeVarInt(out, this.id); + out.writeDouble(this.xPower); + out.writeDouble(this.yPower); + out.writeDouble(this.zPower); + } +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/entity/ClientboundSetEquipmentPacket.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/entity/ClientboundSetEquipmentPacket.java index f0eb34c5..7457a0ce 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/entity/ClientboundSetEquipmentPacket.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/entity/ClientboundSetEquipmentPacket.java @@ -4,7 +4,7 @@ import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper; import org.geysermc.mcprotocollib.protocol.codec.MinecraftPacket; import org.geysermc.mcprotocollib.protocol.data.game.entity.EquipmentSlot; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Equipment; -import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; import lombok.Data; @@ -28,7 +28,7 @@ public class ClientboundSetEquipmentPacket implements MinecraftPacket { while (hasNextEntry) { int rawSlot = in.readByte(); EquipmentSlot slot = EquipmentSlot.from(((byte) rawSlot) & 127); - ItemStack item = helper.readItemStack(in); + ItemStack item = helper.readOptionalItemStack(in); list.add(new Equipment(slot, item)); hasNextEntry = (rawSlot & 128) == 128; } @@ -44,7 +44,7 @@ public class ClientboundSetEquipmentPacket implements MinecraftPacket { rawSlot = rawSlot | 128; } out.writeByte(rawSlot); - helper.writeItemStack(out, this.equipment[i].getItem()); + helper.writeOptionalItemStack(out, this.equipment[i].getItem()); } } } diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/entity/ClientboundUpdateAttributesPacket.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/entity/ClientboundUpdateAttributesPacket.java index c544fee9..5a2bcf81 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/entity/ClientboundUpdateAttributesPacket.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/entity/ClientboundUpdateAttributesPacket.java @@ -27,7 +27,7 @@ public class ClientboundUpdateAttributesPacket implements MinecraftPacket { this.attributes = new ArrayList<>(); int length = helper.readVarInt(in); for (int index = 0; index < length; index++) { - String key = helper.readString(in); + int attributeId = helper.readVarInt(in); double value = in.readDouble(); List modifiers = new ArrayList<>(); int len = helper.readVarInt(in); @@ -35,7 +35,7 @@ public class ClientboundUpdateAttributesPacket implements MinecraftPacket { modifiers.add(new AttributeModifier(helper.readUUID(in), in.readDouble(), helper.readModifierOperation(in))); } - AttributeType type = AttributeType.Builtin.BUILTIN.computeIfAbsent(Identifier.formalize(key), AttributeType.Custom::new); + AttributeType type = AttributeType.Builtin.BUILTIN.get(attributeId); //.computeIfAbsent(attributeId, AttributeType.Custom::new); TODO this.attributes.add(new Attribute(type, value, modifiers)); } } @@ -45,7 +45,7 @@ public class ClientboundUpdateAttributesPacket implements MinecraftPacket { helper.writeVarInt(out, this.entityId); helper.writeVarInt(out, this.attributes.size()); for (Attribute attribute : this.attributes) { - helper.writeString(out, attribute.getType().getIdentifier()); + helper.writeVarInt(out, attribute.getType().getId()); out.writeDouble(attribute.getValue()); helper.writeVarInt(out, attribute.getModifiers().size()); for (AttributeModifier modifier : attribute.getModifiers()) { diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/entity/ClientboundUpdateMobEffectPacket.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/entity/ClientboundUpdateMobEffectPacket.java index e232d6c4..3209bb7c 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/entity/ClientboundUpdateMobEffectPacket.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/entity/ClientboundUpdateMobEffectPacket.java @@ -18,6 +18,7 @@ public class ClientboundUpdateMobEffectPacket implements MinecraftPacket { private static final int FLAG_AMBIENT = 0x01; private static final int FLAG_SHOW_PARTICLES = 0x02; private static final int FLAG_SHOW_ICON = 0x04; + private static final int FLAG_BLEND = 0x08; private final int entityId; private final @NonNull Effect effect; @@ -26,26 +27,26 @@ public class ClientboundUpdateMobEffectPacket implements MinecraftPacket { private final boolean ambient; private final boolean showParticles; private final boolean showIcon; - private final @Nullable CompoundTag factorData; + private final boolean blend; public ClientboundUpdateMobEffectPacket(ByteBuf in, MinecraftCodecHelper helper) { this.entityId = helper.readVarInt(in); this.effect = helper.readEffect(in); - this.amplifier = in.readByte(); + this.amplifier = helper.readVarInt(in); this.duration = helper.readVarInt(in); int flags = in.readByte(); this.ambient = (flags & FLAG_AMBIENT) != 0; this.showParticles = (flags & FLAG_SHOW_PARTICLES) != 0; this.showIcon = (flags & FLAG_SHOW_ICON) != 0; - this.factorData = helper.readNullable(in, helper::readAnyTagOrThrow); + this.blend = (flags & FLAG_BLEND) != 0; } @Override public void serialize(ByteBuf out, MinecraftCodecHelper helper) { helper.writeVarInt(out, this.entityId); helper.writeEffect(out, this.effect); - out.writeByte(this.amplifier); + helper.writeVarInt(out, this.amplifier); helper.writeVarInt(out, this.duration); int flags = 0; @@ -58,8 +59,10 @@ public class ClientboundUpdateMobEffectPacket implements MinecraftPacket { if (this.showIcon) { flags |= FLAG_SHOW_ICON; } + if (this.blend) { + flags |= FLAG_BLEND; + } out.writeByte(flags); - helper.writeNullable(out, this.factorData, helper::writeAnyTag); } } diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/entity/spawn/ClientboundAddEntityPacket.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/entity/spawn/ClientboundAddEntityPacket.java index 92f39180..5a2ff2f1 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/entity/spawn/ClientboundAddEntityPacket.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/entity/spawn/ClientboundAddEntityPacket.java @@ -69,7 +69,8 @@ public class ClientboundAddEntityPacket implements MinecraftPacket { } else if (this.type == EntityType.POTION) { this.data = new SplashPotionData(data); } else if (this.type == EntityType.SPECTRAL_ARROW || this.type == EntityType.FIREBALL || this.type == EntityType.SMALL_FIREBALL - || this.type == EntityType.DRAGON_FIREBALL || this.type == EntityType.WITHER_SKULL || this.type == EntityType.FISHING_BOBBER) { + || this.type == EntityType.DRAGON_FIREBALL || this.type == EntityType.WITHER_SKULL || this.type == EntityType.FISHING_BOBBER + || this.type == EntityType.BREEZE_WIND_CHARGE) { this.data = new ProjectileData(data); } else if (this.type == EntityType.WARDEN) { this.data = new WardenData(data); diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/inventory/ClientboundContainerSetContentPacket.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/inventory/ClientboundContainerSetContentPacket.java index 7ea27153..337999e7 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/inventory/ClientboundContainerSetContentPacket.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/inventory/ClientboundContainerSetContentPacket.java @@ -2,7 +2,7 @@ package org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.inventory; import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper; import org.geysermc.mcprotocollib.protocol.codec.MinecraftPacket; -import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; import lombok.Data; @@ -24,9 +24,9 @@ public class ClientboundContainerSetContentPacket implements MinecraftPacket { this.stateId = helper.readVarInt(in); this.items = new ItemStack[helper.readVarInt(in)]; for (int index = 0; index < this.items.length; index++) { - this.items[index] = helper.readItemStack(in); + this.items[index] = helper.readOptionalItemStack(in); } - this.carriedItem = helper.readItemStack(in); + this.carriedItem = helper.readOptionalItemStack(in); } @Override @@ -35,8 +35,8 @@ public class ClientboundContainerSetContentPacket implements MinecraftPacket { helper.writeVarInt(out, this.stateId); helper.writeVarInt(out, this.items.length); for (ItemStack item : this.items) { - helper.writeItemStack(out, item); + helper.writeOptionalItemStack(out, item); } - helper.writeItemStack(out, this.carriedItem); + helper.writeOptionalItemStack(out, this.carriedItem); } } diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/inventory/ClientboundContainerSetSlotPacket.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/inventory/ClientboundContainerSetSlotPacket.java index 6ac8b3ed..00e3a452 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/inventory/ClientboundContainerSetSlotPacket.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/inventory/ClientboundContainerSetSlotPacket.java @@ -2,7 +2,7 @@ package org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.inventory; import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper; import org.geysermc.mcprotocollib.protocol.codec.MinecraftPacket; -import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; import lombok.Data; @@ -22,7 +22,7 @@ public class ClientboundContainerSetSlotPacket implements MinecraftPacket { this.containerId = in.readUnsignedByte(); this.stateId = helper.readVarInt(in); this.slot = in.readShort(); - this.item = helper.readItemStack(in); + this.item = helper.readOptionalItemStack(in); } @Override @@ -30,6 +30,6 @@ public class ClientboundContainerSetSlotPacket implements MinecraftPacket { out.writeByte(this.containerId); helper.writeVarInt(out, this.stateId); out.writeShort(this.slot); - helper.writeItemStack(out, this.item); + helper.writeOptionalItemStack(out, this.item); } } diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/inventory/ClientboundMerchantOffersPacket.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/inventory/ClientboundMerchantOffersPacket.java index 032a25ae..1e4216cf 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/inventory/ClientboundMerchantOffersPacket.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/inventory/ClientboundMerchantOffersPacket.java @@ -2,7 +2,7 @@ package org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.inventory; import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper; import org.geysermc.mcprotocollib.protocol.codec.MinecraftPacket; -import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import org.geysermc.mcprotocollib.protocol.data.game.inventory.VillagerTrade; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; @@ -27,9 +27,12 @@ public class ClientboundMerchantOffersPacket implements MinecraftPacket { int size = helper.readVarInt(in); this.trades = new VillagerTrade[size]; for (int i = 0; i < trades.length; i++) { - ItemStack firstInput = helper.readItemStack(in); - ItemStack output = helper.readItemStack(in); - ItemStack secondInput = helper.readItemStack(in); + ItemStack firstInput = helper.readTradeItemStack(in); + ItemStack output = helper.readOptionalItemStack(in); + ItemStack secondInput = null; + if (in.readBoolean()) { + secondInput = helper.readTradeItemStack(in); + } boolean tradeDisabled = in.readBoolean(); int numUses = in.readInt(); @@ -54,9 +57,12 @@ public class ClientboundMerchantOffersPacket implements MinecraftPacket { helper.writeVarInt(out, this.trades.length); for (VillagerTrade trade : this.trades) { - helper.writeItemStack(out, trade.getFirstInput()); - helper.writeItemStack(out, trade.getOutput()); - helper.writeItemStack(out, trade.getSecondInput()); + helper.writeTradeItemStack(out, trade.getFirstInput()); + helper.writeOptionalItemStack(out, trade.getOutput()); + out.writeBoolean(trade.getSecondInput() != null); + if (trade.getSecondInput() != null) { + helper.writeTradeItemStack(out, trade.getSecondInput()); + } out.writeBoolean(trade.isTradeDisabled()); out.writeInt(trade.getNumUses()); diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/level/ClientboundLevelParticlesPacket.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/level/ClientboundLevelParticlesPacket.java index 737e01bc..f80fdac3 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/level/ClientboundLevelParticlesPacket.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/level/ClientboundLevelParticlesPacket.java @@ -26,7 +26,6 @@ public class ClientboundLevelParticlesPacket implements MinecraftPacket { private final int amount; public ClientboundLevelParticlesPacket(ByteBuf in, MinecraftCodecHelper helper) { - ParticleType type = helper.readParticleType(in); this.longDistance = in.readBoolean(); this.x = in.readDouble(); this.y = in.readDouble(); @@ -36,12 +35,12 @@ public class ClientboundLevelParticlesPacket implements MinecraftPacket { this.offsetZ = in.readFloat(); this.velocityOffset = in.readFloat(); this.amount = in.readInt(); + ParticleType type = helper.readParticleType(in); this.particle = new Particle(type, helper.readParticleData(in, type)); } @Override public void serialize(ByteBuf out, MinecraftCodecHelper helper) { - helper.writeParticleType(out, this.particle.getType()); out.writeBoolean(this.longDistance); out.writeDouble(this.x); out.writeDouble(this.y); @@ -51,6 +50,7 @@ public class ClientboundLevelParticlesPacket implements MinecraftPacket { out.writeFloat(this.offsetZ); out.writeFloat(this.velocityOffset); out.writeInt(this.amount); + helper.writeParticleType(out, this.particle.getType()); helper.writeParticleData(out, this.particle.getType(), this.particle.getData()); } } diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/level/ClientboundMapItemDataPacket.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/level/ClientboundMapItemDataPacket.java index 605265f9..290c5c27 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/level/ClientboundMapItemDataPacket.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/level/ClientboundMapItemDataPacket.java @@ -36,9 +36,9 @@ public class ClientboundMapItemDataPacket implements MinecraftPacket { if (hasIcons) { for (int index = 0; index < this.icons.length; index++) { int type = helper.readVarInt(in); - int x = in.readUnsignedByte(); - int z = in.readUnsignedByte(); - int rotation = in.readUnsignedByte(); + int x = in.readByte(); + int z = in.readByte(); + int rotation = in.readByte(); Component displayName = null; if (in.readBoolean()) { displayName = helper.readComponent(in); diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/scoreboard/ClientboundSetObjectivePacket.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/scoreboard/ClientboundSetObjectivePacket.java index d51beeb2..2e5d9730 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/scoreboard/ClientboundSetObjectivePacket.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/scoreboard/ClientboundSetObjectivePacket.java @@ -68,7 +68,7 @@ public class ClientboundSetObjectivePacket implements MinecraftPacket { this.numberFormat = helper.readNullable(in, helper::readNumberFormat); } else { this.displayName = null; - this.type = null; + this.type = ScoreType.INTEGER; this.numberFormat = null; } } diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/title/ClientboundSetTitleTextPacket.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/title/ClientboundSetTitleTextPacket.java index 0e647c25..3dd9186a 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/title/ClientboundSetTitleTextPacket.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/title/ClientboundSetTitleTextPacket.java @@ -8,13 +8,14 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.With; import net.kyori.adventure.text.Component; +import lombok.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; @Data @With @AllArgsConstructor public class ClientboundSetTitleTextPacket implements MinecraftPacket { - private final @Nullable Component text; + private final @NonNull Component text; public ClientboundSetTitleTextPacket(ByteBuf in, MinecraftCodecHelper helper) { this.text = helper.readComponent(in); @@ -22,6 +23,6 @@ public class ClientboundSetTitleTextPacket implements MinecraftPacket { @Override public void serialize(ByteBuf out, MinecraftCodecHelper helper) { - helper.writeString(out, DefaultComponentSerializer.get().serializeOr(this.text, "null")); + helper.writeComponent(out, this.text); } } diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/serverbound/ServerboundChatCommandPacket.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/serverbound/ServerboundChatCommandPacket.java index bcff868d..b96e1f4d 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/serverbound/ServerboundChatCommandPacket.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/serverbound/ServerboundChatCommandPacket.java @@ -2,7 +2,6 @@ package org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound; import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper; import org.geysermc.mcprotocollib.protocol.codec.MinecraftPacket; -import org.geysermc.mcprotocollib.protocol.data.game.ArgumentSignature; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; import lombok.Data; @@ -17,40 +16,13 @@ import java.util.List; @AllArgsConstructor public class ServerboundChatCommandPacket implements MinecraftPacket { private final String command; - private final long timeStamp; - private final long salt; - private final List signatures; - private final int offset; - private final BitSet acknowledgedMessages; public ServerboundChatCommandPacket(ByteBuf in, MinecraftCodecHelper helper) { this.command = helper.readString(in); - this.timeStamp = in.readLong(); - this.salt = in.readLong(); - this.signatures = new ArrayList<>(); - int signatureCount = Math.min(helper.readVarInt(in), 8); - for (int i = 0; i < signatureCount; i++) { - byte[] signature = new byte[256]; - signatures.add(new ArgumentSignature(helper.readString(in, 16), signature)); - in.readBytes(signature); - } - - this.offset = helper.readVarInt(in); - this.acknowledgedMessages = helper.readFixedBitSet(in, 20); } @Override public void serialize(ByteBuf out, MinecraftCodecHelper helper) { helper.writeString(out, this.command); - out.writeLong(this.timeStamp); - out.writeLong(this.salt); - helper.writeVarInt(out, this.signatures.size()); - for (ArgumentSignature signature : this.signatures) { - helper.writeString(out, signature.getName()); - out.writeBytes(signature.getSignature()); - } - - helper.writeVarInt(out, this.offset); - helper.writeFixedBitSet(out, this.acknowledgedMessages, 20); } } diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/serverbound/ServerboundChatCommandSignedPacket.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/serverbound/ServerboundChatCommandSignedPacket.java new file mode 100644 index 00000000..44e148a8 --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/serverbound/ServerboundChatCommandSignedPacket.java @@ -0,0 +1,56 @@ +package org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound; + +import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper; +import org.geysermc.mcprotocollib.protocol.codec.MinecraftPacket; +import org.geysermc.mcprotocollib.protocol.data.game.ArgumentSignature; +import io.netty.buffer.ByteBuf; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.With; + +import java.util.ArrayList; +import java.util.BitSet; +import java.util.List; + +@Data +@With +@AllArgsConstructor +public class ServerboundChatCommandSignedPacket implements MinecraftPacket { + private final String command; + private final long timeStamp; + private final long salt; + private final List signatures; + private final int offset; + private final BitSet acknowledgedMessages; + + public ServerboundChatCommandSignedPacket(ByteBuf in, MinecraftCodecHelper helper) { + this.command = helper.readString(in); + this.timeStamp = in.readLong(); + this.salt = in.readLong(); + this.signatures = new ArrayList<>(); + int signatureCount = Math.min(helper.readVarInt(in), 8); + for (int i = 0; i < signatureCount; i++) { + byte[] signature = new byte[256]; + signatures.add(new ArgumentSignature(helper.readString(in, 16), signature)); + in.readBytes(signature); + } + + this.offset = helper.readVarInt(in); + this.acknowledgedMessages = helper.readFixedBitSet(in, 20); + } + + @Override + public void serialize(ByteBuf out, MinecraftCodecHelper helper) { + helper.writeString(out, this.command); + out.writeLong(this.timeStamp); + out.writeLong(this.salt); + helper.writeVarInt(out, this.signatures.size()); + for (ArgumentSignature signature : this.signatures) { + helper.writeString(out, signature.getName()); + out.writeBytes(signature.getSignature()); + } + + helper.writeVarInt(out, this.offset); + helper.writeFixedBitSet(out, this.acknowledgedMessages, 20); + } +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/serverbound/ServerboundDebugSampleSubscriptionPacket.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/serverbound/ServerboundDebugSampleSubscriptionPacket.java new file mode 100644 index 00000000..64691f15 --- /dev/null +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/serverbound/ServerboundDebugSampleSubscriptionPacket.java @@ -0,0 +1,25 @@ +package org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound; + +import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper; +import org.geysermc.mcprotocollib.protocol.codec.MinecraftPacket; +import org.geysermc.mcprotocollib.protocol.data.game.RemoteDebugSampleType; +import io.netty.buffer.ByteBuf; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.With; + +@Data +@With +@AllArgsConstructor +public class ServerboundDebugSampleSubscriptionPacket implements MinecraftPacket { + private final RemoteDebugSampleType debugSampleType; + + public ServerboundDebugSampleSubscriptionPacket(ByteBuf in, MinecraftCodecHelper helper) { + this.debugSampleType = RemoteDebugSampleType.from(helper.readVarInt(in)); + } + + @Override + public void serialize(ByteBuf out, MinecraftCodecHelper helper) { + helper.writeVarInt(out, this.debugSampleType.ordinal()); + } +} diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/serverbound/inventory/ServerboundContainerButtonClickPacket.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/serverbound/inventory/ServerboundContainerButtonClickPacket.java index e338f53f..a0dd2437 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/serverbound/inventory/ServerboundContainerButtonClickPacket.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/serverbound/inventory/ServerboundContainerButtonClickPacket.java @@ -15,13 +15,13 @@ public class ServerboundContainerButtonClickPacket implements MinecraftPacket { private final int buttonId; public ServerboundContainerButtonClickPacket(ByteBuf in, MinecraftCodecHelper helper) { - this.containerId = in.readByte(); - this.buttonId = in.readByte(); + this.containerId = helper.readVarInt(in); + this.buttonId = helper.readVarInt(in); } @Override public void serialize(ByteBuf out, MinecraftCodecHelper helper) { - out.writeByte(this.containerId); - out.writeByte(this.buttonId); + helper.writeVarInt(out, this.containerId); + helper.writeVarInt(out, this.buttonId); } } diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/serverbound/inventory/ServerboundContainerClickPacket.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/serverbound/inventory/ServerboundContainerClickPacket.java index 4fd15572..a0178654 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/serverbound/inventory/ServerboundContainerClickPacket.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/serverbound/inventory/ServerboundContainerClickPacket.java @@ -2,7 +2,7 @@ package org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory; import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper; import org.geysermc.mcprotocollib.protocol.codec.MinecraftPacket; -import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import org.geysermc.mcprotocollib.protocol.data.game.inventory.ClickItemAction; import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerAction; import org.geysermc.mcprotocollib.protocol.data.game.inventory.ContainerActionType; @@ -87,11 +87,11 @@ public class ServerboundContainerClickPacket implements MinecraftPacket { this.changedSlots = new Int2ObjectOpenHashMap<>(changedItemsSize); for (int i = 0; i < changedItemsSize; i++) { int key = in.readShort(); - ItemStack value = helper.readItemStack(in); + ItemStack value = helper.readOptionalItemStack(in); this.changedSlots.put(key, value); } - this.carriedItem = helper.readItemStack(in); + this.carriedItem = helper.readOptionalItemStack(in); } @Override @@ -111,9 +111,9 @@ public class ServerboundContainerClickPacket implements MinecraftPacket { helper.writeVarInt(out, this.changedSlots.size()); for (Int2ObjectMap.Entry pair : this.changedSlots.int2ObjectEntrySet()) { out.writeShort(pair.getIntKey()); - helper.writeItemStack(out, pair.getValue()); + helper.writeOptionalItemStack(out, pair.getValue()); } - helper.writeItemStack(out, this.carriedItem); + helper.writeOptionalItemStack(out, this.carriedItem); } } diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/serverbound/inventory/ServerboundSetCreativeModeSlotPacket.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/serverbound/inventory/ServerboundSetCreativeModeSlotPacket.java index 55da3fa7..75f9fe36 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/serverbound/inventory/ServerboundSetCreativeModeSlotPacket.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/serverbound/inventory/ServerboundSetCreativeModeSlotPacket.java @@ -2,7 +2,7 @@ package org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.inventory; import org.geysermc.mcprotocollib.protocol.codec.MinecraftCodecHelper; import org.geysermc.mcprotocollib.protocol.codec.MinecraftPacket; -import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import io.netty.buffer.ByteBuf; import lombok.AllArgsConstructor; import lombok.Data; @@ -13,17 +13,17 @@ import org.checkerframework.checker.nullness.qual.Nullable; @With @AllArgsConstructor public class ServerboundSetCreativeModeSlotPacket implements MinecraftPacket { - private final int slot; + private final short slot; private final @Nullable ItemStack clickedItem; public ServerboundSetCreativeModeSlotPacket(ByteBuf in, MinecraftCodecHelper helper) { this.slot = in.readShort(); - this.clickedItem = helper.readItemStack(in); + this.clickedItem = helper.readOptionalItemStack(in); } @Override public void serialize(ByteBuf out, MinecraftCodecHelper helper) { out.writeShort(this.slot); - helper.writeItemStack(out, this.clickedItem); + helper.writeOptionalItemStack(out, this.clickedItem); } } diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/serverbound/level/ServerboundBlockEntityTagQuery.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/serverbound/level/ServerboundBlockEntityTagQueryPacket.java similarity index 82% rename from protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/serverbound/level/ServerboundBlockEntityTagQuery.java rename to protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/serverbound/level/ServerboundBlockEntityTagQueryPacket.java index 896723c6..b0e94d6a 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/serverbound/level/ServerboundBlockEntityTagQuery.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/ingame/serverbound/level/ServerboundBlockEntityTagQueryPacket.java @@ -12,11 +12,11 @@ import org.cloudburstmc.math.vector.Vector3i; @Data @With @AllArgsConstructor -public class ServerboundBlockEntityTagQuery implements MinecraftPacket { +public class ServerboundBlockEntityTagQueryPacket implements MinecraftPacket { private final int transactionId; private final @NonNull Vector3i position; - public ServerboundBlockEntityTagQuery(ByteBuf in, MinecraftCodecHelper helper) { + public ServerboundBlockEntityTagQueryPacket(ByteBuf in, MinecraftCodecHelper helper) { this.transactionId = helper.readVarInt(in); this.position = helper.readPosition(in); } diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/login/clientbound/ClientboundGameProfilePacket.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/login/clientbound/ClientboundGameProfilePacket.java index 0b81e96a..52a45215 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/login/clientbound/ClientboundGameProfilePacket.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/login/clientbound/ClientboundGameProfilePacket.java @@ -17,6 +17,7 @@ import java.util.List; @AllArgsConstructor public class ClientboundGameProfilePacket implements MinecraftPacket { private final @NonNull GameProfile profile; + private final boolean strictErrorHandling; public ClientboundGameProfilePacket(ByteBuf in, MinecraftCodecHelper helper) { GameProfile profile = new GameProfile(helper.readUUID(in), helper.readString(in)); @@ -35,6 +36,7 @@ public class ClientboundGameProfilePacket implements MinecraftPacket { profile.setProperties(propertyList); this.profile = profile; + this.strictErrorHandling = in.readBoolean(); } @Override @@ -50,6 +52,7 @@ public class ClientboundGameProfilePacket implements MinecraftPacket { helper.writeString(out, property.getSignature()); } } + out.writeBoolean(this.strictErrorHandling); } @Override diff --git a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/login/clientbound/ClientboundHelloPacket.java b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/login/clientbound/ClientboundHelloPacket.java index 75f2d10e..31b7d60b 100644 --- a/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/login/clientbound/ClientboundHelloPacket.java +++ b/protocol/src/main/java/org/geysermc/mcprotocollib/protocol/packet/login/clientbound/ClientboundHelloPacket.java @@ -20,11 +20,13 @@ public class ClientboundHelloPacket implements MinecraftPacket { private final @NonNull String serverId; private final @NonNull PublicKey publicKey; private final byte @NonNull [] challenge; + private final boolean shouldAuthenticate; public ClientboundHelloPacket(ByteBuf in, MinecraftCodecHelper helper) { this.serverId = helper.readString(in); byte[] publicKey = helper.readByteArray(in); this.challenge = helper.readByteArray(in); + this.shouldAuthenticate = in.readBoolean(); try { this.publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(publicKey)); @@ -39,6 +41,7 @@ public class ClientboundHelloPacket implements MinecraftPacket { byte[] encoded = this.publicKey.getEncoded(); helper.writeByteArray(out, encoded); helper.writeByteArray(out, this.challenge); + out.writeBoolean(this.shouldAuthenticate); } @Override diff --git a/protocol/src/main/resources/networkCodec.nbt b/protocol/src/main/resources/networkCodec.nbt index bdd185a1..9b5814f7 100644 Binary files a/protocol/src/main/resources/networkCodec.nbt and b/protocol/src/main/resources/networkCodec.nbt differ diff --git a/protocol/src/test/java/org/geysermc/mcprotocollib/protocol/MinecraftProtocolTest.java b/protocol/src/test/java/org/geysermc/mcprotocollib/protocol/MinecraftProtocolTest.java index 79c3b9f4..99a7c1ca 100644 --- a/protocol/src/test/java/org/geysermc/mcprotocollib/protocol/MinecraftProtocolTest.java +++ b/protocol/src/test/java/org/geysermc/mcprotocollib/protocol/MinecraftProtocolTest.java @@ -43,7 +43,7 @@ public class MinecraftProtocolTest { null, false ); - private static final ClientboundLoginPacket JOIN_GAME_PACKET = new ClientboundLoginPacket(0, false, new String[]{"minecraft:world"}, 0, 16, 16, false, false, false, new PlayerSpawnInfo("overworld", "minecraft:world", 100, GameMode.SURVIVAL, GameMode.SURVIVAL, false, false, null, 100)); + private static final ClientboundLoginPacket JOIN_GAME_PACKET = new ClientboundLoginPacket(0, false, new String[]{"minecraft:world"}, 0, 16, 16, false, false, false, new PlayerSpawnInfo(0, "minecraft:world", 100, GameMode.SURVIVAL, GameMode.SURVIVAL, false, false, null, 100), true); private static Server server; diff --git a/protocol/src/test/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/ServerDeclareRecipesTest.java b/protocol/src/test/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/ServerDeclareRecipesTest.java index 32f63f14..8c139a9b 100644 --- a/protocol/src/test/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/ServerDeclareRecipesTest.java +++ b/protocol/src/test/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/ServerDeclareRecipesTest.java @@ -1,6 +1,6 @@ package org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound; -import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import org.geysermc.mcprotocollib.protocol.data.game.recipe.CraftingBookCategory; import org.geysermc.mcprotocollib.protocol.data.game.recipe.Ingredient; import org.geysermc.mcprotocollib.protocol.data.game.recipe.Recipe; diff --git a/protocol/src/test/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/level/ClientboundSetEquipmentPacketTest.java b/protocol/src/test/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/level/ClientboundSetEquipmentPacketTest.java index 44af3909..9193bdeb 100644 --- a/protocol/src/test/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/level/ClientboundSetEquipmentPacketTest.java +++ b/protocol/src/test/java/org/geysermc/mcprotocollib/protocol/packet/ingame/clientbound/level/ClientboundSetEquipmentPacketTest.java @@ -2,7 +2,7 @@ package org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.level; import org.geysermc.mcprotocollib.protocol.data.game.entity.EquipmentSlot; import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.Equipment; -import org.geysermc.mcprotocollib.protocol.data.game.entity.metadata.ItemStack; +import org.geysermc.mcprotocollib.protocol.data.game.item.ItemStack; import org.geysermc.mcprotocollib.protocol.packet.PacketTest; import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.entity.ClientboundSetEquipmentPacket; import org.junit.jupiter.api.BeforeEach; diff --git a/protocol/src/test/java/org/geysermc/mcprotocollib/protocol/packet/login/clientbound/ClientboundGameProfilePacketTest.java b/protocol/src/test/java/org/geysermc/mcprotocollib/protocol/packet/login/clientbound/ClientboundGameProfilePacketTest.java index 183d69ea..52a2a6e0 100644 --- a/protocol/src/test/java/org/geysermc/mcprotocollib/protocol/packet/login/clientbound/ClientboundGameProfilePacketTest.java +++ b/protocol/src/test/java/org/geysermc/mcprotocollib/protocol/packet/login/clientbound/ClientboundGameProfilePacketTest.java @@ -9,6 +9,6 @@ import java.util.UUID; public class ClientboundGameProfilePacketTest extends PacketTest { @BeforeEach public void setup() { - this.setPackets(new ClientboundGameProfilePacket(new GameProfile(UUID.randomUUID(), "Username"))); + this.setPackets(new ClientboundGameProfilePacket(new GameProfile(UUID.randomUUID(), "Username"), true)); } } diff --git a/protocol/src/test/java/org/geysermc/mcprotocollib/protocol/packet/login/clientbound/ClientboundHelloPacketTest.java b/protocol/src/test/java/org/geysermc/mcprotocollib/protocol/packet/login/clientbound/ClientboundHelloPacketTest.java index b0e13de6..60c8d313 100644 --- a/protocol/src/test/java/org/geysermc/mcprotocollib/protocol/packet/login/clientbound/ClientboundHelloPacketTest.java +++ b/protocol/src/test/java/org/geysermc/mcprotocollib/protocol/packet/login/clientbound/ClientboundHelloPacketTest.java @@ -23,6 +23,6 @@ public class ClientboundHelloPacketTest extends PacketTest { byte[] verifyToken = new byte[4]; new Random().nextBytes(verifyToken); - this.setPackets(new ClientboundHelloPacket("ServerID", keyPair.getPublic(), verifyToken)); + this.setPackets(new ClientboundHelloPacket("ServerID", keyPair.getPublic(), verifyToken, true)); } }