Archived
0

2 Commits

Author SHA1 Message Date
2b3d45a389 UpdateSignPacket 2021-05-08 21:40:50 +03:00
abac6e8491 OpenSignEditorPacket 2021-05-08 21:22:49 +03:00
8 changed files with 125 additions and 112 deletions

View File

@@ -46,20 +46,20 @@ public enum State {
Map.of( Map.of(
0x00, TeleportConfirmPacket.class, 0x00, TeleportConfirmPacket.class,
0x04, ClientSettingsPacket.class, 0x04, ClientSettingsPacket.class,
0x08, CCloseWindowPacket.class,
0x09, PluginMessagePacket.class, 0x09, PluginMessagePacket.class,
0x0B, PingPacket.class, 0x0B, PingPacket.class,
0x0D, PlayerPositionPacket.class, 0x0D, PlayerPositionPacket.class,
0x0E, CPlayerPositionAndLookPacket.class, 0x0E, CPlayerPositionAndLookPacket.class,
0x0F, PlayerLookPacket.class, 0x0F, PlayerLookPacket.class,
0x15, EntityActionPacket.class 0x15, EntityActionPacket.class,
0x1C, UpdateSignPacket.class
), ),
// client bound // client bound
Map.of( Map.of(
OpenWindowPacket.class, 0x13,
PingPacket.class, 0x1F, PingPacket.class, 0x1F,
ChunkDataPacket.class, 0x20, ChunkDataPacket.class, 0x20,
JoinGamePacket.class, 0x23, JoinGamePacket.class, 0x23,
OpenSignEditorPacket.class, 0x2A,
PlayerAbilitiesPacket.class,0x2C, PlayerAbilitiesPacket.class,0x2C,
SPlayerPositionAndLookPacket.class, 0x2F, SPlayerPositionAndLookPacket.class, 0x2F,
SpawnPositionPacket.class, 0x46 SpawnPositionPacket.class, 0x46

View File

@@ -1,46 +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.OpenWindowPacket;
/**
* Close window packet.
*
* <p>Структура пакета</p>
* <pre>
* | FIELD | TYPE | NOTES |
* |-----------|---------------|---------------------------|
* | Window ID | Unsigned Byte | ID окна, которое закрыли. |
* </pre>
*
* <p>
* Vanilla клиент отправляет данный пакет с "Window ID" = 0, при закрытии инвентаря игрока.
* Даже в тех случаях, когда для открытия инвентаря не посылался пакет {@link OpenWindowPacket}
* </p>
*
* @see <a href="https://wiki.vg/index.php?title=Protocol&oldid=14204#Close_Window_.28clientbound.29" target="_top">Close Window (serverbound)</a>
* @see OpenWindowPacket
*/
@NoArgsConstructor
@Getter
@EqualsAndHashCode
@ToString
public class CCloseWindowPacket implements ClientSidePacket {
private int windowId;
@Override
public void readSelf(NetByteBuf netByteBuf) {
this.windowId = netByteBuf.readUnsignedByte();
}
@Override
public void passivate() {
this.windowId = 0;
}
}

View File

@@ -0,0 +1,57 @@
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;
import mc.protocol.packets.server.OpenSignEditorPacket;
import mc.protocol.serializer.LocationSerializer;
/**
* Update Sign packet.
*
* <p>Отправляется клиентом, когда нажата кнопка "Done" в окне редактирования таблички.</p>
*
* <p>Структура пакета</p>
* <pre>
* | FIELD | TYPE | NOTES |
* |----------|--------------|--------------------------------|
* | Location | Location | Позиция редактируемой табилчки |
* | Line 1 | String (384) | Строка таблички |
* | Line 2 | String (384) | Строка таблички |
* | Line 3 | String (384) | Строка таблички |
* | Line 4 | String (384) | Строка таблички |
* </pre>
*
* @see <a href="https://wiki.vg/index.php?title=Protocol&oldid=14204#Update_Sign" target="_top">Update Sign</a>
* @see OpenSignEditorPacket
*/
@NoArgsConstructor
@Getter
@EqualsAndHashCode
@ToString
public class UpdateSignPacket implements ClientSidePacket {
private Location location;
@SuppressWarnings("MismatchedReadAndWriteOfArray")
private String[] lines;
@Override
public void readSelf(NetByteBuf netByteBuf) {
this.location = LocationSerializer.fromLongValue(netByteBuf.readLong());
this.lines = new String[4];
this.lines[0] = netByteBuf.readString(384);
this.lines[1] = netByteBuf.readString(384);
this.lines[2] = netByteBuf.readString(384);
this.lines[3] = netByteBuf.readString(384);
}
@Override
public void passivate() {
this.location = null;
this.lines = null;
}
}

View File

@@ -0,0 +1,33 @@
package mc.protocol.packets.server;
import lombok.Data;
import mc.protocol.io.NetByteBuf;
import mc.protocol.model.Location;
import mc.protocol.packets.ServerSidePacket;
import mc.protocol.packets.client.UpdateSignPacket;
import mc.protocol.serializer.LocationSerializer;
/**
* Открыть окно редактирования таблички.
*
* <p>Структура пакета</p>
* <pre>
* | FIELD | TYPE | NOTES |
* |----------|----------|-------|
* | Location | Location | |
* </pre>
*
* @see <a href="https://wiki.vg/index.php?title=Protocol&oldid=14204#Open_Sign_Editor">Open Sign Editor</a>
* @see UpdateSignPacket
*/
@Data
public class OpenSignEditorPacket implements ServerSidePacket {
private Location location;
@Override
public void writeSelf(NetByteBuf netByteBuf) {
long value = LocationSerializer.toLongValue(this.location);
netByteBuf.writeLong(value);
}
}

View File

@@ -1,45 +0,0 @@
package mc.protocol.packets.server;
import lombok.Data;
import mc.protocol.io.NetByteBuf;
import mc.protocol.model.text.Text;
import mc.protocol.packets.ServerSidePacket;
import mc.protocol.packets.client.CCloseWindowPacket;
import mc.protocol.serializer.TextSerializer;
/**
* Open Window packet.
*
* <p>Структура пакета</p>
* <pre>
* | FIELD | TYPE | NOTES |
* |-----------------|---------------|--------------------------------------------------------------|
* | Window ID | Unsigned Byte | Уникальный ID окна |
* | Window Type | String (32) | Тип окна. [1] |
* | Window Title | Text | Заголовок окна |
* | Number Of Slots | Unsigned Byte | Количество слотов в окне (без учета слотов инвенторя игрока) |
* | | | Всегда 0 для окон без хранения (например Anvil) |
*
* [1] - <a href="https://wiki.vg/index.php?title=Inventory&oldid=14093">Inventory</a>
* </pre>
*
* @see <a href="https://wiki.vg/index.php?title=Protocol&oldid=14204#Open_Window">Open Window</a>
* @see <a href="https://wiki.vg/index.php?title=Inventory&oldid=14093">Inventory</a>
* @see CCloseWindowPacket
*/
@Data
public class OpenWindowPacket implements ServerSidePacket {
private int windowId;
private String windowType;
private Text windowTitle;
private int numberOfSlots;
@Override
public void writeSelf(NetByteBuf netByteBuf) {
netByteBuf.writeUnsignedByte(this.windowId);
netByteBuf.writeString(this.windowType);
netByteBuf.writeString(TextSerializer.toJsonObject(this.windowTitle).toString());
netByteBuf.writeUnsignedByte(this.numberOfSlots);
}
}

View File

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

View File

@@ -0,0 +1,26 @@
package mc.protocol.serializer;
import lombok.experimental.UtilityClass;
import mc.protocol.model.Location;
@UtilityClass
public class LocationSerializer {
public long toLongValue(Location location) {
return ((long) (floorDouble(location.getX()) & 0x3FFFFFF) << 38)
| ((long) (floorDouble(location.getY()) & 0xFFF) << 26)
| (floorDouble(location.getZ()) & 0x3FFFFFF);
}
public Location fromLongValue(long value) {
return new Location(
value >> 38,
(value >> 26) & 0xFFF,
value << 38 >> 38);
}
private static int floorDouble(double value) {
int i = (int) value;
return value < (double) i ? i - 1 : i;
}
}

View File

@@ -7,7 +7,6 @@ import mc.protocol.api.ConnectionContext;
import mc.protocol.model.Location; import mc.protocol.model.Location;
import mc.protocol.model.Look; import mc.protocol.model.Look;
import mc.protocol.model.ServerInfo; import mc.protocol.model.ServerInfo;
import mc.protocol.model.text.Text;
import mc.protocol.packets.PingPacket; import mc.protocol.packets.PingPacket;
import mc.protocol.packets.client.HandshakePacket; import mc.protocol.packets.client.HandshakePacket;
import mc.protocol.packets.client.LoginStartPacket; import mc.protocol.packets.client.LoginStartPacket;
@@ -126,13 +125,10 @@ public class PacketHandler {
// -- Эксперименты -- // // -- Эксперименты -- //
var openWindowPacket = new OpenWindowPacket(); var openSignEditorPacket = new OpenSignEditorPacket();
openWindowPacket.setWindowId(random.nextInt()); openSignEditorPacket.setLocation(spawnLocation);
openWindowPacket.setWindowType("minecraft:chest");
openWindowPacket.setWindowTitle(Text.of("Some Title"));
openWindowPacket.setNumberOfSlots(9);
context.sendNow(openWindowPacket); context.sendNow(openSignEditorPacket);
} }
private static String faviconToBase64(Path iconPath) { private static String faviconToBase64(Path iconPath) {