Tests to check which packets fail to write then read properly

This commit is contained in:
jglrxavpok 2021-02-05 21:18:40 +01:00
parent b29217e076
commit 7b8a8e3eb0
29 changed files with 500 additions and 21 deletions

View File

@ -140,7 +140,7 @@ dependencies {
api 'org.apache.logging.log4j:log4j-slf4j-impl:2.14.0'
// Guava 21.0+ required for Mixin, but Authlib imports 17.0
api 'com.google.guava:guava:21.0'
api 'com.google.guava:guava:30.1-jre'
api 'com.mojang:authlib:1.5.21'
// Code modification

View File

@ -35,7 +35,7 @@ public class InventoryData extends DataType<Inventory> {
// Read all item stacks
for (int i = 0; i < size; i++) {
inventory.setItemStack(i, reader.readSlot());
inventory.setItemStack(i, reader.readItemStack());
}
return inventory;

View File

@ -15,6 +15,6 @@ public class ItemStackData extends DataType<ItemStack> {
@NotNull
@Override
public ItemStack decode(@NotNull BinaryReader reader) {
return reader.readSlot();
return reader.readItemStack();
}
}

View File

@ -20,7 +20,7 @@ public class ItemStackArrayData extends DataType<ItemStack[]> {
public ItemStack[] decode(@NotNull BinaryReader reader) {
ItemStack[] items = new ItemStack[reader.readVarInt()];
for (int i = 0; i < items.length; i++) {
items[i] = reader.readSlot();
items[i] = reader.readItemStack();
}
return items;
}

View File

@ -19,7 +19,7 @@ public class Tag {
private Set<NamespaceID> values;
/**
* Creates a new empty tag
* Creates a new empty tag. This does not cache the tag.
*/
public Tag(NamespaceID name) {
this.name = name;
@ -27,6 +27,15 @@ public class Tag {
lockValues();
}
/**
* Creates a new tag with the given values. This does not cache the tag.
*/
public Tag(NamespaceID name, Set<NamespaceID> values) {
this.name = name;
this.values = new HashSet<>(values);
lockValues();
}
/**
* Creates a new tag with the contents of the container
* @param manager Used to load tag contents (as tags are valid values inside 'values')

View File

@ -1,10 +1,18 @@
package net.minestom.server.network.packet.client;
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;
/**
* Represents a packet received from a client.
*/
public interface ClientPacket extends Readable {
public interface ClientPacket extends Readable, Writeable {
@Override
default void write(@NotNull BinaryWriter writer) {
// FIXME: remove when all packets are written and read properly
throw new UnsupportedOperationException("WIP: This packet is not setup to be written from Minestom code at the moment.");
}
}

View File

@ -21,6 +21,6 @@ public class ClientClickWindowPacket extends ClientPlayPacket {
this.button = reader.readByte();
this.actionNumber = reader.readShort();
this.mode = reader.readVarInt();
this.item = reader.readSlot();
this.item = reader.readItemStack();
}
}

View File

@ -13,6 +13,6 @@ public class ClientCreativeInventoryActionPacket extends ClientPlayPacket {
@Override
public void read(@NotNull BinaryReader reader) {
this.slot = reader.readShort();
this.item = reader.readSlot();
this.item = reader.readItemStack();
}
}

View File

@ -14,7 +14,7 @@ public class ClientEditBookPacket extends ClientPlayPacket {
@Override
public void read(@NotNull BinaryReader reader) {
this.book = reader.readSlot();
this.book = reader.readItemStack();
this.isSigning = reader.readBoolean();
this.hand = Player.Hand.values()[reader.readVarInt()];
}

View File

@ -1,21 +1,23 @@
package net.minestom.server.network.packet.server;
import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.utils.binary.BinaryWriter;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.Readable;
import net.minestom.server.utils.binary.Writeable;
import org.jetbrains.annotations.NotNull;
import java.nio.CharBuffer;
/**
* Represents a packet which can be sent to a player using {@link PlayerConnection#sendPacket(ServerPacket)}.
*/
public interface ServerPacket extends Writeable {
public interface ServerPacket extends Readable, Writeable {
/**
* Writes the packet to a {@link BinaryWriter}.
*
* @param writer the writer to write the packet to.
*/
void write(@NotNull BinaryWriter writer);
@Override
default void read(@NotNull BinaryReader reader) {
// FIXME: remove when all packets are written and read properly
throw new UnsupportedOperationException("WIP: This packet is not set up to be read from Minestom code at the moment.");
}
/**
* Gets the id of this packet.

View File

@ -1,14 +1,20 @@
package net.minestom.server.network.packet.server.play;
import net.minestom.server.MinecraftServer;
import net.minestom.server.entity.EntityType;
import net.minestom.server.fluids.Fluid;
import net.minestom.server.gamedata.tags.Tag;
import net.minestom.server.instance.block.Block;
import net.minestom.server.item.Material;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.registry.Registries;
import net.minestom.server.utils.NamespaceID;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
@ -27,6 +33,11 @@ public class TagsPacket implements ServerPacket {
MinecraftServer.getTagManager().addRequiredTagsToPacket(REQUIRED_TAGS_PACKET);
}
/**
* Default constructor, required for reflection operations.
*/
public TagsPacket() {}
@Override
public void write(@NotNull BinaryWriter writer) {
writeTags(writer, blockTags, name -> Registries.getBlock(name).ordinal());
@ -35,6 +46,14 @@ public class TagsPacket implements ServerPacket {
writeTags(writer, entityTags, name -> Registries.getEntityType(name).ordinal());
}
@Override
public void read(@NotNull BinaryReader reader) {
readTags(reader, blockTags, id -> NamespaceID.from("minecraft", Block.values()[id].getName()));
readTags(reader, itemTags, id -> NamespaceID.from("minecraft", Material.values()[id].getName()));
readTags(reader, fluidTags, id -> NamespaceID.from(Fluid.values()[id].getNamespaceID()));
readTags(reader, entityTags, id -> NamespaceID.from(EntityType.values()[id].getNamespaceID()));
}
private void writeTags(BinaryWriter writer, List<Tag> tags, Function<NamespaceID, Integer> idSupplier) {
writer.writeVarInt(tags.size());
for (Tag tag : tags) {
@ -51,6 +70,23 @@ public class TagsPacket implements ServerPacket {
}
}
public void readTags(BinaryReader reader, List<Tag> output, Function<Integer, NamespaceID> idSupplier) {
output.clear();
int length = reader.readVarInt();
for (int i = 0; i < length; i++) {
String name = reader.readSizedString(Integer.MAX_VALUE);
int count = reader.readVarInt();
Set<NamespaceID> values = new HashSet<>();
for (int j = 0; j < count; j++) {
int protocolID = reader.readVarInt();
values.add(idSupplier.apply(protocolID));
}
output.add(new Tag(NamespaceID.from(name), values));
}
}
@Override
public int getId() {
return ServerPacketIdentifier.TAGS;

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;
@ -10,12 +11,23 @@ public class TimeUpdatePacket implements ServerPacket {
public long worldAge;
public long timeOfDay;
/**
* Default constructor, required for reflection operations.
*/
public TimeUpdatePacket() {}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeLong(worldAge);
writer.writeLong(timeOfDay);
}
@Override
public void read(@NotNull BinaryReader reader) {
worldAge = reader.readLong();
timeOfDay = reader.readLong();
}
@Override
public int getId() {
return ServerPacketIdentifier.TIME_UPDATE;

View File

@ -6,6 +6,7 @@ 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.TickUtils;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.apache.commons.lang3.Validate;
import org.jetbrains.annotations.NotNull;
@ -67,6 +68,10 @@ public class TitlePacket implements ComponentHoldingServerPacket {
this.fadeOut = fadeOut;
}
public TitlePacket() {
this(SET_TITLE, Component.empty());
}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeVarInt(action.ordinal());
@ -88,6 +93,27 @@ public class TitlePacket implements ComponentHoldingServerPacket {
}
}
@Override
public void read(@NotNull BinaryReader reader) {
action = Action.values()[reader.readVarInt()];
switch (action) {
case SET_TITLE:
case SET_SUBTITLE:
case SET_ACTION_BAR:
payload = reader.readComponent(Integer.MAX_VALUE);
break;
case SET_TIMES_AND_DISPLAY:
fadeIn = reader.readInt();
stay = reader.readInt();
fadeOut = reader.readInt();
case HIDE:
case RESET:
break;
}
}
@Override
public int getId() {
return ServerPacketIdentifier.TITLE;

View File

@ -3,7 +3,10 @@ package net.minestom.server.network.packet.server.play;
import net.minestom.server.item.ItemStack;
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;
public class TradeListPacket implements ServerPacket {
@ -15,6 +18,13 @@ public class TradeListPacket implements ServerPacket {
public boolean regularVillager;
public boolean canRestock;
/**
* Default constructor, required for reflection operations.
*/
public TradeListPacket() {
trades = new Trade[0];
}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeVarInt(windowId);
@ -28,12 +38,28 @@ public class TradeListPacket implements ServerPacket {
writer.writeBoolean(canRestock);
}
@Override
public void read(@NotNull BinaryReader reader) {
windowId = reader.readVarInt();
byte tradeCount = reader.readByte();
trades = new Trade[tradeCount];
for (int i = 0; i < tradeCount; i++) {
trades[i] = new Trade();
trades[i].read(reader);
}
villagerLevel = reader.readVarInt();
experience = reader.readVarInt();
regularVillager = reader.readBoolean();
canRestock = reader.readBoolean();
}
@Override
public int getId() {
return ServerPacketIdentifier.TRADE_LIST;
}
public static class Trade {
public static class Trade implements Writeable, Readable {
public ItemStack inputItem1;
public ItemStack result;
@ -46,8 +72,8 @@ public class TradeListPacket implements ServerPacket {
public float priceMultiplier;
public int demand;
private void write(BinaryWriter writer) {
@Override
public void write(BinaryWriter writer) {
boolean hasSecondItem = inputItem2 != null;
writer.writeItemStack(inputItem1);
@ -64,6 +90,26 @@ public class TradeListPacket implements ServerPacket {
writer.writeInt(demand);
}
@Override
public void read(@NotNull BinaryReader reader) {
inputItem1 = reader.readItemStack();
result = reader.readItemStack();
boolean hasSecondItem = reader.readBoolean();
if(hasSecondItem) {
inputItem2 = reader.readItemStack();
} else {
inputItem2 = null;
}
tradeDisabled = reader.readBoolean();
tradeUsesNumber = reader.readInt();
maxTradeUsesNumber = reader.readInt();
exp = reader.readInt();
specialPrice = reader.readInt();
priceMultiplier = reader.readFloat();
demand = reader.readInt();
}
}
}

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,12 +10,23 @@ public class UnloadChunkPacket implements ServerPacket {
public int chunkX, chunkZ;
/**
* Default constructor, required for reflection operations.
*/
public UnloadChunkPacket() {}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeInt(chunkX);
writer.writeInt(chunkZ);
}
@Override
public void read(@NotNull BinaryReader reader) {
chunkX = reader.readInt();
chunkZ = reader.readInt();
}
@Override
public int getId() {
return ServerPacketIdentifier.UNLOAD_CHUNK;

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;
@ -19,6 +20,14 @@ public class UnlockRecipesPacket implements ServerPacket {
// Only if mode = 0
public String[] initRecipesId;
/**
* Default constructor, required for reflection operations.
*/
public UnlockRecipesPacket() {
recipesId = new String[0];
initRecipesId = new String[0];
}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeVarInt(mode);
@ -41,6 +50,30 @@ public class UnlockRecipesPacket implements ServerPacket {
}
}
@Override
public void read(@NotNull BinaryReader reader) {
mode = reader.readVarInt();
craftingRecipeBookOpen = reader.readBoolean();
craftingRecipeBookFilterActive = reader.readBoolean();
smeltingRecipeBookOpen = reader.readBoolean();
smeltingRecipeBookFilterActive = reader.readBoolean();
int length = reader.readVarInt();
recipesId = new String[length];
for (int i = 0; i < length; i++) {
recipesId[i] = reader.readSizedString(Integer.MAX_VALUE);
}
if(mode == 0) {
int initRecipesLength = reader.readVarInt();
initRecipesId = new String[initRecipesLength];
for (int i = 0; i < length; i++) {
initRecipesId[i] = reader.readSizedString(Integer.MAX_VALUE);
}
}
}
@Override
public int getId() {
return ServerPacketIdentifier.UNLOCK_RECIPES;

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;
@ -11,6 +12,11 @@ public class UpdateHealthPacket implements ServerPacket {
public int food;
public float foodSaturation;
/**
* Default constructor, required for reflection operations.
*/
public UpdateHealthPacket() {}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeFloat(health);
@ -18,6 +24,13 @@ public class UpdateHealthPacket implements ServerPacket {
writer.writeFloat(foodSaturation);
}
@Override
public void read(@NotNull BinaryReader reader) {
health = reader.readFloat();
food = reader.readVarInt();
foodSaturation = reader.readFloat();
}
@Override
public int getId() {
return ServerPacketIdentifier.UPDATE_HEALTH;

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 net.minestom.server.utils.cache.CacheablePacket;
import net.minestom.server.utils.cache.TemporaryCache;
@ -9,6 +10,8 @@ import net.minestom.server.utils.cache.TimedBuffer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
@ -36,9 +39,25 @@ public class UpdateLightPacket implements ServerPacket, CacheablePacket {
private final UUID identifier;
private final long timestamp;
/**
* Default constructor, required for reflection operations.
* This one will make a packet that is not meant to be cached
*/
public UpdateLightPacket() {
this(UUID.randomUUID(), Long.MAX_VALUE);
for (int i = 0; i < 14; i++) {
skyLight.add(new byte[2048]);
}
for (int i = 0; i < 6; i++) {
blockLight.add(new byte[2048]);
}
}
public UpdateLightPacket(@Nullable UUID identifier, long timestamp) {
this.identifier = identifier;
this.timestamp = timestamp;
skyLight = new ArrayList<>(14);
blockLight = new ArrayList<>(6);
}
@Override
@ -67,6 +86,44 @@ public class UpdateLightPacket implements ServerPacket, CacheablePacket {
}
}
@Override
public void read(@NotNull BinaryReader reader) {
chunkX = reader.readVarInt();
chunkZ = reader.readVarInt();
trustEdges = reader.readBoolean();
skyLightMask = reader.readVarInt();
blockLightMask = reader.readVarInt();
emptySkyLightMask = reader.readVarInt();
emptyBlockLightMask = reader.readVarInt();
// sky light
skyLight.clear();
for (int i = 0; i < 14; i++) {
int length = reader.readVarInt();
if(length != 2048) {
throw new IllegalStateException("Length must be 2048.");
}
byte[] bytes = reader.readBytes(length);
skyLight.add(bytes);
}
// block light
blockLight.clear();
for (int i = 0; i < 6; i++) {
int length = reader.readVarInt();
if(length != 2048) {
throw new IllegalStateException("Length must be 2048.");
}
byte[] bytes = reader.readBytes(length);
blockLight.add(bytes);
}
}
@Override
public int getId() {
return ServerPacketIdentifier.UPDATE_LIGHT;

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;
@ -12,6 +13,14 @@ public class UpdateScorePacket implements ServerPacket {
public String objectiveName;
public int value;
/**
* Default constructor, required for reflection operations.
*/
public UpdateScorePacket() {
entityName = "";
objectiveName = "";
}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeSizedString(entityName);
@ -22,6 +31,16 @@ public class UpdateScorePacket implements ServerPacket {
}
}
@Override
public void read(@NotNull BinaryReader reader) {
entityName = reader.readSizedString(Integer.MAX_VALUE);
action = reader.readByte();
objectiveName = reader.readSizedString(Integer.MAX_VALUE);
if(action != 1) {
value = reader.readVarInt();
}
}
@Override
public int getId() {
return ServerPacketIdentifier.UPDATE_SCORE;

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,11 +10,21 @@ public class UpdateViewDistancePacket implements ServerPacket {
public int viewDistance;
/**
* Default constructor, required for reflection operations.
*/
public UpdateViewDistancePacket() {}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeVarInt(viewDistance);
}
@Override
public void read(@NotNull BinaryReader reader) {
viewDistance = reader.readVarInt();
}
@Override
public int getId() {
return ServerPacketIdentifier.UPDATE_VIEW_DISTANCE;

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,12 +10,23 @@ public class UpdateViewPositionPacket implements ServerPacket {
public int chunkX, chunkZ;
/**
* Default constructor, required for reflection operations.
*/
public UpdateViewPositionPacket() {}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeVarInt(chunkX);
writer.writeVarInt(chunkZ);
}
@Override
public void read(@NotNull BinaryReader reader) {
chunkX = reader.readVarInt();
chunkZ = reader.readVarInt();
}
@Override
public int getId() {
return ServerPacketIdentifier.UPDATE_VIEW_POSITION;

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;
@ -10,6 +11,11 @@ public class VehicleMovePacket implements ServerPacket {
public double x, y, z;
public float yaw, pitch;
/**
* Default constructor, required for reflection operations.
*/
public VehicleMovePacket() {}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeDouble(x);
@ -19,6 +25,15 @@ public class VehicleMovePacket implements ServerPacket {
writer.writeFloat(pitch);
}
@Override
public void read(@NotNull BinaryReader reader) {
x = reader.readDouble();
y = reader.readDouble();
z = reader.readDouble();
yaw = reader.readFloat();
pitch = reader.readFloat();
}
@Override
public int getId() {
return ServerPacketIdentifier.VEHICLE_MOVE;

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;
@ -11,6 +12,11 @@ public class WindowConfirmationPacket implements ServerPacket {
public short actionNumber;
public boolean accepted;
/**
* Default constructor, required for reflection operations.
*/
public WindowConfirmationPacket() {}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeByte(windowId);
@ -18,6 +24,13 @@ public class WindowConfirmationPacket implements ServerPacket {
writer.writeBoolean(accepted);
}
@Override
public void read(@NotNull BinaryReader reader) {
windowId = reader.readByte();
actionNumber = reader.readShort();
accepted = reader.readBoolean();
}
@Override
public int getId() {
return ServerPacketIdentifier.WINDOW_CONFIRMATION;

View File

@ -3,6 +3,7 @@ package net.minestom.server.network.packet.server.play;
import net.minestom.server.item.ItemStack;
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;
@ -11,6 +12,11 @@ public class WindowItemsPacket implements ServerPacket {
public byte windowId;
public ItemStack[] items;
/**
* Default constructor, required for reflection operations.
*/
public WindowItemsPacket() {}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeByte(windowId);
@ -26,6 +32,17 @@ public class WindowItemsPacket implements ServerPacket {
}
}
@Override
public void read(@NotNull BinaryReader reader) {
windowId = reader.readByte();
short length = reader.readShort();
items = new ItemStack[length];
for (int i = 0; i < length; i++) {
items[i] = reader.readItemStack();
}
}
@Override
public int getId() {
return ServerPacketIdentifier.WINDOW_ITEMS;

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;
@ -11,6 +12,11 @@ public class WindowPropertyPacket implements ServerPacket {
public short property;
public short value;
/**
* Default constructor, required for reflection operations.
*/
public WindowPropertyPacket() {}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeByte(windowId);
@ -18,6 +24,13 @@ public class WindowPropertyPacket implements ServerPacket {
writer.writeShort(value);
}
@Override
public void read(@NotNull BinaryReader reader) {
windowId = reader.readByte();
property = reader.readShort();
value = reader.readShort();
}
@Override
public int getId() {
return ServerPacketIdentifier.WINDOW_PROPERTY;

View File

@ -10,6 +10,16 @@ public class WorldBorderPacket implements ServerPacket {
public Action action;
public WBAction wbAction;
private static final WBAction DEFAULT_ACTION = new WBSetSize(0.0);
/**
* Default constructor, required for reflection operations.
*/
public WorldBorderPacket() {
action = Action.SET_SIZE;
wbAction = DEFAULT_ACTION;
}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeVarInt(action.ordinal());

View File

@ -1,6 +1,7 @@
package net.minestom.server.network.packet.server.status;
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;
@ -8,6 +9,11 @@ public class PongPacket implements ServerPacket {
public long number;
/**
* Default constructor, required for reflection operations.
*/
public PongPacket() {}
public PongPacket(long number) {
this.number = number;
}
@ -17,6 +23,11 @@ public class PongPacket implements ServerPacket {
writer.writeLong(number);
}
@Override
public void read(@NotNull BinaryReader reader) {
number = reader.readLong();
}
@Override
public int getId() {
return 0x01;

View File

@ -63,10 +63,20 @@ public class BinaryReader extends InputStream {
return buffer.readUnsignedShort();
}
/**
* Same as readInt
*/
public int readInteger() {
return buffer.readInt();
}
/**
* Same as readInteger, created for parity with BinaryWriter
*/
public int readInt() {
return buffer.readInt();
}
public long readLong() {
return buffer.readLong();
}
@ -143,12 +153,20 @@ public class BinaryReader extends InputStream {
* @return the read item
* @throws NullPointerException if the item could not get read
*/
public ItemStack readSlot() {
public ItemStack readItemStack() {
final ItemStack itemStack = NBTUtils.readItemStack(this);
Check.notNull(itemStack, "#readSlot returned null, probably because the buffer was corrupted");
return itemStack;
}
/**
* Same as readItemStack
*/
@Deprecated
public ItemStack readSlot() {
return readItemStack();
}
/**
* Use {@link #readComponent(int)}
*/

View File

@ -0,0 +1,86 @@
package readwritepackets;
import com.google.common.reflect.ClassPath;
import net.minestom.server.MinecraftServer;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.network.packet.server.ServerPacket;
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.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DynamicTest;
import org.junit.jupiter.api.TestFactory;
import java.io.IOException;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
/**
* If you are using IntelliJ, set it up so that tests are run through IntelliJ and not Gradle for this collection of tests
*/
public class ReadWritePackets {
/**
* Test that all read operations on ServerPacket subclasses are implemented, and use the correct amount of memory.
* This is by no means a perfect test as some packets have variable length and content has to be validated
*/
@TestFactory
public Collection<DynamicTest> checkServerImplementationPresence() throws IOException {
return checkImplementationPresence(ServerPacket.class);
}
/**
* Test that all write operations on ClientPacket subclasses are implemented, and use the correct amount of memory.
* This is by no means a perfect test as some packets have variable length and content has to be validated
*/
@TestFactory
public Collection<DynamicTest> checkClientImplementationPresence() throws IOException {
return checkImplementationPresence(ClientPacket.class);
}
private <T extends Readable & Writeable> Collection<DynamicTest> checkImplementationPresence(Class<T> packetClass) throws IOException {
ClassPath cp = ClassPath.from(ClassLoader.getSystemClassLoader());
List<DynamicTest> allTests = new LinkedList<>();
for(ClassPath.ClassInfo classInfo : cp.getAllClasses()) {
if(!classInfo.getPackageName().startsWith("net.minestom.server.network.packet"))
continue;
try {
Class<?> clazz = classInfo.load();
if(packetClass.isAssignableFrom(clazz) && !clazz.isInterface() && ((clazz.getModifiers() & Modifier.ABSTRACT) != Modifier.ABSTRACT)) {
allTests.add(DynamicTest.dynamicTest("WriteThenRead "+clazz.getSimpleName(), () -> {
// required for managers to be loaded
MinecraftServer.init();
BinaryWriter writer = new BinaryWriter();
T packet = (T) clazz.getConstructor().newInstance();
// write packet
packet.write(writer);
// re-read packet
byte[] originalBytes = writer.toByteArray();
BinaryReader reader = new BinaryReader(originalBytes);
packet.read(reader);
Assertions.assertEquals(0, reader.getRemainingBytes().length, "Packet did not read all available data");
// re-write to ensure packet contents are the same
BinaryWriter secondWriter = new BinaryWriter();
packet.write(secondWriter);
// check that contents are the same than before read
Assertions.assertArrayEquals(originalBytes, secondWriter.toByteArray());
}));
}
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
return allTests;
}
}