Merge pull request #798 from AlexProgrammerDE/1.20.5-dev-2

1.20.5 dev 2
This commit is contained in:
Camotoy 2024-04-24 16:03:22 -04:00 committed by GitHub
commit 1ca8808eba
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
115 changed files with 2575 additions and 300 deletions

View file

@ -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());
}

View file

@ -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
))
);

View file

@ -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 {
*/
<T> void setFlag(Flag<T> flag, T value);
/**
* Sets the values for a collection of flags.
*
* @param flags Collection of flags
*/
public void setFlags(Map<String, Object> flags);
/**
* Gets the listeners listening on this session.
*

View file

@ -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.

View file

@ -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 {

View file

@ -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<ByteBuf> {
@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);

View file

@ -67,6 +67,11 @@ public abstract class TcpSession extends SimpleChannelInboundHandler<Packet> 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<Packet> imp
this.flags.put(flag.key(), value);
}
@Override
public void setFlags(Map<String, Object> flags) {
this.flags.putAll(flags);
}
@Override
public List<SessionListener> getListeners() {
return Collections.unmodifiableList(this.listeners);

View file

@ -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));
}
}
}

View file

@ -57,6 +57,11 @@ public final class MinecraftConstants {
*/
public static final Flag<Boolean> VERIFY_USERS_KEY = new Flag<>("verify-users", Boolean.class);
/**
* Session flag for determining whether to accept transferred connections. Server only.
*/
public static final Flag<Boolean> ACCEPT_TRANSFERS_KEY = new Flag<>("accept-transfers", Boolean.class);
/**
* Session flag for providing a custom server info response builder. Server only.
*/

View file

@ -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));
}
}

View file

@ -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<String, Tag> entry : networkCodec.getValue().entrySet()) {
CompoundTag entryTag = (CompoundTag) entry.getValue();
StringTag typeTag = entryTag.get("type");
ListTag valueTag = entryTag.get("value");
List<RegistryEntry> 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));
}
}

View file

@ -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)

View file

@ -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 <T> Holder<T> readHolder(ByteBuf buf, Function<ByteBuf, T> readCustom) {
int registryId = this.readVarInt(buf);
return registryId == 0 ? Holder.ofCustom(readCustom.apply(buf)) : Holder.ofId(registryId - 1);
}
public <T> void writeHolder(ByteBuf buf, Holder<T> holder, BiConsumer<ByteBuf, T> 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<DataComponentType<?>, 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<DataComponentType<?>, 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);
}
}

View file

@ -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!");
}

View file

@ -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<T> {
static <T> Holder<T> ofId(int id) {
return new IdHolder<>(id);
}
static <T> Holder<T> ofCustom(T object) {
return new CustomHolder<>(object);
}
boolean isId();
int id();
boolean isCustom();
T custom();
Holder<T> ifId(Consumer<Holder<T>> action);
Holder<T> ifCustom(Consumer<Holder<T>> action);
record IdHolder<T>(int id) implements Holder<T> {
@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<T> ifId(Consumer<Holder<T>> action) {
action.accept(this);
return this;
}
@Override
public Holder<T> ifCustom(Consumer<Holder<T>> action) {
// no-op
return this;
}
}
record CustomHolder<T>(T object) implements Holder<T> {
@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<T> ifId(Consumer<Holder<T>> action) {
return this;
}
@Override
public Holder<T> ifCustom(Consumer<Holder<T>> action) {
action.accept(this);
return this;
}
}
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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];
}
}

View file

@ -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;

View file

@ -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();

View file

@ -6,7 +6,8 @@ public enum EquipmentSlot {
BOOTS,
LEGGINGS,
CHESTPLATE,
HELMET;
HELMET,
BODY;
private static final EquipmentSlot[] VALUES = values();

View file

@ -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<String, AttributeType> 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<AttributeType> BUILTIN = new Int2ObjectOpenHashMap<>();
public static AttributeType from(int id) {
return BUILTIN.get(id);
}
static {
for (Builtin attribute : values()) {
BUILTIN.put(attribute.ordinal(), attribute);
}
}
}
}

View file

@ -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();

View file

@ -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");
}

View file

@ -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];
}
}

View file

@ -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;

View file

@ -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<T> {
public static final MetadataType<String> STRING = new MetadataType<>(MinecraftCodecHelper::readString, MinecraftCodecHelper::writeString, ObjectEntityMetadata::new);
public static final MetadataType<Component> CHAT = new MetadataType<>(MinecraftCodecHelper::readComponent, MinecraftCodecHelper::writeComponent, ObjectEntityMetadata::new);
public static final MetadataType<Optional<Component>> OPTIONAL_CHAT = new MetadataType<>(optionalReader(MinecraftCodecHelper::readComponent), optionalWriter(MinecraftCodecHelper::writeComponent), ObjectEntityMetadata::new);
public static final MetadataType<ItemStack> ITEM = new MetadataType<>(MinecraftCodecHelper::readItemStack, MinecraftCodecHelper::writeItemStack, ObjectEntityMetadata::new);
public static final MetadataType<ItemStack> 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<Vector3f> ROTATION = new MetadataType<>(MinecraftCodecHelper::readRotation, MinecraftCodecHelper::writeRotation, ObjectEntityMetadata::new);
public static final MetadataType<Vector3i> POSITION = new MetadataType<>(MinecraftCodecHelper::readPosition, MinecraftCodecHelper::writePosition, ObjectEntityMetadata::new);
@ -45,14 +47,17 @@ public class MetadataType<T> {
public static final IntMetadataType OPTIONAL_BLOCK_STATE = new IntMetadataType(MinecraftCodecHelper::readVarInt, MinecraftCodecHelper::writeVarInt, IntEntityMetadata::new);
public static final MetadataType<CompoundTag> NBT_TAG = new MetadataType<>(MinecraftCodecHelper::readAnyTag, MinecraftCodecHelper::writeAnyTag, ObjectEntityMetadata::new);
public static final MetadataType<Particle> PARTICLE = new MetadataType<>(MinecraftCodecHelper::readParticle, MinecraftCodecHelper::writeParticle, ObjectEntityMetadata::new);
public static final MetadataType<List<Particle>> PARTICLES = new MetadataType<>(listReader(MinecraftCodecHelper::readParticle), listWriter(MinecraftCodecHelper::writeParticle), ObjectEntityMetadata::new);
public static final MetadataType<VillagerData> 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> 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<GlobalPos>> OPTIONAL_GLOBAL_POS = new MetadataType<>(optionalReader(MinecraftCodecHelper::readGlobalPos), optionalWriter(MinecraftCodecHelper::writeGlobalPos), ObjectEntityMetadata::new);
public static final MetadataType<PaintingType> PAINTING_VARIANT = new MetadataType<>(MinecraftCodecHelper::readPaintingType, MinecraftCodecHelper::writePaintingType, ObjectEntityMetadata::new);
public static final MetadataType<SnifferState> SNIFFER_STATE = new MetadataType<>(MinecraftCodecHelper::readSnifferState, MinecraftCodecHelper::writeSnifferState, ObjectEntityMetadata::new);
public static final MetadataType<ArmadilloState> ARMADILLO_STATE = new MetadataType<>(MinecraftCodecHelper::readArmadilloState, MinecraftCodecHelper::writeArmadilloState, ObjectEntityMetadata::new);
public static final MetadataType<Vector3f> VECTOR3 = new MetadataType<>(MinecraftCodecHelper::readRotation, MinecraftCodecHelper::writeRotation, ObjectEntityMetadata::new);
public static final MetadataType<Vector4f> QUATERNION = new MetadataType<>(MinecraftCodecHelper::readQuaternion, MinecraftCodecHelper::writeQuaternion, ObjectEntityMetadata::new);
@ -145,6 +150,26 @@ public class MetadataType<T> {
};
}
private static <T> Reader<List<T>> listReader(Reader<T> reader) {
return (helper, input) -> {
List<T> ret = new ArrayList<>();
for (int i = 0; i < helper.readVarInt(input); i++) {
ret.add(reader.read(helper, input));
}
return ret;
};
}
private static <T> Writer<List<T>> listWriter(Writer<T> 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()) {

View file

@ -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;

View file

@ -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,

View file

@ -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;

View file

@ -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);

View file

@ -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<BlockPredicate> 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<PropertyMatcher> 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;
}
}

View file

@ -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<TrimMaterial> material, Holder<TrimPattern> pattern, boolean showInTooltip) {
public record TrimMaterial(String assetName, int ingredientId, float itemModelIndex,
Int2ObjectMap<String> overrideArmorMaterials, Component description) {
}
public record TrimPattern(String assetId, int templateItemId, Component description, boolean decal) {
}
}

View file

@ -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<BannerPattern> pattern;
private final int colorId;
@Data
@AllArgsConstructor
public static class BannerPattern {
private final String assetId;
private final String translationKey;
}
}

View file

@ -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;
}

View file

@ -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<String, String> properties;
}

View file

@ -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<Boolean> {
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<Boolean, BooleanComponentType> 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> {
boolean readPrimitive(ByteBuf input);
@Deprecated
@Override
default Boolean read(ByteBuf input) {
return this.readPrimitive(input);
}
}
@FunctionalInterface
public interface BooleanWriter extends BasicWriter<Boolean> {
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<Boolean> {
BooleanDataComponent createPrimitive(BooleanComponentType type, boolean value);
@Deprecated
@Override
default DataComponent<Boolean, BooleanComponentType> create(DataComponentType<Boolean> type, Boolean value) {
throw new UnsupportedOperationException("Unsupported read method! Use primitive createPrimitive!");
}
}
}

View file

@ -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<V, T extends DataComponentType<V>> {
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());
}
}

View file

@ -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<T> {
private static final List<DataComponentType<?>> VALUES = new ArrayList<>();
public static final DataComponentType<CompoundTag> 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<Component> CUSTOM_NAME = new DataComponentType<>(ItemCodecHelper::readComponent, ItemCodecHelper::writeComponent, ObjectDataComponent::new);
public static final DataComponentType<Component> ITEM_NAME = new DataComponentType<>(ItemCodecHelper::readComponent, ItemCodecHelper::writeComponent, ObjectDataComponent::new);
public static final DataComponentType<List<Component>> 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<ItemEnchantments> ENCHANTMENTS = new DataComponentType<>(ItemCodecHelper::readItemEnchantments, ItemCodecHelper::writeItemEnchantments, ObjectDataComponent::new);
public static final DataComponentType<AdventureModePredicate> CAN_PLACE_ON = new DataComponentType<>(ItemCodecHelper::readAdventureModePredicate, ItemCodecHelper::writeAdventureModePredicate, ObjectDataComponent::new);
public static final DataComponentType<AdventureModePredicate> CAN_BREAK = new DataComponentType<>(ItemCodecHelper::readAdventureModePredicate, ItemCodecHelper::writeAdventureModePredicate, ObjectDataComponent::new);
public static final DataComponentType<ItemAttributeModifiers> 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<Unit> HIDE_ADDITIONAL_TOOLTIP = new DataComponentType<>(unitReader(), unitWriter(), ObjectDataComponent::new);
public static final DataComponentType<Unit> 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<Unit> 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<CompoundTag> INTANGIBLE_PROJECTILE = new DataComponentType<>(ItemCodecHelper::readAnyTag, ItemCodecHelper::writeAnyTag, ObjectDataComponent::new);
public static final DataComponentType<FoodProperties> FOOD = new DataComponentType<>(ItemCodecHelper::readFoodProperties, ItemCodecHelper::writeFoodProperties, ObjectDataComponent::new);
public static final DataComponentType<Unit> FIRE_RESISTANT = new DataComponentType<>(unitReader(), unitWriter(), ObjectDataComponent::new);
public static final DataComponentType<ToolData> TOOL = new DataComponentType<>(ItemCodecHelper::readToolData, ItemCodecHelper::writeToolData, ObjectDataComponent::new);
public static final DataComponentType<ItemEnchantments> STORED_ENCHANTMENTS = new DataComponentType<>(ItemCodecHelper::readItemEnchantments, ItemCodecHelper::writeItemEnchantments, ObjectDataComponent::new);
public static final DataComponentType<DyedItemColor> 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<CompoundTag> 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<List<ItemStack>> CHARGED_PROJECTILES = new DataComponentType<>(listReader(ItemCodecHelper::readItemStack), listWriter(ItemCodecHelper::writeItemStack), ObjectDataComponent::new);
public static final DataComponentType<List<ItemStack>> BUNDLE_CONTENTS = new DataComponentType<>(listReader(ItemCodecHelper::readItemStack), listWriter(ItemCodecHelper::writeItemStack), ObjectDataComponent::new);
public static final DataComponentType<PotionContents> POTION_CONTENTS = new DataComponentType<>(ItemCodecHelper::readPotionContents, ItemCodecHelper::writePotionContents, ObjectDataComponent::new);
public static final DataComponentType<List<SuspiciousStewEffect>> SUSPICIOUS_STEW_EFFECTS = new DataComponentType<>(listReader(ItemCodecHelper::readStewEffect), listWriter(ItemCodecHelper::writeStewEffect), ObjectDataComponent::new);
public static final DataComponentType<WritableBookContent> WRITABLE_BOOK_CONTENT = new DataComponentType<>(ItemCodecHelper::readWritableBookContent, ItemCodecHelper::writeWritableBookContent, ObjectDataComponent::new);
public static final DataComponentType<WrittenBookContent> WRITTEN_BOOK_CONTENT = new DataComponentType<>(ItemCodecHelper::readWrittenBookContent, ItemCodecHelper::writeWrittenBookContent, ObjectDataComponent::new);
public static final DataComponentType<ArmorTrim> TRIM = new DataComponentType<>(ItemCodecHelper::readArmorTrim, ItemCodecHelper::writeArmorTrim, ObjectDataComponent::new);
public static final DataComponentType<CompoundTag> DEBUG_STICK_STATE = new DataComponentType<>(ItemCodecHelper::readAnyTag, ItemCodecHelper::writeAnyTag, ObjectDataComponent::new);
public static final DataComponentType<CompoundTag> ENTITY_DATA = new DataComponentType<>(ItemCodecHelper::readAnyTag, ItemCodecHelper::writeAnyTag, ObjectDataComponent::new);
public static final DataComponentType<CompoundTag> BUCKET_ENTITY_DATA = new DataComponentType<>(ItemCodecHelper::readAnyTag, ItemCodecHelper::writeAnyTag, ObjectDataComponent::new);
public static final DataComponentType<CompoundTag> BLOCK_ENTITY_DATA = new DataComponentType<>(ItemCodecHelper::readAnyTag, ItemCodecHelper::writeAnyTag, ObjectDataComponent::new);
public static final DataComponentType<Holder<Instrument>> 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<ListTag> RECIPES = new DataComponentType<>(ItemCodecHelper::readRecipes, ItemCodecHelper::writeRecipes, ObjectDataComponent::new);
public static final DataComponentType<LodestoneTracker> LODESTONE_TRACKER = new DataComponentType<>(ItemCodecHelper::readLodestoneTarget, ItemCodecHelper::writeLodestoneTarget, ObjectDataComponent::new);
public static final DataComponentType<Fireworks.FireworkExplosion> FIREWORK_EXPLOSION = new DataComponentType<>(ItemCodecHelper::readFireworkExplosion, ItemCodecHelper::writeFireworkExplosion, ObjectDataComponent::new);
public static final DataComponentType<Fireworks> FIREWORKS = new DataComponentType<>(ItemCodecHelper::readFireworks, ItemCodecHelper::writeFireworks, ObjectDataComponent::new);
public static final DataComponentType<GameProfile> PROFILE = new DataComponentType<>(ItemCodecHelper::readResolvableProfile, ItemCodecHelper::writeResolvableProfile, ObjectDataComponent::new);
public static final DataComponentType<String> NOTE_BLOCK_SOUND = new DataComponentType<>(ItemCodecHelper::readResourceLocation, ItemCodecHelper::writeResourceLocation, ObjectDataComponent::new);
public static final DataComponentType<List<BannerPatternLayer>> 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<List<Integer>> POT_DECORATIONS = new DataComponentType<>(listReader(ItemCodecHelper::readVarInt), listWriter(ItemCodecHelper::writeVarInt), ObjectDataComponent::new);
public static final DataComponentType<List<ItemStack>> CONTAINER = new DataComponentType<>(listReader(ItemCodecHelper::readOptionalItemStack), listWriter(MinecraftCodecHelper::writeOptionalItemStack), ObjectDataComponent::new);
public static final DataComponentType<BlockStateProperties> BLOCK_STATE = new DataComponentType<>(ItemCodecHelper::readBlockStateProperties, ItemCodecHelper::writeBlockStateProperties, ObjectDataComponent::new);
public static final DataComponentType<List<BeehiveOccupant>> BEES = new DataComponentType<>(listReader(ItemCodecHelper::readBeehiveOccupant), listWriter(ItemCodecHelper::writeBeehiveOccupant), ObjectDataComponent::new);
public static final DataComponentType<StringTag> LOCK = new DataComponentType<>(ItemCodecHelper::readLock, ItemCodecHelper::writeLock, ObjectDataComponent::new);
public static final DataComponentType<CompoundTag> CONTAINER_LOOT = new DataComponentType<>(ItemCodecHelper::readAnyTag, ItemCodecHelper::writeAnyTag, ObjectDataComponent::new);
protected final int id;
protected final Reader<T> reader;
protected final Writer<T> writer;
protected final DataComponentFactory<T> dataComponentFactory;
protected DataComponentType(Reader<T> reader, Writer<T> writer, DataComponentFactory<T> dataComponentFactory) {
this.id = VALUES.size();
this.reader = reader;
this.writer = writer;
this.dataComponentFactory = dataComponentFactory;
VALUES.add(this);
}
public DataComponent<T, ? extends DataComponentType<T>> readDataComponent(ItemCodecHelper helper, ByteBuf input) {
return this.dataComponentFactory.create(this, this.reader.read(helper, input));
}
public DataComponent<T, ? extends DataComponentType<T>> 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> {
V read(ItemCodecHelper helper, ByteBuf input);
}
@FunctionalInterface
public interface Writer<V> {
void write(ItemCodecHelper helper, ByteBuf output, V value);
}
@FunctionalInterface
public interface BasicReader<V> extends Reader<V> {
V read(ByteBuf input);
default V read(ItemCodecHelper helper, ByteBuf input) {
return this.read(input);
}
}
@FunctionalInterface
public interface BasicWriter<V> extends Writer<V> {
void write(ByteBuf output, V Value);
default void write(ItemCodecHelper helper, ByteBuf output, V value) {
this.write(output, value);
}
}
@FunctionalInterface
public interface DataComponentFactory<V> {
DataComponent<V, ? extends DataComponentType<V>> create(DataComponentType<V> type, V value);
}
private static <T> Reader<List<T>> listReader(Reader<T> reader) {
return (helper, input) -> {
List<T> 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 <T> Writer<List<T>> listWriter(Writer<T> writer) {
return (helper, output, value) -> {
helper.writeVarInt(output, value.size());
for (T object : value) {
writer.write(helper, output, object);
}
};
}
private static Reader<Unit> unitReader() {
return (helper, input) -> Unit.INSTANCE;
}
private static Writer<Unit> 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();
}
}

View file

@ -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<DataComponentType<?>, DataComponent<?, ?>> dataComponents;
@Nullable
public <T> T get(DataComponentType<T> type) {
DataComponent component = dataComponents.get(type);
return component == null ? null : (T) component.getValue();
}
public <T> T getOrDefault(DataComponentType<T> type, T def) {
T value = get(type);
return value != null ? value : def;
}
public <T> void put(DataComponentType<T> 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));
}
}

View file

@ -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;
}

View file

@ -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<T> {
private final T raw;
private final @Nullable T optional;
}

View file

@ -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<FireworkExplosion> 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;
}
}

View file

@ -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<PossibleEffect> effects;
@Data
@AllArgsConstructor
public static class PossibleEffect {
private final MobEffectDetails effect;
private final float probability;
}
}

View file

@ -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;
}

View file

@ -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<Integer> {
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<Integer, IntComponentType> 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<Integer> {
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<Integer> {
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<Integer> {
IntDataComponent createPrimitive(IntComponentType type, int value);
@Deprecated
@Override
default DataComponent<Integer, IntComponentType> create(DataComponentType<Integer> type, Integer value) {
throw new UnsupportedOperationException("Unsupported read method! Use primitive createPrimitive!");
}
}
}

View file

@ -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<Entry> 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];
}
}
}

View file

@ -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 <T> Filterable<T> readFilterable(ByteBuf buf, Function<ByteBuf, T> reader) {
T raw = reader.apply(buf);
T filtered = null;
if (buf.readBoolean()) {
filtered = reader.apply(buf);
}
return new Filterable<>(raw, filtered);
}
public <T> void writeFilterable(ByteBuf buf, Filterable<T> filterable, BiConsumer<ByteBuf, T> 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<Integer, Integer> 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<Integer, Integer> entry : itemEnchantments.getEnchantments().entrySet()) {
this.writeVarInt(buf, entry.getKey());
this.writeVarInt(buf, entry.getValue());
}
buf.writeBoolean(itemEnchantments.isShowInTooltip());
}
public AdventureModePredicate readAdventureModePredicate(ByteBuf buf) {
List<AdventureModePredicate.BlockPredicate> 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<AdventureModePredicate.PropertyMatcher> 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<ToolData.Rule> 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<ItemAttributeModifiers.Entry> 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<MobEffectDetails> 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<MobEffectDetails> 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<FoodProperties.PossibleEffect> 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<Filterable<String>> 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<String> page : content.getPages()) {
this.writeFilterable(buf, page, this::writeString);
}
}
public WrittenBookContent readWrittenBookContent(ByteBuf buf) {
Filterable<String> title = this.readFilterable(buf, this::readString);
String author = this.readString(buf);
int generation = this.readVarInt(buf);
List<Filterable<Component>> 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<Component> page : content.getPages()) {
this.writeFilterable(buf, page, this::writeComponent);
}
buf.writeBoolean(content.isResolved());
}
public ArmorTrim readArmorTrim(ByteBuf buf) {
Holder<ArmorTrim.TrimMaterial> material = this.readHolder(buf, this::readTrimMaterial);
Holder<ArmorTrim.TrimPattern> 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<String> 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<String> 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<Instrument> 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<Instrument> 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<Fireworks.FireworkExplosion> 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<GameProfile.Property> 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<String, String> 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<String, String> 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);
}
}

View file

@ -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<Integer, Integer> enchantments;
private final boolean showInTooltip;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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<MobEffectDetails> customEffects;
}

View file

@ -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;
}

View file

@ -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<Rule> 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;
}
}

View file

@ -0,0 +1,5 @@
package org.geysermc.mcprotocollib.protocol.data.game.item.component;
public enum Unit {
INSTANCE;
}

View file

@ -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<Filterable<String>> pages;
}

View file

@ -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<String> title;
private final String author;
private final int generation;
private final List<Filterable<Component>> pages;
private final boolean resolved;
}

View file

@ -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<Boolean, BooleanComponentType> {
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);
}
}

View file

@ -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<Integer, IntComponentType> {
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);
}
}

View file

@ -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<T> extends DataComponent<T, DataComponentType<T>> {
private final T value;
public ObjectDataComponent(@NonNull DataComponentType<T> type, T value) {
super(type);
this.value = value;
}
@Override
public T getValue() {
return value;
}
}

View file

@ -45,7 +45,8 @@ public enum BlockEntityType {
BRUSHABLE_BLOCK,
DECORATED_POT,
CRAFTER,
TRIAL_SPAWNER;
TRIAL_SPAWNER,
VAULT;
private static final BlockEntityType[] VALUES = values();

View file

@ -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;

View file

@ -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;
}

View file

@ -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;

View file

@ -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();

View file

@ -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;

View file

@ -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;

View file

@ -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<String, RecipeType> 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];
}
}

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -2,7 +2,8 @@ package org.geysermc.mcprotocollib.protocol.data.handshake;
public enum HandshakeIntent {
STATUS,
LOGIN;
LOGIN,
TRANSFER;
private static final HandshakeIntent[] VALUES = values();

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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<RegistryEntry> 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);
}
}
}

View file

@ -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) {
}
}

View file

@ -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<KnownPack> 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());
}
}
}

View file

@ -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<KnownPack> 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());
}
}
}

View file

@ -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());
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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();

View file

@ -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();

View file

@ -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);
}
}

View file

@ -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());
}
}
}

View file

@ -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<AttributeModifier> 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()) {

View file

@ -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);
}
}

View file

@ -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);

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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());

View file

@ -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());
}
}

View file

@ -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);

View file

@ -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;
}
}

View file

@ -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);
}
}

Some files were not shown because too many files have changed in this diff Show more