diff --git a/protocol/src/main/java/mc/protocol/ChatMode.java b/protocol/src/main/java/mc/protocol/ChatMode.java new file mode 100644 index 0000000..33c7bcc --- /dev/null +++ b/protocol/src/main/java/mc/protocol/ChatMode.java @@ -0,0 +1,20 @@ +package mc.protocol; + +import javax.annotation.Nullable; + +public enum ChatMode { + FULL, + COMMANDS_ONLY, + HIDDEN; + + @Nullable + public static ChatMode valueById(int id) { + // а зачем усложнять? + //@formatter:off + if (id == 1) return FULL; + else if (id == 2) return COMMANDS_ONLY; + else if (id == 3) return HIDDEN; + else return null; + //@formatter:on + } +} diff --git a/protocol/src/main/java/mc/protocol/MainHand.java b/protocol/src/main/java/mc/protocol/MainHand.java new file mode 100644 index 0000000..15ea441 --- /dev/null +++ b/protocol/src/main/java/mc/protocol/MainHand.java @@ -0,0 +1,18 @@ +package mc.protocol; + +import javax.annotation.Nullable; + +public enum MainHand { + LEFT, + RIGHT; + + @Nullable + public static MainHand valueById(int id) { + // а зачем усложнять? + //@formatter:off + if (id == 0) return LEFT; + else if (id == 1) return RIGHT; + else return null; + //@formatter:on + } +} diff --git a/protocol/src/main/java/mc/protocol/State.java b/protocol/src/main/java/mc/protocol/State.java index a4227dd..3f7db7b 100644 --- a/protocol/src/main/java/mc/protocol/State.java +++ b/protocol/src/main/java/mc/protocol/State.java @@ -6,6 +6,7 @@ import mc.protocol.packets.ClientSidePacket; import mc.protocol.packets.Packet; import mc.protocol.packets.PingPacket; import mc.protocol.packets.ServerSidePacket; +import mc.protocol.packets.client.ClientSettingsPacket; import mc.protocol.packets.client.HandshakePacket; import mc.protocol.packets.client.LoginStartPacket; import mc.protocol.packets.client.StatusServerRequestPacket; @@ -48,7 +49,7 @@ public enum State { ), PLAY(3, // server bound - Map.of(), + Map.of(0x04, ClientSettingsPacket.class), // client bound Map.of(JoinGamePacket.class, 0x23) ); diff --git a/protocol/src/main/java/mc/protocol/packets/client/ClientSettingsPacket.java b/protocol/src/main/java/mc/protocol/packets/client/ClientSettingsPacket.java new file mode 100644 index 0000000..680db2c --- /dev/null +++ b/protocol/src/main/java/mc/protocol/packets/client/ClientSettingsPacket.java @@ -0,0 +1,94 @@ +package mc.protocol.packets.client; + +import lombok.*; +import mc.protocol.ChatMode; +import mc.protocol.MainHand; +import mc.protocol.io.NetByteBuf; +import mc.protocol.packets.ClientSidePacket; + +/** + * Client settings packet. + * + *
Структура пакета
+ *+ * | FIELD | TYPE | NOTES | + * |-------------------- |---------------|---------------------------------------------------| + * | Locale | String (16) | например en_gb | + * | View Distance | Byte | Дистанция отрисовки со стороны Клиента, в чанках. | + * | Chat Mode | VarInt | 0: enabled | + * | | | 1: commands only | + * | | | 2: hidden | + * | | | [1] | + * | Chat Colors | Boolean | “Colors” multiplayer setting (???) | + * | Displayed Skin Parts | Unsigned Byte | битовая маска отображения скина. См. ниже | + * | Main Hand | VarInt | 0: Left | + * | | | 1: Right | + * + * [1] - Processing chat + *+ * + *
Биты "Displayed Skin Parts"
+ *+ * Bit 0 (0x01): Плащ (Cape) + * Bit 1 (0x02): Рубашка (Jacket) + * Bit 2 (0x04): Левый рукав (Left Sleeve) + * Bit 3 (0x08): Правый рукав (Right Sleeve) + * Bit 4 (0x10): Левая штанина (Left Pants Leg) + * Bit 5 (0x20): Правая штанина (Right Pants Leg) + * Bit 6 (0x40): Шлем (Hat) + *+ * + * @see Client Settings + */ +@NoArgsConstructor +@Getter +@EqualsAndHashCode +@ToString +public class ClientSettingsPacket implements ClientSidePacket { + + private String locale; + private int viewDistance; + private ChatMode chatMode; + private boolean chatColors; + @SuppressWarnings("java:S116") + private int $displayedSkinPartsBitMask; + private MainHand mainHand; + + @Override + public void readSelf(NetByteBuf netByteBuf) { + this.locale = netByteBuf.readString(16); + this.viewDistance = netByteBuf.readByte(); + this.chatMode = ChatMode.valueById(netByteBuf.readVarInt()); + this.chatColors = netByteBuf.readBoolean(); + this.$displayedSkinPartsBitMask = netByteBuf.readUnsignedByte(); + this.mainHand = MainHand.valueById(netByteBuf.readVarInt()); + } + + public boolean isCapeEnabled() { + return ($displayedSkinPartsBitMask & 0x01) > 0; + } + + public boolean isJacketEnabled() { + return ($displayedSkinPartsBitMask & 0x02) > 0; + } + + public boolean isLeftSleeveEnabled() { + return ($displayedSkinPartsBitMask & 0x04) > 0; + } + + public boolean isRightSleeveEnabled() { + return ($displayedSkinPartsBitMask & 0x08) > 0; + } + + public boolean isLeftPantsEnabled() { + return ($displayedSkinPartsBitMask & 0x10) > 0; + } + + public boolean isRightPantsEnabled() { + return ($displayedSkinPartsBitMask & 0x20) > 0; + } + + public boolean isHatEnabled() { + return ($displayedSkinPartsBitMask & 0x40) > 0; + } +}