Handshake and login packets, even more readable server packets

This commit is contained in:
jglrxavpok 2021-02-17 19:04:48 +01:00
parent f9dcbafddf
commit 43957805fd
36 changed files with 557 additions and 42 deletions

View File

@ -1986,10 +1986,9 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
return;
}
OpenWindowPacket openWindowPacket = new OpenWindowPacket();
OpenWindowPacket openWindowPacket = new OpenWindowPacket(newInventory.getTitle());
openWindowPacket.windowId = newInventory.getWindowId();
openWindowPacket.windowType = newInventory.getInventoryType().getWindowType();
openWindowPacket.title = newInventory.getTitle();
playerConnection.sendPacket(openWindowPacket);
newInventory.addViewer(this);
this.openInventory = newInventory;

View File

@ -118,11 +118,10 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View
public void setTitle(@NotNull String title) {
this.title = title;
OpenWindowPacket packet = new OpenWindowPacket();
OpenWindowPacket packet = new OpenWindowPacket(title);
packet.windowId = getWindowId();
packet.windowType = getInventoryType().getWindowType();
packet.title = title;
// Re-open the inventory
sendPacketToViewers(packet);

View File

@ -11,6 +11,7 @@ import net.minestom.server.network.packet.server.login.LoginDisconnectPacket;
import net.minestom.server.network.player.NettyPlayerConnection;
import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
import java.net.SocketAddress;
@ -25,7 +26,7 @@ public class HandshakePacket implements ClientPreplayPacket {
private static final Component INVALID_BUNGEE_FORWARDING = Component.text("If you wish to use IP forwarding, please enable it in your BungeeCord config as well!", NamedTextColor.RED);
private int protocolVersion;
private String serverAddress;
private String serverAddress = "";
private int serverPort;
private int nextState;
@ -37,6 +38,18 @@ public class HandshakePacket implements ClientPreplayPacket {
this.nextState = reader.readVarInt();
}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeVarInt(protocolVersion);
int maxLength = BungeeCordProxy.isEnabled() ? Short.MAX_VALUE : 255;
if(serverAddress.length() > maxLength) {
throw new IllegalArgumentException("serverAddress is "+serverAddress.length()+" characters long, maximum allowed is "+maxLength);
}
writer.writeSizedString(serverAddress);
writer.writeUnsignedShort(serverPort);
writer.writeVarInt(nextState);
}
@Override
public void process(@NotNull PlayerConnection connection) {

View File

@ -11,6 +11,7 @@ import net.minestom.server.network.player.NettyPlayerConnection;
import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.utils.async.AsyncUtils;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
import javax.crypto.SecretKey;
@ -22,6 +23,11 @@ public class EncryptionResponsePacket implements ClientPreplayPacket {
private byte[] sharedSecret;
private byte[] verifyToken;
public EncryptionResponsePacket() {
sharedSecret = new byte[0];
verifyToken = new byte[0];
}
@Override
public void process(@NotNull PlayerConnection connection) {
@ -68,6 +74,12 @@ public class EncryptionResponsePacket implements ClientPreplayPacket {
verifyToken = ByteArrayData.decodeByteArray(reader);
}
@Override
public void write(@NotNull BinaryWriter writer) {
ByteArrayData.encodeByteArray(writer, sharedSecret);
ByteArrayData.encodeByteArray(writer, verifyToken);
}
public SecretKey getSecretKey() {
return MojangCrypt.decryptByteToSecretKey(MojangAuth.getKeyPair().getPrivate(), sharedSecret);
}

View File

@ -12,6 +12,7 @@ import net.minestom.server.network.packet.server.login.LoginDisconnectPacket;
import net.minestom.server.network.player.NettyPlayerConnection;
import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
import java.net.InetAddress;
@ -27,7 +28,7 @@ public class LoginPluginResponsePacket implements ClientPreplayPacket {
public int messageId;
public boolean successful;
public byte[] data;
public byte[] data = new byte[0];
@Override
public void process(@NotNull PlayerConnection connection) {
@ -93,7 +94,17 @@ public class LoginPluginResponsePacket implements ClientPreplayPacket {
this.messageId = reader.readVarInt();
this.successful = reader.readBoolean();
if (successful) {
this.data = reader.getRemainingBytes();
this.data = reader.readRemainingBytes();
}
}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeVarInt(messageId);
writer.writeBoolean(successful);
if(successful) {
writer.writeBytes(data);
}
}
}

View File

@ -15,6 +15,7 @@ import net.minestom.server.network.packet.server.login.LoginPluginRequestPacket;
import net.minestom.server.network.player.NettyPlayerConnection;
import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
@ -24,7 +25,7 @@ public class LoginStartPacket implements ClientPreplayPacket {
private static final Component ALREADY_CONNECTED = Component.text("You are already on this server", NamedTextColor.RED);
public String username;
public String username = "";
@Override
public void process(@NotNull PlayerConnection connection) {
@ -101,4 +102,10 @@ public class LoginStartPacket implements ClientPreplayPacket {
this.username = reader.readSizedString(16);
}
@Override
public void write(@NotNull BinaryWriter writer) {
if(username.length() > 16)
throw new IllegalArgumentException("Username is not allowed to be longer than 16 characters");
writer.writeSizedString(username);
}
}

View File

@ -1,18 +1,24 @@
package net.minestom.server.network.packet.server.handshake;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ResponsePacket implements ServerPacket {
public String jsonResponse;
public String jsonResponse = "";
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeSizedString(jsonResponse);
}
@Override
public void read(@NotNull BinaryReader reader) {
jsonResponse = reader.readSizedString(Integer.MAX_VALUE);
}
@Override
public int getId() {
return 0x00;

View File

@ -5,6 +5,7 @@ import net.minestom.server.extras.MojangAuth;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.network.player.NettyPlayerConnection;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
@ -20,6 +21,14 @@ public class EncryptionRequestPacket implements ServerPacket {
connection.setNonce(nonce);
}
/**
* Only for testing purposes. DO NOT USE
*/
private EncryptionRequestPacket() {
MojangAuth.init();
publicKey = new byte[0];
}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeSizedString("");
@ -28,6 +37,14 @@ public class EncryptionRequestPacket implements ServerPacket {
ByteArrayData.encodeByteArray(writer, nonce);
}
@Override
public void read(@NotNull BinaryReader reader) {
reader.readSizedString(Integer.MAX_VALUE); // server id, apparently empty
publicKey = ByteArrayData.decodeByteArray(reader);
nonce = ByteArrayData.decodeByteArray(reader);
}
@Override
public int getId() {
return ServerPacketIdentifier.LOGIN_ENCRYPTION_REQUEST;

View File

@ -4,6 +4,7 @@ import net.kyori.adventure.text.Component;
import net.minestom.server.chat.JsonMessage;
import net.minestom.server.network.packet.server.ComponentHoldingServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
@ -14,6 +15,10 @@ import java.util.function.UnaryOperator;
public class LoginDisconnectPacket implements ComponentHoldingServerPacket {
public Component kickMessage;
private LoginDisconnectPacket() {
this(Component.text("This constructor should not be used, tell your server devs."));
}
public LoginDisconnectPacket(@NotNull Component kickMessage) {
this.kickMessage = kickMessage;
}
@ -31,6 +36,11 @@ public class LoginDisconnectPacket implements ComponentHoldingServerPacket {
writer.writeComponent(kickMessage);
}
@Override
public void read(@NotNull BinaryReader reader) {
kickMessage = reader.readComponent(Integer.MAX_VALUE);
}
@Override
public int getId() {
return ServerPacketIdentifier.LOGIN_DISCONNECT;

View File

@ -2,13 +2,14 @@ package net.minestom.server.network.packet.server.login;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class LoginPluginRequestPacket implements ServerPacket {
public int messageId;
public String channel;
public String channel = "none";
public byte[] data;
@Override
@ -20,6 +21,13 @@ public class LoginPluginRequestPacket implements ServerPacket {
}
}
@Override
public void read(@NotNull BinaryReader reader) {
messageId = reader.readVarInt();
channel = reader.readSizedString(Integer.MAX_VALUE);
data = reader.readRemainingBytes();
}
@Override
public int getId() {
return ServerPacketIdentifier.LOGIN_PLUGIN_REQUEST;

View File

@ -2,6 +2,7 @@ package net.minestom.server.network.packet.server.login;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
@ -12,6 +13,13 @@ public class LoginSuccessPacket implements ServerPacket {
public UUID uuid;
public String username;
/**
* DO NOT USE.
*/
private LoginSuccessPacket() {
this(new UUID(0,0), "");
}
public LoginSuccessPacket(@NotNull UUID uuid, @NotNull String username) {
this.uuid = uuid;
this.username = username;
@ -23,6 +31,12 @@ public class LoginSuccessPacket implements ServerPacket {
writer.writeSizedString(username);
}
@Override
public void read(@NotNull BinaryReader reader) {
uuid = reader.readUuid();
username = reader.readSizedString(Integer.MAX_VALUE);
}
@Override
public int getId() {
return ServerPacketIdentifier.LOGIN_SUCCESS;

View File

@ -2,6 +2,7 @@ package net.minestom.server.network.packet.server.login;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
@ -9,6 +10,13 @@ public class SetCompressionPacket implements ServerPacket {
public int threshold;
/**
* DO NOT USE
*/
private SetCompressionPacket() {
threshold = 256;
}
public SetCompressionPacket(int threshold) {
this.threshold = threshold;
}
@ -18,6 +26,11 @@ public class SetCompressionPacket implements ServerPacket {
writer.writeVarInt(threshold);
}
@Override
public void read(@NotNull BinaryReader reader) {
threshold = reader.readVarInt();
}
@Override
public int getId() {
return ServerPacketIdentifier.LOGIN_SET_COMPRESSION;

View File

@ -2,6 +2,7 @@ package net.minestom.server.network.packet.server.play;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
@ -9,6 +10,8 @@ public class KeepAlivePacket implements ServerPacket {
public long id;
KeepAlivePacket() {}
public KeepAlivePacket(long id) {
this.id = id;
}
@ -18,6 +21,11 @@ public class KeepAlivePacket implements ServerPacket {
writer.writeLong(id);
}
@Override
public void read(@NotNull BinaryReader reader) {
id = reader.readLong();
}
@Override
public int getId() {
return ServerPacketIdentifier.KEEP_ALIVE;

View File

@ -4,7 +4,10 @@ import net.kyori.adventure.text.Component;
import net.minestom.server.network.packet.server.ComponentHoldingServerPacket;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import net.minestom.server.utils.binary.Readable;
import net.minestom.server.utils.binary.Writeable;
import org.jetbrains.annotations.NotNull;
import java.util.*;
@ -17,13 +20,15 @@ public class MapDataPacket implements ComponentHoldingServerPacket {
public boolean trackingPosition;
public boolean locked;
public Icon[] icons;
public Icon[] icons = new Icon[0];
public short columns;
public short rows;
public byte x;
public byte z;
public byte[] data;
public byte[] data = new byte[0];
public MapDataPacket() {}
@Override
public void write(@NotNull BinaryWriter writer) {
@ -58,6 +63,32 @@ public class MapDataPacket implements ComponentHoldingServerPacket {
}
@Override
public void read(@NotNull BinaryReader reader) {
mapId = reader.readVarInt();
scale = reader.readByte();
trackingPosition = reader.readBoolean();
locked = reader.readBoolean();
int iconCount = reader.readVarInt();
icons = new Icon[iconCount];
for (int i = 0; i < iconCount; i++) {
icons[i] = new Icon();
icons[i].read(reader);
}
columns = reader.readByte();
if(columns <= 0) {
return;
}
rows = reader.readByte();
x = reader.readByte();
z = reader.readByte();
int dataLength = reader.readVarInt();
data = reader.readBytes(dataLength);
}
@Override
public int getId() {
return ServerPacketIdentifier.MAP_DATA;
@ -101,13 +132,13 @@ public class MapDataPacket implements ComponentHoldingServerPacket {
}
}
public static class Icon {
public static class Icon implements Writeable, Readable {
public int type;
public byte x, z;
public byte direction;
public Component displayName;
private void write(BinaryWriter writer) {
public void write(BinaryWriter writer) {
writer.writeVarInt(type);
writer.writeByte(x);
writer.writeByte(z);
@ -120,6 +151,20 @@ public class MapDataPacket implements ComponentHoldingServerPacket {
}
}
@Override
public void read(@NotNull BinaryReader reader) {
type = reader.readVarInt();
x = reader.readByte();
z = reader.readByte();
direction = reader.readByte();
boolean hasDisplayName = reader.readBoolean();
if(hasDisplayName) {
displayName = reader.readComponent(Integer.MAX_VALUE);
} else {
displayName = null;
}
}
}
}

View File

@ -3,6 +3,7 @@ package net.minestom.server.network.packet.server.play;
import net.minestom.server.instance.Chunk;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import net.minestom.server.utils.chunk.ChunkUtils;
import org.jetbrains.annotations.NotNull;
@ -14,7 +15,9 @@ public class MultiBlockChangePacket implements ServerPacket {
public int section;
//TODO this is important prob if we add a light api
public boolean suppressLightUpdates = true;
public BlockChange[] blockChanges;
public BlockChange[] blockChanges = new BlockChange[0];
public MultiBlockChangePacket() {}
@Override
public void write(@NotNull BinaryWriter writer) {
@ -31,6 +34,30 @@ public class MultiBlockChangePacket implements ServerPacket {
}
}
@Override
public void read(@NotNull BinaryReader reader) {
long chunkIndexWithSection = reader.readLong();
chunkX = ChunkUtils.getChunkXFromChunkIndexWithSection(chunkIndexWithSection);
chunkZ = ChunkUtils.getChunkZFromChunkIndexWithSection(chunkIndexWithSection);
section = ChunkUtils.getSectionFromChunkIndexWithSection(chunkIndexWithSection);
suppressLightUpdates = reader.readBoolean();
int blockChangeCount = reader.readVarInt();
blockChanges = new BlockChange[blockChangeCount];
for (int i = 0; i < blockChangeCount; i++) {
BlockChange change = new BlockChange();
long encodedChange = reader.readVarLong();
short localPos = (short) (encodedChange & 0x0F_FF);
change.positionX = getXFromLocalBlockPosAsShort(localPos);
change.positionY = getYFromLocalBlockPosAsShort(localPos);
change.positionZ = getZFromLocalBlockPosAsShort(localPos);
change.newBlockId = (int) (encodedChange >> 12);
blockChanges[i] = change;
}
}
public static short getLocalBlockPosAsShort(int x, int y, int z) {
x = x % Chunk.CHUNK_SIZE_X;
y = y % 16;
@ -38,6 +65,18 @@ public class MultiBlockChangePacket implements ServerPacket {
return (short) (x << 8 | z << 4 | y);
}
public static int getXFromLocalBlockPosAsShort(short localPos) {
return (localPos >> 8) % Chunk.CHUNK_SIZE_X;
}
public static int getZFromLocalBlockPosAsShort(short localPos) {
return (localPos >> 4) % Chunk.CHUNK_SIZE_Z;
}
public static int getYFromLocalBlockPosAsShort(short localPos) {
return localPos & 0xF;
}
@Override
public int getId() {
return ServerPacketIdentifier.MULTI_BLOCK_CHANGE;

View File

@ -4,6 +4,8 @@ import net.kyori.adventure.sound.Sound.Source;
import net.minestom.server.adventure.AdventurePacketConvertor;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.sound.SoundCategory;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
@ -15,6 +17,11 @@ public class NamedSoundEffectPacket implements ServerPacket {
public float volume;
public float pitch;
public NamedSoundEffectPacket() {
soundName = "";
soundSource = Source.AMBIENT;
}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeSizedString(soundName);
@ -26,6 +33,17 @@ public class NamedSoundEffectPacket implements ServerPacket {
writer.writeFloat(pitch);
}
@Override
public void read(@NotNull BinaryReader reader) {
soundName = reader.readSizedString(Integer.MAX_VALUE);
soundSource = Source.values()[reader.readVarInt()];
x = reader.readInt() / 8;
y = reader.readInt() / 8;
z = reader.readInt() / 8;
volume = reader.readFloat();
pitch = reader.readFloat();
}
@Override
public int getId() {
return ServerPacketIdentifier.NAMED_SOUND_EFFECT;

View File

@ -1,16 +1,25 @@
package net.minestom.server.network.packet.server.play;
import net.minestom.server.MinecraftServer;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
import org.jglrxavpok.hephaistos.nbt.NBT;
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import org.jglrxavpok.hephaistos.nbt.NBTEnd;
import org.jglrxavpok.hephaistos.nbt.NBTException;
import java.io.IOException;
public class NbtQueryResponsePacket implements ServerPacket {
public int transactionId;
public NBTCompound nbtCompound;
public NbtQueryResponsePacket() {}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeVarInt(transactionId);
@ -22,6 +31,23 @@ public class NbtQueryResponsePacket implements ServerPacket {
}
}
@Override
public void read(@NotNull BinaryReader reader) {
transactionId = reader.readVarInt();
try {
NBT nbt = reader.readTag();
if (nbt instanceof NBTEnd) {
return;
}
nbtCompound = (NBTCompound) nbt;
} catch (IOException | NBTException e) {
MinecraftServer.getExceptionManager().handleException(e);
// TODO: should we throw? the packet is not valid
}
}
@Override
public int getId() {
return ServerPacketIdentifier.NBT_QUERY_RESPONSE;

View File

@ -3,18 +3,26 @@ package net.minestom.server.network.packet.server.play;
import net.minestom.server.entity.Player;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class OpenBookPacket implements ServerPacket {
public Player.Hand hand;
public Player.Hand hand = Player.Hand.MAIN;
public OpenBookPacket() {}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeVarInt(hand.ordinal());
}
@Override
public void read(@NotNull BinaryReader reader) {
hand = Player.Hand.values()[reader.readVarInt()];
}
@Override
public int getId() {
return ServerPacketIdentifier.OPEN_BOOK;

View File

@ -2,6 +2,7 @@ package net.minestom.server.network.packet.server.play;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
@ -18,6 +19,13 @@ public class OpenHorseWindowPacket implements ServerPacket {
writer.writeInt(entityId);
}
@Override
public void read(@NotNull BinaryReader reader) {
windowId = reader.readByte();
slotCount = reader.readVarInt();
entityId = reader.readInt();
}
@Override
public int getId() {
return ServerPacketIdentifier.OPEN_HORSE_WINDOW;

View File

@ -3,19 +3,32 @@ package net.minestom.server.network.packet.server.play;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.BlockPosition;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class OpenSignEditorPacket implements ServerPacket {
// WARNING: There must be a sign in this location (you can send a BlockChangePacket beforehand)
/**
* WARNING: There must be a sign in this location (you can send a BlockChangePacket beforehand)
*/
public BlockPosition signPosition;
public OpenSignEditorPacket() {
signPosition = new BlockPosition(0,0,0);
}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeBlockPosition(signPosition);
}
@Override
public void read(@NotNull BinaryReader reader) {
signPosition = reader.readBlockPosition();
}
@Override
public int getId() {
return ServerPacketIdentifier.OPEN_SIGN_EDITOR;

View File

@ -1,7 +1,10 @@
package net.minestom.server.network.packet.server.play;
import net.minestom.server.chat.ColoredText;
import net.minestom.server.chat.JsonMessage;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
@ -9,13 +12,26 @@ public class OpenWindowPacket implements ServerPacket {
public int windowId;
public int windowType;
public String title;
public JsonMessage title = ColoredText.of("");
public OpenWindowPacket() {}
public OpenWindowPacket(String title) {
this.title = ColoredText.of(title);
}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeVarInt(windowId);
writer.writeVarInt(windowType);
writer.writeSizedString("{\"text\": \"" + title + " \"}");
writer.writeJsonMessage(title);
}
@Override
public void read(@NotNull BinaryReader reader) {
windowId = reader.readVarInt();
windowType = reader.readVarInt();
title = reader.readJsonMessage(Integer.MAX_VALUE);
}
@Override

View File

@ -2,6 +2,7 @@ package net.minestom.server.network.packet.server.play;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
@ -16,7 +17,11 @@ public class ParticlePacket implements ServerPacket {
public float particleData;
public int particleCount;
public Consumer<BinaryWriter> dataConsumer;
public byte[] data;
public ParticlePacket() {
data = new byte[0];
}
@Override
public void write(@NotNull BinaryWriter writer) {
@ -31,9 +36,23 @@ public class ParticlePacket implements ServerPacket {
writer.writeFloat(particleData);
writer.writeInt(particleCount);
if (dataConsumer != null) {
dataConsumer.accept(writer);
}
writer.writeBytes(data);
}
@Override
public void read(@NotNull BinaryReader reader) {
particleId = reader.readInt();
longDistance = reader.readBoolean();
x = reader.readDouble();
y = reader.readDouble();
z = reader.readDouble();
offsetX = reader.readFloat();
offsetY = reader.readFloat();
offsetZ = reader.readFloat();
particleData = reader.readFloat();
particleCount = reader.readInt();
data = reader.readRemainingBytes();
}
@Override

View File

@ -2,6 +2,7 @@ package net.minestom.server.network.packet.server.play;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
@ -34,6 +35,18 @@ public class PlayerAbilitiesPacket implements ServerPacket {
writer.writeFloat(fieldViewModifier);
}
@Override
public void read(@NotNull BinaryReader reader) {
byte flags = reader.readByte();
invulnerable = (flags & 1) == 1;
flying = (flags & 2) == 2;
allowFlying = (flags & 4) == 4;
instantBreak = (flags & 8) == 8;
flyingSpeed = reader.readFloat();
fieldViewModifier = reader.readFloat();
}
@Override
public int getId() {
return ServerPacketIdentifier.PLAYER_ABILITIES;

View File

@ -6,6 +6,7 @@ import net.minestom.server.entity.GameMode;
import net.minestom.server.network.packet.server.ComponentHoldingServerPacket;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
@ -18,6 +19,10 @@ public class PlayerInfoPacket implements ComponentHoldingServerPacket {
public Action action;
public List<PlayerInfo> playerInfos;
PlayerInfoPacket() {
this(Action.UPDATE_DISPLAY_NAME);
}
public PlayerInfoPacket(Action action) {
this.action = action;
this.playerInfos = new CopyOnWriteArrayList<>();
@ -35,6 +40,41 @@ public class PlayerInfoPacket implements ComponentHoldingServerPacket {
}
}
@Override
public void read(@NotNull BinaryReader reader) {
action = Action.values()[reader.readVarInt()];
int playerInfoCount = reader.readVarInt();
playerInfos = new ArrayList<>(playerInfoCount);
for (int i = 0; i < playerInfoCount; i++) {
UUID uuid = reader.readUuid();
PlayerInfo info;
switch (action) {
case ADD_PLAYER:
info = new AddPlayer(uuid, reader);
break;
case UPDATE_GAMEMODE:
info = new UpdateGamemode(uuid, reader);
break;
case UPDATE_LATENCY:
info = new UpdateLatency(uuid, reader);
break;
case UPDATE_DISPLAY_NAME:
info = new UpdateDisplayName(uuid, reader);
break;
case REMOVE_PLAYER:
info = new RemovePlayer(uuid);
break;
default:
throw new IllegalArgumentException("Unsupported action encountered: "+action.name());
}
playerInfos.set(i, info);
}
}
@Override
public int getId() {
return ServerPacketIdentifier.PLAYER_INFO;
@ -121,6 +161,27 @@ public class PlayerInfoPacket implements ComponentHoldingServerPacket {
this.ping = ping;
}
AddPlayer(UUID uuid, BinaryReader reader) {
super(uuid);
name = reader.readSizedString(Integer.MAX_VALUE);
int propertyCount = reader.readVarInt();
properties = new ArrayList<>(propertyCount);
for (int i = 0; i < propertyCount; i++) {
properties.set(i, new Property(reader));
}
gameMode = GameMode.fromId((byte) reader.readVarInt());
ping = reader.readVarInt();
boolean hasDisplayName = reader.readBoolean();
if(hasDisplayName) {
displayName = reader.readComponent(Integer.MAX_VALUE);
} else {
displayName = null;
}
}
@Override
public void write(BinaryWriter writer) {
writer.writeSizedString(name);
@ -173,6 +234,16 @@ public class PlayerInfoPacket implements ComponentHoldingServerPacket {
this(name, value, null);
}
Property(BinaryReader reader) {
name = reader.readSizedString(Integer.MAX_VALUE);
value = reader.readSizedString(Integer.MAX_VALUE);
boolean hasSignature = reader.readBoolean();
if(hasSignature) {
signature = reader.readSizedString(Integer.MAX_VALUE);
}
}
public void write(BinaryWriter writer) {
writer.writeSizedString(name);
writer.writeSizedString(value);
@ -194,6 +265,11 @@ public class PlayerInfoPacket implements ComponentHoldingServerPacket {
this.gameMode = gameMode;
}
UpdateGamemode(UUID uuid, BinaryReader reader) {
super(uuid);
gameMode = GameMode.fromId((byte) reader.readVarInt());
}
@Override
public void write(BinaryWriter writer) {
writer.writeVarInt(gameMode.getId());
@ -209,6 +285,11 @@ public class PlayerInfoPacket implements ComponentHoldingServerPacket {
this.ping = ping;
}
UpdateLatency(UUID uuid, BinaryReader reader) {
super(uuid);
ping = reader.readVarInt();
}
@Override
public void write(BinaryWriter writer) {
writer.writeVarInt(ping);
@ -224,6 +305,16 @@ public class PlayerInfoPacket implements ComponentHoldingServerPacket {
this.displayName = displayName;
}
UpdateDisplayName(UUID uuid, BinaryReader reader) {
super(uuid);
boolean hasDisplayName = reader.readBoolean();
if(hasDisplayName) {
displayName = reader.readComponent(Integer.MAX_VALUE);
} else {
displayName = null;
}
}
@Override
public void write(BinaryWriter writer) {
final boolean hasDisplayName = displayName != null;

View File

@ -4,6 +4,7 @@ import net.kyori.adventure.text.Component;
import net.minestom.server.network.packet.server.ComponentHoldingServerPacket;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@ -18,6 +19,10 @@ public class PlayerListHeaderAndFooterPacket implements ComponentHoldingServerPa
public Component header;
public Component footer;
public PlayerListHeaderAndFooterPacket() {
this(null, null);
}
public PlayerListHeaderAndFooterPacket(@Nullable Component header, @Nullable Component footer) {
this.header = header;
this.footer = footer;
@ -29,11 +34,6 @@ public class PlayerListHeaderAndFooterPacket implements ComponentHoldingServerPa
writer.writeComponent(Objects.requireNonNullElseGet(footer, Component::empty));
}
@Override
public int getId() {
return ServerPacketIdentifier.PLAYER_LIST_HEADER_AND_FOOTER;
}
@Override
public @NotNull Collection<Component> components() {
List<Component> components = new ArrayList<>();
@ -50,4 +50,14 @@ public class PlayerListHeaderAndFooterPacket implements ComponentHoldingServerPa
public @NotNull ServerPacket copyWithOperator(@NotNull UnaryOperator<Component> operator) {
return new PlayerListHeaderAndFooterPacket(header == null ? null : operator.apply(header), footer == null ? null : operator.apply(footer));
}
public void read(@NotNull BinaryReader reader) {
header = reader.readComponent(Integer.MAX_VALUE);
footer = reader.readComponent(Integer.MAX_VALUE);
}
@Override
public int getId() {
return ServerPacketIdentifier.PLAYER_LIST_HEADER_AND_FOOTER;
}
}

View File

@ -3,6 +3,7 @@ package net.minestom.server.network.packet.server.play;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
@ -12,6 +13,9 @@ public class PlayerPositionAndLookPacket implements ServerPacket {
public byte flags;
public int teleportId;
public PlayerPositionAndLookPacket() {
position = new Position();
}
@Override
public void write(@NotNull BinaryWriter writer) {
@ -26,6 +30,14 @@ public class PlayerPositionAndLookPacket implements ServerPacket {
writer.writeVarInt(teleportId);
}
@Override
public void read(@NotNull BinaryReader reader) {
position = new Position(reader.readDouble(), reader.readDouble(), reader.readDouble(), reader.readFloat(), reader.readFloat());
flags = reader.readByte();
teleportId = reader.readVarInt();
}
@Override
public int getId() {
return ServerPacketIdentifier.PLAYER_POSITION_AND_LOOK;

View File

@ -3,13 +3,16 @@ package net.minestom.server.network.packet.server.play;
import net.minestom.server.MinecraftServer;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
public class PluginMessagePacket implements ServerPacket {
public String channel;
public byte[] data;
public String channel = "none";
public byte[] data = new byte[0];
@Override
public void write(@NotNull BinaryWriter writer) {
@ -17,6 +20,12 @@ public class PluginMessagePacket implements ServerPacket {
writer.writeBytes(data);
}
@Override
public void read(@NotNull BinaryReader reader) {
channel = reader.readSizedString(Integer.MAX_VALUE);
data = reader.getRemainingBytes();
}
@Override
public int getId() {
return ServerPacketIdentifier.PLUGIN_MESSAGE;

View File

@ -3,13 +3,16 @@ package net.minestom.server.network.packet.server.play;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.potion.PotionEffect;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class RemoveEntityEffectPacket implements ServerPacket {
public int entityId;
public PotionEffect effect;
public PotionEffect effect = PotionEffect.ABSORPTION;
public RemoveEntityEffectPacket() {}
@Override
public void write(@NotNull BinaryWriter writer) {
@ -17,6 +20,12 @@ public class RemoveEntityEffectPacket implements ServerPacket {
writer.writeByte((byte) effect.getId());
}
@Override
public void read(@NotNull BinaryReader reader) {
entityId = reader.readVarInt();
effect = PotionEffect.fromId(reader.readByte());
}
@Override
public int getId() {
return ServerPacketIdentifier.REMOVE_ENTITY_EFFECT;

View File

@ -2,13 +2,16 @@ package net.minestom.server.network.packet.server.play;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ResourcePackSendPacket implements ServerPacket {
public String url;
public String hash; // Size 40
public String url = "";
public String hash = "0000000000000000000000000000000000000000"; // Size 40
public ResourcePackSendPacket() {}
@Override
public void write(@NotNull BinaryWriter writer) {
@ -16,6 +19,12 @@ public class ResourcePackSendPacket implements ServerPacket {
writer.writeSizedString(hash);
}
@Override
public void read(@NotNull BinaryReader reader) {
url = reader.readSizedString(Integer.MAX_VALUE);
hash = reader.readSizedString(Integer.MAX_VALUE);
}
@Override
public int getId() {
return ServerPacketIdentifier.RESOURCE_PACK_SEND;

View File

@ -52,9 +52,9 @@ public class TabCompletePacket implements ComponentHoldingServerPacket {
for (int i = 0; i < matchCount; i++) {
String match = reader.readSizedString(Integer.MAX_VALUE);
boolean hasTooltip = reader.readBoolean();
JsonMessage tooltip = null;
Component tooltip = null;
if(hasTooltip) {
tooltip = reader.readJsonMessage(Integer.MAX_VALUE);
tooltip = reader.readComponent(Integer.MAX_VALUE);
}
Match newMatch = new Match();
newMatch.match = match;

View File

@ -113,13 +113,13 @@ public class TeamsPacket implements ComponentHoldingServerPacket {
switch (action) {
case CREATE_TEAM:
case UPDATE_TEAM_INFO:
this.teamDisplayName = reader.readJsonMessage(Integer.MAX_VALUE);
this.teamDisplayName = reader.readComponent(Integer.MAX_VALUE);
this.friendlyFlags = reader.readByte();
nameTagVisibility = NameTagVisibility.fromIdentifier(reader.readSizedString(Integer.MAX_VALUE));
collisionRule = CollisionRule.fromIdentifier(reader.readSizedString(Integer.MAX_VALUE));
this.teamColor = reader.readVarInt();
this.teamPrefix = reader.readJsonMessage(Integer.MAX_VALUE);
this.teamSuffix = reader.readJsonMessage(Integer.MAX_VALUE);
this.teamColor = NamedTextColor.ofExact(reader.readVarInt());
this.teamPrefix = reader.readComponent(Integer.MAX_VALUE);
this.teamSuffix = reader.readComponent(Integer.MAX_VALUE);
break;
case REMOVE_TEAM:

View File

@ -2,6 +2,7 @@ package net.minestom.server.particle;
import net.minestom.server.network.packet.server.play.ParticlePacket;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.Nullable;
import java.util.function.Consumer;
@ -13,7 +14,7 @@ public class ParticleCreator {
public static ParticlePacket createParticlePacket(Particle particleType, boolean distance,
double x, double y, double z,
float offsetX, float offsetY, float offsetZ,
float particleData, int count, Consumer<BinaryWriter> dataWriter) {
float particleData, int count, @Nullable Consumer<BinaryWriter> dataWriter) {
ParticlePacket particlePacket = new ParticlePacket();
particlePacket.particleId = particleType.getId();
particlePacket.longDistance = distance;
@ -28,7 +29,14 @@ public class ParticleCreator {
particlePacket.particleData = particleData;
particlePacket.particleCount = count;
particlePacket.dataConsumer = dataWriter;
if(dataWriter != null) {
BinaryWriter writer = new BinaryWriter();
dataWriter.accept(writer);
particlePacket.data = writer.toByteArray();
} else {
particlePacket.data = new byte[0];
}
return particlePacket;
}

View File

@ -136,7 +136,15 @@ public class BinaryReader extends InputStream {
return array;
}
/**
* @deprecated Use {@link #readRemainingBytes()} (same semantics, but more consistent naming)
*/
@Deprecated
public byte[] getRemainingBytes() {
return readRemainingBytes();
}
public byte[] readRemainingBytes() {
return readBytes(buffer.readableBytes());
}

View File

@ -6,6 +6,7 @@ import io.netty.buffer.Unpooled;
import net.kyori.adventure.text.Component;
import net.minestom.server.MinecraftServer;
import net.minestom.server.adventure.AdventureSerializer;
import net.minestom.server.chat.JsonMessage;
import net.minestom.server.item.ItemStack;
import net.minestom.server.utils.BlockPosition;
import net.minestom.server.utils.NBTUtils;
@ -176,6 +177,15 @@ public class BinaryWriter extends OutputStream {
buffer.writeCharSequence(string, StandardCharsets.UTF_8);
}
/**
* Writes a JsonMessage to the buffer.
* Simply a writeSizedString with message.toString()
* @param message
*/
public void writeJsonMessage(JsonMessage message) {
writeSizedString(message.toString());
}
/**
* Writes a var-int array to the buffer.
* <p>
@ -327,4 +337,8 @@ public class BinaryWriter extends OutputStream {
public void write(int b) {
writeByte((byte) b);
}
public void writeUnsignedShort(int yourShort) {
buffer.writeShort(yourShort & 0xFFFF);
}
}

View File

@ -296,4 +296,24 @@ public final class ChunkUtils {
return (byte) (index >> 12 & 0xF);
}
/**
* Returns the section, from a chunk index encoded with {@link #getChunkIndexWithSection(int, int, int)}
*/
public static int getSectionFromChunkIndexWithSection(long index) {
return (int) (index & 1048575L);
}
/**
* Returns the chunk X, from a chunk index encoded with {@link #getChunkIndexWithSection(int, int, int)}
*/
public static int getChunkXFromChunkIndexWithSection(long index) {
return (int) ((index >> 42) & 4194303L);
}
/**
* Returns the chunk Z, from a chunk index encoded with {@link #getChunkIndexWithSection(int, int, int)}
*/
public static int getChunkZFromChunkIndexWithSection(long index) {
return (int) ((index >> 20) & 4194303L);
}
}

View File

@ -13,6 +13,7 @@ import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.LinkedList;
@ -55,7 +56,9 @@ public class ReadWritePackets {
MinecraftServer.init();
BinaryWriter writer = new BinaryWriter();
T packet = (T) clazz.getConstructor().newInstance();
Constructor<?> constructor = clazz.getDeclaredConstructor();
constructor.setAccessible(true);
T packet = (T) constructor.newInstance();
// write packet
packet.write(writer);