From 9ccb9a6221b3bca04a53292b9985d11e67d09625 Mon Sep 17 00:00:00 2001 From: DmitriyMX Date: Sat, 8 May 2021 04:48:28 +0300 Subject: [PATCH] TeamsPacket --- protocol/src/main/java/mc/protocol/State.java | 1 + .../main/java/mc/protocol/io/NetByteBuf.java | 5 + .../protocol/packets/server/TeamsPacket.java | 119 ++++++++++++++++++ .../mc/protocol/utils/TeamsCollisionRule.java | 15 +++ .../java/mc/protocol/utils/TeamsMode.java | 16 +++ .../utils/TeamsNameTagVisibility.java | 15 +++ .../main/java/mc/server/PacketHandler.java | 32 +++-- 7 files changed, 194 insertions(+), 9 deletions(-) create mode 100644 protocol/src/main/java/mc/protocol/packets/server/TeamsPacket.java create mode 100644 protocol/src/main/java/mc/protocol/utils/TeamsCollisionRule.java create mode 100644 protocol/src/main/java/mc/protocol/utils/TeamsMode.java create mode 100644 protocol/src/main/java/mc/protocol/utils/TeamsNameTagVisibility.java diff --git a/protocol/src/main/java/mc/protocol/State.java b/protocol/src/main/java/mc/protocol/State.java index e46a2d1..f2bcbb3 100644 --- a/protocol/src/main/java/mc/protocol/State.java +++ b/protocol/src/main/java/mc/protocol/State.java @@ -57,6 +57,7 @@ public enum State { PingPacket.class, 0x1F, JoinGamePacket.class, 0x23, ScoreboardDisplayPacket.class, 0x3B, + TeamsPacket.class, 0x44, SpawnPositionPacket.class, 0x46, ChunkDataPacket.class, 0x20, PlayerAbilitiesPacket.class,0x2C, diff --git a/protocol/src/main/java/mc/protocol/io/NetByteBuf.java b/protocol/src/main/java/mc/protocol/io/NetByteBuf.java index b76ba17..f851077 100644 --- a/protocol/src/main/java/mc/protocol/io/NetByteBuf.java +++ b/protocol/src/main/java/mc/protocol/io/NetByteBuf.java @@ -99,6 +99,11 @@ public class NetByteBuf extends ByteBuf { } public void writeString(String string) { + if (string == null) { + writeVarInt(0); + return; + } + byte[] buf = string.getBytes(StandardCharsets.UTF_8); if (buf.length > Short.MAX_VALUE) { diff --git a/protocol/src/main/java/mc/protocol/packets/server/TeamsPacket.java b/protocol/src/main/java/mc/protocol/packets/server/TeamsPacket.java new file mode 100644 index 0000000..8c223c1 --- /dev/null +++ b/protocol/src/main/java/mc/protocol/packets/server/TeamsPacket.java @@ -0,0 +1,119 @@ +package mc.protocol.packets.server; + +import lombok.Data; +import mc.protocol.io.NetByteBuf; +import mc.protocol.packets.ServerSidePacket; +import mc.protocol.utils.TeamsCollisionRule; +import mc.protocol.utils.TeamsMode; +import mc.protocol.utils.TeamsNameTagVisibility; + +import java.util.ArrayList; +import java.util.List; + +/** + * Teams packet. + * + *

Структура пакета

+ *
+ * | FIELD       | TYPE        | NOTES                                                 |
+ * |------------ |-------------|-------------------------------------------------------|
+ * | Team Name   | String (16) | Уникальное название команды (совместно со scoreboard) |
+ * | Mode        | Byte        | Режим. Определяет остальые поля пакета                |
+ * | Data Fields | -           | Определяется "Mode"                                   |
+ * 
+ * + *

Варианты "Mode"

+ *
+ * | MODE                             | DATA FIELD          | TYPE                 | NOTES                                             |
+ * | VALUE | DESCRIPTION              |                     |                      |                                                   |
+ * |-------|--------------------------|---------------------|----------------------|---------------------------------------------------|
+ * | 0     | create team              | Team Display Name   | String (32)          |                                                   |
+ * |       |                          | Team Prefix         | String (16)          | Отображается перед именем игроков текущей команды |
+ * |       |                          | Team Suffix         | String (16)          | Отображается после имени игроков текущей команды  |
+ * |       |                          | Friendly Flags      | Byte                 | Битовая маска:                                    |
+ * |       |                          |                     |                      | 0x01 - разрешён friendly fire                     |
+ * |       |                          |                     |                      | 0x02 - могут видеть невидимок своей команды       |
+ * |       |                          | Name Tag Visibility | String (32)          | фиксированные значения:                           |
+ * |       |                          |                     |                      | - always                                          |
+ * |       |                          |                     |                      | - hideForOtherTeams                               |
+ * |       |                          |                     |                      | - hideForOwnTeam                                  |
+ * |       |                          |                     |                      | - never                                           |
+ * |       |                          | Collision Rule      | String (32)          | фиксированные значения:                           |
+ * |       |                          |                     |                      | - always                                          |
+ * |       |                          |                     |                      | - pushOtherTeams                                  |
+ * |       |                          |                     |                      | - pushOwnTeam                                     |
+ * |       |                          |                     |                      | - never                                           |
+ * |       |                          | Color               | Byte                 | For colors, the same Chat colors (0-15).          |
+ * |       |                          |                     |                      | -1 indicates RESET/no color.                      |
+ * |       |                          | Entity Count        | VarInt               | Количество элементов в поле "Entities"            |
+ * |       |                          | Entities            | Array of String (40) | Уникальные идентификаторы участников команды.     |
+ * |       |                          |                     |                      | Для Игроков - это Имена                           |
+ * |       |                          |                     |                      | Для любых других сущностей - это UUID             |
+ * | 1     | remove team              | -                   | -                    | удаление текущей команды                          |
+ * | 2     | update team info         | Team Display Name   | String (32)          |                                                   |
+ * |       |                          | Team Prefix         | String (16)          | (см. выше)                                        |
+ * |       |                          | Team Suffix         | String (16)          | (см. выше)                                        |
+ * |       |                          | Friendly Flags      | Byte                 | (см. выше)                                        |
+ * |       |                          | Name Tag Visibility | String (32)          | (см. выше)                                        |
+ * |       |                          | Collision Rule      | String (32)          | (см. выше)                                        |
+ * |       |                          | Color               | Byte                 | (см. выше)                                        |
+ * | 3     | add players to team      | Entity Count        | VarInt               | (см. выше)                                        |
+ * |       |                          | Entities            | Array of String (40) | (см. выше)                                        |
+ * | 4     | remove players from team | Entity Count        | VarInt               | (см. выше)                                        |
+ * |       |                          | Entities            | Array of String (40) | (см. выше)                                        |
+ * 
+ * + * @see Teams + */ +@Data +public class TeamsPacket implements ServerSidePacket { + + private final List members = new ArrayList<>(); + + private String name; + private TeamsMode mode; + + private String displayName; + private String prefix; + private String suffix; + private TeamsNameTagVisibility nameTagVisibility; + private TeamsCollisionRule collisionRule; + private int color; + + @Override + public void writeSelf(NetByteBuf netByteBuf) { + netByteBuf.writeString(this.name); + netByteBuf.writeByte(this.mode.getCode()); + + switch (this.mode) { + case CREATE: + netByteBuf.writeString(this.displayName); + netByteBuf.writeString(this.prefix); + netByteBuf.writeString(this.suffix); + netByteBuf.writeByte(0); // Friendly Flags + netByteBuf.writeString(this.nameTagVisibility.getCode()); + netByteBuf.writeString(this.collisionRule.getCode()); + netByteBuf.writeByte(this.color); + netByteBuf.writeVarInt(this.members.size()); + this.members.forEach(netByteBuf::writeString); + break; + case UPDATE: + netByteBuf.writeString(this.displayName); + netByteBuf.writeString(this.prefix); + netByteBuf.writeString(this.suffix); + netByteBuf.writeByte(0); // Friendly Flags + netByteBuf.writeString(this.nameTagVisibility.getCode()); + netByteBuf.writeString(this.collisionRule.getCode()); + netByteBuf.writeByte(this.color); + break; + case ADD_MEMBER: + case REMOVE_MEMBER: + netByteBuf.writeVarInt(this.members.size()); + this.members.forEach(netByteBuf::writeString); + break; + case REMOVE: + default: + break; + } + } +} diff --git a/protocol/src/main/java/mc/protocol/utils/TeamsCollisionRule.java b/protocol/src/main/java/mc/protocol/utils/TeamsCollisionRule.java new file mode 100644 index 0000000..7a90d8e --- /dev/null +++ b/protocol/src/main/java/mc/protocol/utils/TeamsCollisionRule.java @@ -0,0 +1,15 @@ +package mc.protocol.utils; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public enum TeamsCollisionRule { + ALWAYS("always"), + PUSH_OTHER_TEAMS("pushOtherTeams"), + PUSH_OWN_TEAM("pushOwnTeam"), + NEVER("never"); + + @Getter + private final String code; +} diff --git a/protocol/src/main/java/mc/protocol/utils/TeamsMode.java b/protocol/src/main/java/mc/protocol/utils/TeamsMode.java new file mode 100644 index 0000000..5a0b427 --- /dev/null +++ b/protocol/src/main/java/mc/protocol/utils/TeamsMode.java @@ -0,0 +1,16 @@ +package mc.protocol.utils; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public enum TeamsMode { + CREATE(0), + REMOVE(1), + UPDATE(2), + ADD_MEMBER(3), + REMOVE_MEMBER(4); + + @Getter + private final int code; +} diff --git a/protocol/src/main/java/mc/protocol/utils/TeamsNameTagVisibility.java b/protocol/src/main/java/mc/protocol/utils/TeamsNameTagVisibility.java new file mode 100644 index 0000000..5b8f348 --- /dev/null +++ b/protocol/src/main/java/mc/protocol/utils/TeamsNameTagVisibility.java @@ -0,0 +1,15 @@ +package mc.protocol.utils; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public enum TeamsNameTagVisibility { + ALWAYS("always"), + HIDE_FOR_OTHER_TEAMS("hideForOtherTeams"), + HIDE_FOR_OWN_TEAM("hideForOwnTeam"), + NEVER("never"); + + @Getter + private final String code; +} diff --git a/server/src/main/java/mc/server/PacketHandler.java b/server/src/main/java/mc/server/PacketHandler.java index a7ec96d..466418d 100644 --- a/server/src/main/java/mc/server/PacketHandler.java +++ b/server/src/main/java/mc/server/PacketHandler.java @@ -13,10 +13,7 @@ import mc.protocol.packets.client.LoginStartPacket; import mc.protocol.packets.client.StatusServerRequestPacket; import mc.protocol.packets.server.*; import mc.protocol.serializer.TextSerializer; -import mc.protocol.utils.Difficulty; -import mc.protocol.utils.GameMode; -import mc.protocol.utils.LevelType; -import mc.protocol.utils.ScoreboardPosition; +import mc.protocol.utils.*; import mc.server.config.Config; import org.apache.commons.io.IOUtils; @@ -69,15 +66,19 @@ public class PacketHandler { } public void onLoginStart(ConnectionContext context, LoginStartPacket loginStartPacket) { + UUID playerUuid = UUID.randomUUID(); + int playerEid = random.nextInt(); + String playerName = loginStartPacket.getName(); + var loginSuccessPacket = new LoginSuccessPacket(); - loginSuccessPacket.setUuid(UUID.randomUUID()); - loginSuccessPacket.setName(loginStartPacket.getName()); + loginSuccessPacket.setUuid(playerUuid); + loginSuccessPacket.setName(playerName); context.sendNow(loginSuccessPacket); context.setState(State.PLAY); var joinGamePacket = new JoinGamePacket(); - joinGamePacket.setEntityId(random.nextInt()); + joinGamePacket.setEntityId(playerEid); joinGamePacket.setGameMode(GameMode.SPECTATOR); joinGamePacket.setDimension(0/*Overworld*/); joinGamePacket.setDifficulty(Difficulty.PEACEFUL); @@ -126,11 +127,24 @@ public class PacketHandler { // --- Эксперименты --- // + TeamsPacket teamsPacket = new TeamsPacket(); + teamsPacket.setName("Score::List"); + teamsPacket.setMode(TeamsMode.CREATE); + teamsPacket.setDisplayName(teamsPacket.getName()); + teamsPacket.setNameTagVisibility(TeamsNameTagVisibility.NEVER); + teamsPacket.setCollisionRule(TeamsCollisionRule.NEVER); + teamsPacket.setColor(-1/*no color*/); + teamsPacket.getMembers().add(playerName); + + context.send(teamsPacket); + ScoreboardDisplayPacket scoreboardDisplayPacket = new ScoreboardDisplayPacket(); scoreboardDisplayPacket.setPosition(ScoreboardPosition.LIST); - scoreboardDisplayPacket.setName("Score::List"); + scoreboardDisplayPacket.setName(teamsPacket.getName()); - context.sendNow(scoreboardDisplayPacket); + context.send(scoreboardDisplayPacket); + + context.flushSending(); } private static String faviconToBase64(Path iconPath) {