Archived
0

refactoring: Packets

This commit is contained in:
2021-05-10 03:15:11 +03:00
parent 70d8efe421
commit f9a71250b1
39 changed files with 184 additions and 253 deletions

View File

@@ -1,100 +0,0 @@
package mc.protocol;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import mc.protocol.packets.ClientSidePacket;
import mc.protocol.packets.Packet;
import mc.protocol.packets.KeepAlivePacket;
import mc.protocol.packets.ServerSidePacket;
import mc.protocol.packets.client.*;
import mc.protocol.packets.server.*;
import javax.annotation.Nullable;
import java.util.Collections;
import java.util.Map;
@RequiredArgsConstructor
public enum State {
HANDSHAKING(-1,
// client side
Map.of(0x00, HandshakePacket.class)
),
STATUS(1,
// client side
Map.of(
0x00, StatusServerRequestPacket.class,
0x01, KeepAlivePacket.class
),
// server side
Map.of(
StatusServerResponse.class, 0x00,
KeepAlivePacket.class, 0x01
)
),
LOGIN(2,
// server bound
Map.of(0x00, LoginStartPacket.class),
// client bound
Map.of(
DisconnectPacket.class, 0x00,
LoginSuccessPacket.class, 0x02
)
),
PLAY(3,
// server bound
Map.of(
0x00, TeleportConfirmPacket.class,
0x04, ClientSettingsPacket.class,
0x09, PluginMessagePacket.class,
0x0B, KeepAlivePacket.class,
0x0D, PlayerPositionPacket.class,
0x0E, CPlayerPositionAndLookPacket.class,
0x0F, PlayerLookPacket.class,
0x15, EntityActionPacket.class
),
// client bound
Map.of(
KeepAlivePacket.class, 0x1F,
ChunkDataPacket.class, 0x20,
JoinGamePacket.class, 0x23,
PlayerAbilitiesPacket.class,0x2C,
SPlayerPositionAndLookPacket.class, 0x2F,
SpawnPositionPacket.class, 0x46
)
);
@Nullable
public static State getById(int id) {
for (State state : State.values()) {
if (state.id == id) {
return state;
}
}
return null;
}
@Getter
private final int id;
@Getter
private final Map<Integer, Class<? extends ClientSidePacket>> clientSidePackets;
private final Map<Class<? extends ServerSidePacket>, Integer> serverSidePackets;
State(int id, Map<Integer, Class<? extends ClientSidePacket>> clientSidePackets) {
this.id = id;
this.clientSidePackets = clientSidePackets;
this.serverSidePackets = Collections.emptyMap();
}
@Nullable
public Class<? extends ClientSidePacket> getClientSidePacketById(int id) {
return clientSidePackets == null ? null : clientSidePackets.get(id);
}
@Nullable
public Integer getServerSidePacketId(Class<? extends Packet> clazz) {
return serverSidePackets == null ? null : serverSidePackets.get(clazz);
}
}

View File

@@ -1,24 +0,0 @@
package mc.protocol.model;
import lombok.AllArgsConstructor;
import lombok.Data;
@AllArgsConstructor
@Data
public class Location {
private double x;
private double y;
private double z;
public int getIntX() {
return (int) x;
}
public int getIntZ() {
return (int) z;
}
public Location toChunkXZ() {
return new Location(this.getIntX() >> 4, 0d, this.getIntZ() >> 4);
}
}

View File

@@ -1,11 +0,0 @@
package mc.protocol.model;
import lombok.AllArgsConstructor;
import lombok.Data;
@AllArgsConstructor
@Data
public class Look {
private float yaw;
private float pitch;
}

View File

@@ -1,50 +0,0 @@
package mc.protocol.model;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import lombok.RequiredArgsConstructor;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import mc.protocol.model.text.Text;
import java.util.List;
@Accessors(fluent = true)
@Getter
@Setter
@ToString
public class ServerInfo {
private final Version version = new Version();
private final Players players = new Players();
private Text description;
private String favicon;
@Getter
@Setter
@ToString
public static class Version {
private String name;
private int protocol;
}
@Getter
@Setter
@ToString
public static class Players {
private int max;
private int online;
private List<SamplePlayer> sample;
}
@RequiredArgsConstructor
@Getter
@EqualsAndHashCode
@ToString
public static class SamplePlayer {
private final String id;
private final String name;
}
}

View File

@@ -1,151 +0,0 @@
package mc.protocol.model.text;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.Getter;
import lombok.experimental.Accessors;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
@Accessors(fluent = true)
@AllArgsConstructor
@Data
public class Text {
private TextColor color;
private TextStyle style;
private String content;
private List<Text> children;
public static Text of(String string) {
return new Text(null, null, string, null);
}
public static Text of(TextColor color, String string) {
return new Text(color, null, string, null);
}
public static Text of(TextStyle style, String string) {
return new Text(null, style, string, null);
}
public static Text of(TextColor color, TextStyle style, String string) {
return new Text(color, style, string, null);
}
public static Builder builder() {
return new Builder();
}
@NoArgsConstructor
@ToString
public static class Builder {
@Getter(onMethod = @__(@Nullable))
private StringBuilder contentBuilder;
private TextStyle.Builder styleBuilder;
private TextColor color;
private List<Text> children;
public Builder append(char content) {
if (this.contentBuilder == null) {
this.contentBuilder = new StringBuilder();
}
this.contentBuilder.append(content);
return this;
}
public Builder append(String content) {
if (this.contentBuilder == null) {
this.contentBuilder = new StringBuilder(content);
} else {
this.contentBuilder.append(content);
}
return this;
}
public Builder append(Text text) {
if (children == null) {
children = new ArrayList<>();
}
children.add(text);
return this;
}
public Builder style(TextStyle style) {
//@formatter:off
if (style.bold() != null) bold(style.bold());
if (style.italic() != null) italic(style.italic());
if (style.underline() != null) underline(style.underline());
if (style.strikethrough() != null) strikethrough(style.strikethrough());
if (style.obfuscated() != null) obfuscated(style.obfuscated());
//@formatter:on
return this;
}
public Builder color(TextColor color) {
this.color = color;
return this;
}
public Builder bold(Boolean bold) {
if (this.styleBuilder == null) {
this.styleBuilder = TextStyle.builder();
}
this.styleBuilder.bold(bold);
return this;
}
public Builder italic(Boolean italic) {
if (this.styleBuilder == null) {
this.styleBuilder = TextStyle.builder();
}
this.styleBuilder.italic(italic);
return this;
}
public Builder underline(Boolean underline) {
if (this.styleBuilder == null) {
this.styleBuilder = TextStyle.builder();
}
this.styleBuilder.underline(underline);
return this;
}
public Builder strikethrough(Boolean strikethrough) {
if (this.styleBuilder == null) {
this.styleBuilder = TextStyle.builder();
}
this.styleBuilder.strikethrough(strikethrough);
return this;
}
public Builder obfuscated(Boolean obfuscated) {
if (this.styleBuilder == null) {
this.styleBuilder = TextStyle.builder();
}
this.styleBuilder.obfuscated(obfuscated);
return this;
}
public Text build() {
return new Text(
color,
styleBuilder == null ? null : styleBuilder.build(),
contentBuilder == null ? null : contentBuilder.toString(),
children);
}
}
}

View File

@@ -1,30 +0,0 @@
package mc.protocol.model.text;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@Getter
public enum TextColor {
//@formatter:off
BLACK ("black", '0'),
DARK_BLUE ("dark_blue", '1'),
DARK_GREEN ("dark_green", '2'),
DARK_AQUA ("dark_aqua", '3'),
DARK_RED ("dark_red", '4'),
DARK_PUEPLE("dark_purple", '5'),
GOLD ("gold", '6'),
GRAY ("gray", '7'),
DARK_GRAY ("dark_gray", '8'),
BLUE ("blue", '9'),
GREEN ("green", 'a'),
AQUA ("aqua", 'b'),
RED ("red", 'c'),
PURPLE ("light_purple",'d'),
YELLOW ("yellow", 'e'),
WHITE ("white", 'f');
//@formatter:on
private final String name;
private final char code;
}

View File

@@ -1,82 +0,0 @@
package mc.protocol.model.text;
import lombok.*;
import lombok.experimental.Accessors;
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@Accessors(fluent = true)
@Data
@SuppressWarnings("java:S1845")
public class TextStyle {
public static final TextStyle BOLD = new TextStyle(true, null, null, null, null);
public static final TextStyle ITALIC = new TextStyle(null, true, null, null, null);
public static final TextStyle UNDERLINE = new TextStyle(null, null, true, null, null);
public static final TextStyle STRIKETHOUGH = new TextStyle(null, null, null, true, null);
public static final TextStyle OBFUSCATED = new TextStyle(null, null, null, null, true);
public static final TextStyle RESET = new TextStyle(false, false, false, false, false);
public static final TextStyle NONE = new TextStyle(null, null, null, null, null);
private Boolean bold;
private Boolean italic;
private Boolean underline;
private Boolean strikethrough;
private Boolean obfuscated;
public static Builder builder() {
return new TextStyle.Builder();
}
@NoArgsConstructor
@ToString
public static class Builder {
private Boolean bold;
private Boolean italic;
private Boolean underline;
private Boolean strikethrough;
private Boolean obfuscated;
public Builder bold(Boolean bold) {
this.bold = bold;
return this;
}
public Builder italic(Boolean italic) {
this.italic = italic;
return this;
}
public Builder underline(Boolean underline) {
this.underline = underline;
return this;
}
public Builder strikethrough(Boolean strikethrough) {
this.strikethrough = strikethrough;
return this;
}
public Builder obfuscated(Boolean obfuscated) {
this.obfuscated = obfuscated;
return this;
}
public Builder merge(TextStyle style) {
//@formatter:off
if (style.bold != null) this.bold = style.bold;
if (style.italic != null) this.italic = style.italic;
if (style.underline != null) this.underline = style.underline;
if (style.strikethrough != null) this.strikethrough = style.strikethrough;
if (style.obfuscated != null) this.obfuscated = style.obfuscated;
//@formatter:on
return this;
}
public TextStyle build() {
return new TextStyle(bold, italic, underline, strikethrough, obfuscated);
}
}
}

View File

@@ -1,21 +0,0 @@
package mc.protocol.packets;
import mc.protocol.io.NetByteBuf;
public abstract class EmptyPacket implements ClientSidePacket, ServerSidePacket {
@Override
public void readSelf(NetByteBuf netByteBuf) {
// empty
}
@Override
public void writeSelf(NetByteBuf netByteBuf) {
// empty
}
@Override
public void passivate() {
// pass
}
}

View File

@@ -1,46 +0,0 @@
package mc.protocol.packets;
import lombok.Data;
import mc.protocol.io.NetByteBuf;
/**
* Пинг-пакет.
*
* <p>Эхо-пакет, которым проверяется качество соединения между <b>Клиентом</b> и <b>Сервером</b>.</p>
*
* <p>По спецификации:</p>
* <oi>
* <li>если <b>Сервер</b> не ответил <b>Клиенту</b> в течении 20 секунд, <b>Клиент</b> отключается
* и выдаёт ошибку <i>"Timed out"</i>.</li>
* <li>если <b>Клиент</b> не отвечает <b>Серверу</b> в течении 30 секунд, <b>Сервер</b> отключает <b>Клиента</b>.</li>
* </oi>
*
* <p>Структура пакета</p>
* <pre>
* | FIELD | TYPE | NOTES |
* |---------|------|------------------------|
* | Payload | Long | Любое уникальное число |
* </pre>
*
* @see <a href="https://wiki.vg/index.php?title=Protocol&oldid=7368#Keep_Alive">Keep Alive</a>
*/
@Data
public class KeepAlivePacket implements ClientSidePacket, ServerSidePacket {
private Long payload;
@Override
public void readSelf(NetByteBuf netByteBuf) {
payload = netByteBuf.readLong();
}
@Override
public void passivate() {
this.payload = null;
}
@Override
public void writeSelf(NetByteBuf netByteBuf) {
netByteBuf.writeLong(payload);
}
}

View File

@@ -1,64 +0,0 @@
package mc.protocol.packets.client;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import mc.protocol.io.NetByteBuf;
import mc.protocol.model.Location;
import mc.protocol.model.Look;
import mc.protocol.packets.ClientSidePacket;
/**
* Клиент сообщает о движении и повороте головы Игрока.
*
* <p>Структура пакета</p>
* <pre>
* | FIELD | TYPE | NOTES |
* |-----------|---------|------------------------------------------------------------|
* | X | Double | Абсолютная позиция по X |
* | Y | Double | Абсолютная позиция по Y. |
* | | | Имеется ввиду позиция ног. Голова находиться выше на 1.62f |
* | Z | Double | Абсолютная позиция по Z |
* | Yaw | Float | Абсолютный поворот головы по OX, в градусах |
* | Pitch | Float | Абсолютный поворот головы по OY, в градусах |
* | On Ground | Boolean | true, если Игрок находится на земле |
* </pre>
*
* @see <a href="https://wiki.vg/index.php?title=Protocol&oldid=14204#Player_Position_And_Look_.28serverbound.29">Player Position And Look (serverbound)</a>
*/
@NoArgsConstructor
@Getter
@EqualsAndHashCode
@ToString
public class CPlayerPositionAndLookPacket implements ClientSidePacket {
private Location position;
private Look look;
private boolean onGround;
@Override
public void readSelf(NetByteBuf netByteBuf) {
double x = netByteBuf.readDouble();
double y = netByteBuf.readDouble();
double z = netByteBuf.readDouble();
this.position = new Location(x, y, z);
float yaw = netByteBuf.readFloat();
float pitch = netByteBuf.readFloat();
this.look = new Look(yaw, pitch);
this.onGround = netByteBuf.readBoolean();
}
@Override
public void passivate() {
this.position = null;
this.look = null;
this.onGround = false;
}
public double getYPositionHead() {
return this.position.getY() + 1.62f;
}
}

View File

@@ -1,104 +0,0 @@
package mc.protocol.packets.client;
import lombok.*;
import mc.protocol.utils.ChatMode;
import mc.protocol.utils.MainHand;
import mc.protocol.io.NetByteBuf;
import mc.protocol.packets.ClientSidePacket;
/**
* Client settings packet.
*
* <p>Структура пакета</p>
* <pre>
* | 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] - <a href="https://wiki.vg/index.php?title=Chat&oldid=13165#Processing_chat">Processing chat</a>
* </pre>
*
* <p>Биты "Displayed Skin Parts"</p>
* <pre>
* 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)
* </pre>
*
* @see <a href="https://wiki.vg/index.php?title=Protocol&oldid=14204#Client_Settings">Client Settings</a>
*/
@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());
}
@Override
public void passivate() {
this.locale = null;
this.viewDistance = 0;
this.chatMode = null;
this.chatColors = false;
this.$displayedSkinPartsBitMask = 0;
this.mainHand = null;
}
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;
}
}

View File

@@ -1,52 +0,0 @@
package mc.protocol.packets.client;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import mc.protocol.io.NetByteBuf;
import mc.protocol.packets.ClientSidePacket;
import mc.protocol.utils.EntityActionAction;
/**
* Entity Action packet.
*
* <p>Структура пакета</p>
* <pre>
* | FIELD | TYPE | NOTES |
* |------------|--------|-------------------------------------------|
* | Entity ID | VarInt | ID игрока |
* | Action ID | VarInt | ID действия |
* | Jump Boost | VarInt | Используется только при "Action ID" = 5. |
* | | | В этом случае значение будет от 0 до 100. |
* | | | В остальных случаях значение 0. |
* </pre>
*
* @see <a href="https://wiki.vg/index.php?title=Protocol&oldid=14204#Entity_Action" target="_top">Entity Action</a>
*/
@NoArgsConstructor
@Getter
@EqualsAndHashCode
@ToString
public class EntityActionPacket implements ClientSidePacket {
private Integer entityId;
private EntityActionAction action;
private Integer jumpBoost;
@Override
public void readSelf(NetByteBuf netByteBuf) {
this.entityId = netByteBuf.readVarInt();
int actionId = netByteBuf.readVarInt();
this.jumpBoost = netByteBuf.readVarInt();
this.action = EntityActionAction.valueOfCode(actionId);
}
@Override
public void passivate() {
this.entityId = null;
this.action = null;
this.jumpBoost = null;
}
}

View File

@@ -1,58 +0,0 @@
package mc.protocol.packets.client;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import mc.protocol.State;
import mc.protocol.io.NetByteBuf;
import mc.protocol.packets.ClientSidePacket;
/**
* Handshake packet.
*
* <p>Данный пакет заставляет сервер переключить текущий {@link State}</p>
*
* <p>Структура пакета</p>
* <pre>
* | FIELD | TYPE | NOTES |
* |------------------|----------------|----------------------------------------------|
* | Protocol version | VarInt | Версия протокола [1] |
* | Server address | Stirng | Hostname или IP |
* | Server port | Unsigned Short | Порт сервера |
* | Next stage | VarInt | ID State на который необходимо переключиться |
*
* [1] - <a href="https://wiki.vg/Protocol_version_numbers" target="_top">Protocol version numbers</a>
* </pre>
*
* @see <a href="https://wiki.vg/index.php?title=Protocol&oldid=7368#Handshake" target="_top">Handshake</a>
* @see State
*/
@NoArgsConstructor
@Getter
@EqualsAndHashCode
@ToString
public class HandshakePacket implements ClientSidePacket {
private int protocolVersion;
private String host;
private int port;
private State nextState;
@Override
public void readSelf(NetByteBuf netByteBuf) {
protocolVersion = netByteBuf.readVarInt();
host = netByteBuf.readString(255);
port = netByteBuf.readUnsignedShort();
nextState = State.getById(netByteBuf.readVarInt());
}
@Override
public void passivate() {
this.protocolVersion = 0;
this.host = null;
this.port = 0;
this.nextState = null;
}
}

View File

@@ -1,42 +0,0 @@
package mc.protocol.packets.client;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import mc.protocol.io.NetByteBuf;
import mc.protocol.packets.ClientSidePacket;
/**
* Login start packet.
*
* <p>Начало авторизации.</p>
*
* <p>Структура пакета</p>
* <pre>
* | FIELD | TYPE | NOTES |
* |-------|--------|------------------|
* | Name | String | Имя/Логин игрока |
* </pre>
*
* @see <a href="https://wiki.vg/index.php?title=Protocol&oldid=7368#Login_Start" target="_top">Login start</a>
*/
@NoArgsConstructor
@Getter
@EqualsAndHashCode
@ToString
public class LoginStartPacket implements ClientSidePacket {
private String name;
@Override
public void readSelf(NetByteBuf netByteBuf) {
this.name = netByteBuf.readString();
}
@Override
public void passivate() {
this.name = null;
}
}

View File

@@ -1,48 +0,0 @@
package mc.protocol.packets.client;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import mc.protocol.io.NetByteBuf;
import mc.protocol.model.Look;
import mc.protocol.packets.ClientSidePacket;
/**
* Клиент сообщает о повороте головы Игрока.
*
* <p>Структура пакета</p>
* <pre>
* | FIELD | TYPE | NOTES |
* |-----------|---------|---------------------------------------------|
* | Yaw | Float | Абсолютный поворот головы по OX, в градусах |
* | Pitch | Float | Абсолютный поворот головы по OY, в градусах |
* | On Ground | Boolean | true, если Игрок находится на земле |
* </pre>
*
* @see <a href="https://wiki.vg/index.php?title=Protocol&oldid=14204#Player_Look">Player Look</a>
*/
@NoArgsConstructor
@Getter
@EqualsAndHashCode
@ToString
public class PlayerLookPacket implements ClientSidePacket {
private Look look;
private boolean onGround;
@Override
public void readSelf(NetByteBuf netByteBuf) {
float yaw = netByteBuf.readFloat();
float pitch = netByteBuf.readFloat();
this.look = new Look(yaw, pitch);
this.onGround = netByteBuf.readBoolean();
}
@Override
public void passivate() {
this.look = null;
this.onGround = false;
}
}

View File

@@ -1,55 +0,0 @@
package mc.protocol.packets.client;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import mc.protocol.io.NetByteBuf;
import mc.protocol.model.Location;
import mc.protocol.packets.ClientSidePacket;
/**
* Клиент сообщает о движении Игрока.
*
* <p>Структура пакета</p>
* <pre>
* | FIELD | TYPE | NOTES |
* |-----------|---------|-------------------------------------|
* | X | Double | Абсолютная позиция по X |
* | Feet Y | Double | Абсолютная позиция ног по Y. |
* | | | Голова находиться выше на 1.62f |
* | Z | Double | Абсолютная позиция по Z |
* | On Ground | Boolean | true, если Игрок находится на земле |
* </pre>
*
* @see <a href="https://wiki.vg/index.php?title=Protocol&oldid=14204#Player_Position">Player Position</a>
*/
@NoArgsConstructor
@Getter
@EqualsAndHashCode
@ToString
public class PlayerPositionPacket implements ClientSidePacket {
private Location position;
private boolean onGround;
@Override
public void readSelf(NetByteBuf netByteBuf) {
double x = netByteBuf.readDouble();
double y = netByteBuf.readDouble();
double z = netByteBuf.readDouble();
this.position = new Location(x, y, z);
this.onGround = netByteBuf.readBoolean();
}
@Override
public void passivate() {
this.position = null;
this.onGround = false;
}
public double getYPositionHead() {
return this.position.getY() + 1.62f;
}
}

View File

@@ -1,48 +0,0 @@
package mc.protocol.packets.client;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import mc.protocol.io.NetByteBuf;
import mc.protocol.packets.ClientSidePacket;
/**
* Plugin Message packet.
*
* <p>Канал связи для модов и плагинов.</p>
*
* <p>Структура пакета</p>
* <pre>
* | FIELD | TYPE | NOTES |
* |--------------|-------------|------------------|
* | Channel name | String (20) | Название канала |
* | Data | Byte array | Любые данные |
* </pre>
*
* @see <a href="https://wiki.vg/index.php?title=Protocol&oldid=14204#Plugin_Message_.28serverbound.29">Plugin Message (serverbound)</a>
* @see <a href="https://wiki.vg/index.php?title=Plugin_channels&oldid=14089">Plugin channels</a>
* @see <a href="https://dinnerbone.com/blog/2012/01/13/minecraft-plugin-channels-messaging/">Minecraft Plugin Channels + Messaging</a>
*/
@NoArgsConstructor
@Getter
@EqualsAndHashCode
@ToString
public class PluginMessagePacket implements ClientSidePacket {
private String channelName;
private byte[] rawData;
@Override
public void readSelf(NetByteBuf netByteBuf) {
this.channelName = netByteBuf.readString(20);
this.rawData = new byte[netByteBuf.readableBytes()];
netByteBuf.readBytes(this.rawData);
}
@Override
public void passivate() {
this.channelName = null;
this.rawData = null;
}
}

View File

@@ -1,18 +0,0 @@
package mc.protocol.packets.client;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
import mc.protocol.packets.EmptyPacket;
/**
* Status server packet, request.
*
* <p>Клиент запрашивает получение информации о сервере</p>
*/
@NoArgsConstructor
@EqualsAndHashCode(callSuper = false)
@ToString
public class StatusServerRequestPacket extends EmptyPacket {
}

View File

@@ -1,41 +0,0 @@
package mc.protocol.packets.client;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import mc.protocol.io.NetByteBuf;
import mc.protocol.packets.ClientSidePacket;
import mc.protocol.packets.server.SPlayerPositionAndLookPacket;
/**
* Teleport сonfirm packet.
*
* <p>Структура пакета</p>
* <pre>
* | FIELD | TYPE | NOTES |
* |-------------|--------|-----------------------------------------------------------|
* | Teleport ID | VarInt | ID, который был выдан пакетом {@link SPlayerPositionAndLookPacket} |
* </pre>
*
* @see <a href="https://wiki.vg/index.php?title=Protocol&oldid=7368#Login_Start" target="_top">Login start</a>
* @see SPlayerPositionAndLookPacket
*/
@NoArgsConstructor
@Getter
@EqualsAndHashCode
@ToString
public class TeleportConfirmPacket implements ClientSidePacket {
private int teleportId;
@Override
public void readSelf(NetByteBuf netByteBuf) {
this.teleportId = netByteBuf.readVarInt();
}
@Override
public void passivate() {
this.teleportId = 0;
}
}

View File

@@ -1,108 +0,0 @@
package mc.protocol.packets.server;
import io.netty.buffer.Unpooled;
import lombok.Data;
import mc.protocol.io.NetByteBuf;
import mc.protocol.packets.ServerSidePacket;
/**
* Данные чанка.
*
* <p>Структура пакета</p>
* <pre>
* | FIELD | TYPE | NOTES |
* |--------------------------|------------- |------------------------------------------------------------------------------------|
* | Chunk X | Integer | Координаты чанка (координата блока, делённая на 16, округленная в меньшую сторону) |
* | Chunk Z | Integer | Координаты чанка (координата блока, делённая на 16, округленная в меньшую сторону) |
* | Is Full chunk | Boolean | См. Chunk Format |
* | Available Sections | VarInt | Битовая маска, где каждый бит - это часть чанка (0-15) |
* | Size of Data | VarInt | Размер поля "Data" |
* | Data | Byte array | Данные чанка. См. Chunk Format |
* | Number of block entities | VarInt | Количество элементов в поле "Block entities" |
* | Block entities | Array of NBT | Все сущности в чанке |
* </pre>
*
* @see <a href="https://wiki.vg/index.php?title=Protocol&oldid=14204#Chunk_Data">Chunk Data</a>
* @see <a href="https://wiki.vg/index.php?title=Chunk_Format&oldid=14135">Chunk Format</a>
*/
@Data
public class ChunkDataPacket implements ServerSidePacket {
private static NetByteBuf voidData;
private int x;
private int z;
@SuppressWarnings("java:S125")
@Override
public void writeSelf(NetByteBuf netByteBuf) {
netByteBuf.writeInt(x);
netByteBuf.writeInt(z);
/* Временное отключение кода
netByteBuf.writeBoolean(true); // Is Full chunk
netByteBuf.writeVarInt(0b11111111); // Available Sections
NetByteBuf data = new NetByteBuf(Unpooled.buffer());
// <Data>
for (int i = 0; i < 16; i++) {
NetByteBuf dataBuff = new NetByteBuf(Unpooled.wrappedBuffer(new byte[4096]));
NetByteBuf blockLight = new NetByteBuf(Unpooled.wrappedBuffer(new byte[2048]));
NetByteBuf skyLight = new NetByteBuf(Unpooled.wrappedBuffer(new byte[2048]));
NetByteBuf biomes = new NetByteBuf(Unpooled.wrappedBuffer(new byte[256]));
// <Chunk Section>
data.writeUnsignedByte(13); // Bits Per Block
// <Palette>
data.writeUnsignedByte(0); // Palette Length (for direct)
// <Palette Data/>
// </Palette>
data.writeVarInt(dataBuff.readableBytes()); // Data Array Length
data.writeBytes(dataBuff); // Data Array
data.writeBytes(blockLight); // Block Light
data.writeBytes(skyLight); // Sky Light
// </Chunk Section>
data.writeBytes(biomes); // Biomes
}
// </Data>
netByteBuf.writeVarInt(data.readableBytes()); // Size of Data
netByteBuf.writeBytes(data); // Data
netByteBuf.writeVarInt(0); // Number of block entities
// write NBT's
*/
netByteBuf.writeBytes(voidData);
voidData.resetReaderIndex();
voidData.resetWriterIndex();
}
static {
voidData = new NetByteBuf(Unpooled.buffer());
voidData.writeBoolean(true); // Is Full chunk
voidData.writeVarInt(0b11111111); // Available Sections
NetByteBuf data = new NetByteBuf(Unpooled.buffer());
for (int i = 0; i < 16; i++) {
NetByteBuf dataBuff = new NetByteBuf(Unpooled.wrappedBuffer(new byte[4096]));
NetByteBuf blockLight = new NetByteBuf(Unpooled.wrappedBuffer(new byte[2048]));
NetByteBuf skyLight = new NetByteBuf(Unpooled.wrappedBuffer(new byte[2048]));
NetByteBuf biomes = new NetByteBuf(Unpooled.wrappedBuffer(new byte[256]));
data.writeUnsignedByte(13);
data.writeUnsignedByte(0);
data.writeVarInt(dataBuff.readableBytes());
data.writeBytes(dataBuff);
data.writeBytes(blockLight);
data.writeBytes(skyLight);
data.writeBytes(biomes);
}
voidData.writeVarInt(data.readableBytes());
voidData.writeBytes(data);
voidData.writeVarInt(0);
voidData.markReaderIndex();
voidData.markWriterIndex();
}
}

View File

@@ -1,44 +0,0 @@
package mc.protocol.packets.server;
import lombok.Data;
import mc.protocol.State;
import mc.protocol.io.NetByteBuf;
import mc.protocol.model.text.Text;
import mc.protocol.packets.ServerSidePacket;
import mc.protocol.serializer.TextSerializer;
/**
* Diconnect packet.
*
* <p>Отключение клиента сервером с указанием причины.</p>
*
* <p>Структура пакета</p>
* <pre>
* | FIELD | TYPE | NOTES |
* |-------------|--------|----------------------------------|
* | JSON Reason | String | Причина отключения. Опционально. |
* </pre>
*
* <p>Пример JSON Reason</p>
* <pre>
* {
* "text": "foo"
* }
* </pre>
*
* @see <a href="https://wiki.vg/index.php?title=Protocol&oldid=7368#Disconnect_2" target="_top">Disconnect</a>
* @see State
*/
@Data
public class DisconnectPacket implements ServerSidePacket {
/**
* Причина отключения.
*/
private Text reason;
@Override
public void writeSelf(NetByteBuf netByteBuf) {
netByteBuf.writeString(TextSerializer.toJsonObject(reason).toString());
}
}

View File

@@ -1,59 +0,0 @@
package mc.protocol.packets.server;
import lombok.Data;
import mc.protocol.utils.Difficulty;
import mc.protocol.utils.GameMode;
import mc.protocol.utils.LevelType;
import mc.protocol.io.NetByteBuf;
import mc.protocol.packets.ServerSidePacket;
/**
* Join game packet.
*
* <p>Структура пакета</p>
* <pre>
* | FIELD | TYPE | NOTES |
* |--------------------|---------------|----------------------------------------------------------------------|
* | Entity ID | Integer | ID сущности (игрока) |
* | Gamemode | Unsigned Byte | 0: Survival |
* | | | 1: Creative |
* | | | 2: Adventure |
* | | | 3: Spectator |
* | | | Bit 3 (0x8) is the hardcore flag. |
* | Dimension | Integer | -1: Nether |
* | | | 0: Overworld |
* | | | 1: End |
* | Difficulty | Unsigned Byte | 0: peaceful |
* | | | 1: easy |
* | | | 2: normal |
* | | | 3: hard |
* | Max Players | Unsigned Byte | Когда-то использовался клиентом для |
* | | | отображения списка игроков. Теперь не используется |
* | Level Type | String (16) | Принимает одно из значений: |
* | | | default, flat, largeBiomes, amplified, default_1_1 |
* | Reduced Debug Info | Boolean | Если true, то Клиент отображает меньше отладочной информации (в F3?) |
* </pre>
*
* @see <a href="https://wiki.vg/index.php?title=Protocol&oldid=14204#Join_Game">Join Game</a>
*/
@Data
public class JoinGamePacket implements ServerSidePacket {
private int entityId;
private GameMode gameMode;
private int dimension;
private Difficulty difficulty;
private LevelType levelType;
private boolean reducedDebugInfo;
@Override
public void writeSelf(NetByteBuf netByteBuf) {
netByteBuf.writeInt(entityId);
netByteBuf.writeUnsignedByte(gameMode.getId());
netByteBuf.writeInt(dimension);
netByteBuf.writeUnsignedByte(difficulty.getId());
netByteBuf.writeUnsignedByte(0); // Max Players, unused
netByteBuf.writeString(levelType.getType());
netByteBuf.writeBoolean(reducedDebugInfo);
}
}

View File

@@ -1,33 +0,0 @@
package mc.protocol.packets.server;
import lombok.Data;
import mc.protocol.io.NetByteBuf;
import mc.protocol.packets.ServerSidePacket;
import java.util.UUID;
/**
* Подтверждение успешного логина.
*
* <p>Структура пакета</p>
* <pre>
* | FIELD | TYPE | NOTES |
* |----------|-------------|-------------------------------|
* | UUID | String (36) | Уникальный ID игрока |
* | Username | String (16) | Имя игрока, выданное сервером |
* </pre>
*
* @see <a href="https://wiki.vg/index.php?title=Protocol&oldid=14204#Login_Success">Login Success</a>
*/
@Data
public class LoginSuccessPacket implements ServerSidePacket {
private UUID uuid;
private String name;
@Override
public void writeSelf(NetByteBuf netByteBuf) {
netByteBuf.writeString(uuid.toString());
netByteBuf.writeString(name);
}
}

View File

@@ -1,60 +0,0 @@
package mc.protocol.packets.server;
import lombok.Data;
import mc.protocol.io.NetByteBuf;
import mc.protocol.packets.ServerSidePacket;
/**
* Характеристики игрока.
*
* <p>Структура пакета</p>
* <pre>
* | FIELD | TYPE | NOTES |
* |------------------------------|----------|-----------------------------------------|
* | Flags | Byte | Битовая маска флагов. См. ниже значения |
* | Flying Speed | Float | Скорость полёта |
* | Field of View (FOV) Modifier | Float | Поле зрения |
* </pre>
*
* <p>Флаги "Flags"</p>
* <pre>
* Bit 0x01 - Неуязвимость (Invulnerable)
* Bit 0x02 - В полёте (Flying)
* Bit 0x04 - Может летать (Allow Flying)
* Bit 0x08 - Creative Mode (Instant Break)
* </pre>
*
* @see <a href="https://wiki.vg/index.php?title=Protocol&oldid=14204#Player_Abilities_.28clientbound.29">Player Abilities</a>
*/
@Data
public class PlayerAbilitiesPacket implements ServerSidePacket {
@SuppressWarnings("java:S116")
private byte $flags = 0;
private float flyingSpeed;
private float fieldOfView;
@Override
public void writeSelf(NetByteBuf netByteBuf) {
netByteBuf.writeByte(this.$flags);
netByteBuf.writeFloat(this.flyingSpeed);
netByteBuf.writeFloat(this.fieldOfView);
}
//FIXME использование value значений
public void setInvulnerable(boolean value) {
this.$flags = (byte) (this.$flags | 0x01);
}
public void setFlying(boolean value) {
this.$flags = (byte) (this.$flags | 0x02);
}
public void setCatFly(boolean value) {
this.$flags = (byte) (this.$flags | 0x04);
}
public void setCreativeMode(boolean value) {
this.$flags = (byte) (this.$flags | 0x08);
}
}

View File

@@ -1,83 +0,0 @@
package mc.protocol.packets.server;
import lombok.Data;
import mc.protocol.io.NetByteBuf;
import mc.protocol.model.Location;
import mc.protocol.model.Look;
import mc.protocol.packets.ServerSidePacket;
import mc.protocol.packets.client.TeleportConfirmPacket;
/**
* Установка позиции и угла осмотра Игрока.
*
* <p>Структура пакета</p>
* <pre>
* | FIELD | TYPE | NOTES |
* |-------------|--------|-----------------------------------------------------------------------------------|
* | X | Double | Абсолютная или относительная позиция по X. Зависит от "Flags" |
* | Y | Double | Абсолютная или относительная позиция по Y. Зависит от "Flags" |
* | Z | Double | Абсолютная или относительная позиция по Z. Зависит от "Flags" |
* | Yaw | Float | Абсолютный или относительный поворот головы по OX, в градусах. Зависит от "Flags" |
* | Pitch | Float | Абсолютный или относительный поворот головы по OY, в градусах. Зависит от "Flags" |
* | Flags | Byte | Битовая маска значений флагов. См. значения ниже |
* | Teleport ID | VarInt | ID для подтверждения клиентом перемещения Игрока |
* </pre>
*
* <p>Значения "Flags"</p>
* <pre>
* | Field | Bit |
* |-------|------|
* | X | 0x01 |
* | Y | 0x02 |
* | Z | 0x04 |
* | X_ROT | 0x08 |
* | Y_ROT | 0x10 |
* </pre>
*
* <p>Примечание от Dinnerbone про "Flags":</p>
* <i>"It's a bitfield, X/Y/Z/Y_ROT/X_ROT. If X is set, the x value is relative and not absolute."</i>
*
* @see <a href="https://wiki.vg/index.php?title=Protocol&oldid=14204#Player_Position_And_Look_.28clientbound.29">Player Position And Look (clientbound)</a>
* @see TeleportConfirmPacket
*/
@Data
public class SPlayerPositionAndLookPacket implements ServerSidePacket {
private Location position;
private Look look;
@SuppressWarnings("java:S116")
private byte $flags = 0;
private int teleportId;
@Override
public void writeSelf(NetByteBuf netByteBuf) {
netByteBuf.writeDouble(this.position.getX());
netByteBuf.writeDouble(this.position.getY());
netByteBuf.writeDouble(this.position.getZ());
netByteBuf.writeFloat(this.look.getYaw());
netByteBuf.writeFloat(this.look.getPitch());
netByteBuf.writeByte(this.$flags);
netByteBuf.writeVarInt(teleportId);
}
//FIXME использовать value значения
public void setFlagX(boolean value) {
this.$flags = (byte) (this.$flags | 0x01);
}
public void setFlagY(boolean value) {
this.$flags = (byte) (this.$flags | 0x02);
}
public void setFlagZ(boolean value) {
this.$flags = (byte) (this.$flags | 0x04);
}
public void setFlagXRot(boolean value) {
this.$flags = (byte) (this.$flags | 0x08);
}
public void setFlagYRot(boolean value) {
this.$flags = (byte) (this.$flags | 0x10);
}
}

View File

@@ -1,41 +0,0 @@
package mc.protocol.packets.server;
import lombok.Data;
import mc.protocol.io.NetByteBuf;
import mc.protocol.model.Location;
import mc.protocol.packets.ServerSidePacket;
/**
* Спавн позиция игрока.
*
* <p>Используется призаходе игрока на сервер.</p>
*
* <p>Структура пакета</p>
* <pre>
* | FIELD | TYPE | NOTES |
* |----------|----------|-----------------------|
* | Location | Position | Локация спавна игрока |
* </pre>
*
* @see <a href="https://wiki.vg/index.php?title=Protocol&oldid=14204#Spawn_Position">Spawn Position</a>
*/
@Data
public class SpawnPositionPacket implements ServerSidePacket {
private Location spawn;
@Override
public void writeSelf(NetByteBuf netByteBuf) {
long spawnSerialized =
((long) (floorDouble(spawn.getX()) & 0x3FFFFFF) << 38)
| ((long) (floorDouble(spawn.getY()) & 0xFFF) << 26)
| (floorDouble(spawn.getZ()) & 0x3FFFFFF);
netByteBuf.writeLong(spawnSerialized);
}
private static int floorDouble(double value) {
int i = (int) value;
return value < (double) i ? i - 1 : i;
}
}

View File

@@ -1,61 +0,0 @@
package mc.protocol.packets.server;
import lombok.Data;
import mc.protocol.io.NetByteBuf;
import mc.protocol.model.ServerInfo;
import mc.protocol.packets.ServerSidePacket;
import mc.protocol.serializer.ServerInfoSerializer;
/**
* Status server packet, response.
*
* <p>Информация о сервере</p>
*
* <p>Структура пакета
* <pre>
* | FIELD | TYPE | NOTES |
* |---------------|--------|-----------------------------------------|
* | JSON Response | String | Информация о сервере в JSON формате [1] |
*
* [1] - <a href="https://wiki.vg/index.php?title=Server_List_Ping&oldid=7555#Response" target="_top">Server List Ping: Response</a>
* </pre>
*
* <p>Пример JSON Response</p>
* <pre>
* {
* "version": {
* "name": "1.8.7",
* "protocol": 47
* },
* "players": {
* "max": 100,
* "online": 5,
* "sample": [
* {
* "name": "thinkofdeath",
* "id": "4566e69f-c907-48ee-8d71-d7ba5aa00d20"
* }
* ]
* },
* "description": {
* "text": "Hello world"
* },
* "favicon": "data:image/png;base64,&lt;data&gt;"
* }
* </pre>
*
* <p><code>`$.favicon`</code> должен быть формата PNG и размеры 64x64 px</p>
*/
@Data
public class StatusServerResponse implements ServerSidePacket {
/**
* Информация о серере.
*/
private ServerInfo info;
@Override
public void writeSelf(NetByteBuf netByteBuf) {
netByteBuf.writeString(ServerInfoSerializer.toJsonObject(info).toString());
}
}

View File

@@ -1,55 +0,0 @@
package mc.protocol.serializer;
import com.eclipsesource.json.Json;
import com.eclipsesource.json.JsonArray;
import com.eclipsesource.json.JsonObject;
import lombok.experimental.UtilityClass;
import mc.protocol.model.ServerInfo;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.stream.Collector;
import java.util.stream.StreamSupport;
@UtilityClass
public class ServerInfoSerializer {
public JsonObject toJsonObject(ServerInfo info) {
JsonObject jsonObject = Json.object()
.add("version", createVersionObj(info))
.add("players", createPlayersObj(info))
.add("description", TextSerializer.toJsonObject(info.description()));
if (info.favicon() != null && !info.favicon().isEmpty()) {
jsonObject.add("favicon", info.favicon());
}
return jsonObject;
}
private JsonObject createVersionObj(ServerInfo info) {
return Json.object()
.add("name", info.version().name())
.add("protocol", info.version().protocol());
}
private JsonObject createPlayersObj(ServerInfo info) {
JsonArray sampleArr = info.players().sample().stream()
.map(samplePlayer -> Json.object()
.add("name", samplePlayer.name())
.add("id", samplePlayer.id()))
.collect(Collector.of(Json::array, JsonArray::add, ServerInfoSerializer::jsonArrayAddAll));
return Json.object()
.add("max", info.players().max())
.add("online", info.players().online())
.add("sample", sampleArr);
}
private static JsonArray jsonArrayAddAll(JsonArray jsonArrayTo, JsonArray jsonArrayFrom) {
StreamSupport.stream(
Spliterators.spliteratorUnknownSize(jsonArrayFrom.iterator(), Spliterator.ORDERED), false)
.forEach(jsonArrayTo::add);
return jsonArrayTo;
}
}

View File

@@ -1,129 +0,0 @@
package mc.protocol.serializer;
import com.eclipsesource.json.Json;
import com.eclipsesource.json.JsonArray;
import com.eclipsesource.json.JsonObject;
import lombok.experimental.UtilityClass;
import mc.protocol.model.text.Text;
import mc.protocol.model.text.TextColor;
import mc.protocol.model.text.TextStyle;
import java.util.Map;
@UtilityClass
public class TextSerializer {
private static final Map<Character, TextStyle> legacyStyleCodes;
private static final Map<Character, TextColor> legacyColorCodes;
public JsonObject toJsonObject(Text text) {
JsonObject jsonObject = Json.object();
if (text.content() != null) {
jsonObject.add("text", text.content());
}
if (text.color() != null) {
jsonObject.add("color", text.color().getName());
}
if (text.style() != null) {
//@formatter:off
if (text.style().bold() != null) jsonObject.add("bold", text.style().bold());
if (text.style().italic() != null) jsonObject.add("italic", text.style().italic());
if (text.style().underline() != null) jsonObject.add("underline", text.style().underline());
if (text.style().strikethrough() != null) jsonObject.add("strikethrough", text.style().strikethrough());
if (text.style().obfuscated() != null) jsonObject.add("obfuscated", text.style().obfuscated());
//@formatter:on
}
if (text.children() != null && !text.children().isEmpty()) {
JsonArray extra = Json.array();
text.children().forEach(child -> extra.add(toJsonObject(child)));
jsonObject.add("extra", extra);
}
return jsonObject;
}
/**
* Преобразование строки вида "&4красный" в {@link Text}.
*
* @param string тест
* @return Text
*/
@SuppressWarnings({"java:S3776", "java:S2583", "java:S135"})
public Text fromPlain(String string) {
boolean flagSys = false;
Text.Builder rootTextBuilder = Text.builder();
Text.Builder textBuilder = rootTextBuilder;
for (char ch : string.toCharArray()) {
if (!flagSys) {
if ('&' == ch) {
flagSys = true;
} else {
textBuilder.append(ch);
}
continue;
}
if (!legacyStyleCodes.containsKey(ch) && !legacyColorCodes.containsKey(ch) && '&' == ch) {
textBuilder.append('&');
flagSys = false;
continue;
}
//noinspection ConstantConditions
if (textBuilder.contentBuilder() != null && textBuilder.contentBuilder().length() > 0) {
if (textBuilder != rootTextBuilder) {
rootTextBuilder.append(textBuilder.build());
}
textBuilder = Text.builder();
}
if (legacyStyleCodes.containsKey(ch)) {
textBuilder.style(legacyStyleCodes.get(ch));
} else {
textBuilder.color(legacyColorCodes.get(ch));
}
flagSys = false;
}
if (textBuilder != rootTextBuilder) {
rootTextBuilder.append(textBuilder.build());
}
return rootTextBuilder.build();
}
static {
legacyColorCodes = Map.ofEntries(
Map.entry('0', TextColor.BLACK),
Map.entry('1', TextColor.DARK_BLUE),
Map.entry('2', TextColor.DARK_GREEN),
Map.entry('3', TextColor.DARK_AQUA),
Map.entry('4', TextColor.DARK_RED),
Map.entry('5', TextColor.DARK_PUEPLE),
Map.entry('6', TextColor.GOLD),
Map.entry('7', TextColor.GRAY),
Map.entry('8', TextColor.DARK_GRAY),
Map.entry('9', TextColor.BLUE),
Map.entry('a', TextColor.GREEN),
Map.entry('b', TextColor.AQUA),
Map.entry('c', TextColor.RED),
Map.entry('d', TextColor.PURPLE),
Map.entry('e', TextColor.YELLOW),
Map.entry('f', TextColor.WHITE)
);
legacyStyleCodes = Map.of(
'k', TextStyle.OBFUSCATED,
'l', TextStyle.BOLD,
'm', TextStyle.STRIKETHOUGH,
'n', TextStyle.UNDERLINE,
'o', TextStyle.ITALIC
);
}
}

View File

@@ -1,20 +0,0 @@
package mc.protocol.utils;
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
}
}

View File

@@ -1,15 +0,0 @@
package mc.protocol.utils;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@Getter
public enum Difficulty {
PEACEFUL(0),
EASY(1),
NORMAL(2),
HARD(3);
private final int id;
}

View File

@@ -1,33 +0,0 @@
package mc.protocol.utils;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import javax.annotation.Nullable;
@RequiredArgsConstructor
public enum EntityActionAction {
START_SNEAKING(0),
STOP_SNEAKING(1),
LEAVE_BED(2),
START_SPRINTING(3),
STOP_SPRINTING(4),
START_JUMP_WITH_HORSE(5),
STOP_JUMP_WITH_HORSE(6),
OPEN_HORSE_INVENTORY(7),
START_FLYING_WITH_ELYTRA(8);
@Nullable
public static EntityActionAction valueOfCode(int code) {
for (EntityActionAction action : EntityActionAction.values()) {
if (action.code == code) {
return action;
}
}
return null;
}
@Getter
private final int code;
}

View File

@@ -1,15 +0,0 @@
package mc.protocol.utils;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@Getter
public enum GameMode {
SURVIVAL(0),
CREATIVE(1),
ADVENTURE(2),
SPECTATOR(3);
private final int id;
}

View File

@@ -1,16 +0,0 @@
package mc.protocol.utils;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@Getter
public enum LevelType {
DEFAULT_TYPE("default"),
FLAT("flat"),
LARGE_BIOMES("largeBiomes"),
AMPLIFIED("amplified"),
DEFAULT_1_1("default_1_1");
private final String type;
}

View File

@@ -1,18 +0,0 @@
package mc.protocol.utils;
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
}
}