immutable packets (record) (#528)

This commit is contained in:
TheMode 2021-11-30 17:49:41 +01:00
parent 07ebd196a8
commit 05de99f45f
234 changed files with 2423 additions and 5682 deletions

View File

@ -102,11 +102,8 @@ public class Demo {
MinecraftServer.getSchedulerManager().buildTask(() -> {
renderingCode.accept(framebuffer);
for (int i = 0; i < subviews.length; i++) {
final MapDataPacket packet = new MapDataPacket();
packet.mapId = mapIDStart + i;
Framebuffer f = subviews[i];
f.preparePacket(packet);
MapDataPacket packet = f.preparePacket(mapIDStart + i);
sendPacket(packet);
}
}).repeat(15, TimeUnit.MILLISECOND).schedule();

View File

@ -10,6 +10,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Date;
import java.util.List;
import java.util.Set;
/**
@ -284,33 +285,14 @@ public class Advancement {
this.parent = parent;
}
@NotNull
protected AdvancementsPacket.ProgressMapping toProgressMapping() {
AdvancementsPacket.ProgressMapping progressMapping = new AdvancementsPacket.ProgressMapping();
{
AdvancementsPacket.AdvancementProgress advancementProgress = new AdvancementsPacket.AdvancementProgress();
advancementProgress.criteria = new AdvancementsPacket.Criteria[]{criteria};
progressMapping.key = identifier;
progressMapping.value = advancementProgress;
}
return progressMapping;
protected @NotNull AdvancementsPacket.ProgressMapping toProgressMapping() {
final var advancementProgress = new AdvancementsPacket.AdvancementProgress(List.of(criteria));
return new AdvancementsPacket.ProgressMapping(identifier, advancementProgress);
}
@NotNull
protected AdvancementsPacket.DisplayData toDisplayData() {
AdvancementsPacket.DisplayData displayData = new AdvancementsPacket.DisplayData();
displayData.x = x;
displayData.y = y;
displayData.title = title;
displayData.description = description;
displayData.icon = icon;
displayData.frameType = frameType;
displayData.flags = getFlags();
if (background != null) {
displayData.backgroundTexture = background;
}
return displayData;
protected @NotNull AdvancementsPacket.DisplayData toDisplayData() {
return new AdvancementsPacket.DisplayData(title, description, icon,
frameType, getFlags(), background, x, y);
}
/**
@ -318,31 +300,13 @@ public class Advancement {
*
* @return the mapping of this advancement
*/
@NotNull
protected AdvancementsPacket.AdvancementMapping toMapping() {
AdvancementsPacket.AdvancementMapping mapping = new AdvancementsPacket.AdvancementMapping();
{
AdvancementsPacket.Advancement adv = new AdvancementsPacket.Advancement();
mapping.key = getIdentifier();
mapping.value = adv;
final Advancement parent = getParent();
if (parent != null) {
adv.parentIdentifier = parent.getIdentifier();
}
adv.displayData = toDisplayData();
adv.criterions = new String[]{criteria.criterionIdentifier};
AdvancementsPacket.Requirement requirement = new AdvancementsPacket.Requirement();
{
requirement.requirements = new String[]{criteria.criterionIdentifier};
}
adv.requirements = new AdvancementsPacket.Requirement[]{requirement};
}
return mapping;
protected @NotNull AdvancementsPacket.AdvancementMapping toMapping() {
final Advancement parent = getParent();
final String parentIdentifier = parent != null ? parent.getIdentifier() : null;
AdvancementsPacket.Advancement adv = new AdvancementsPacket.Advancement(parentIdentifier, toDisplayData(),
List.of(criteria.criterionIdentifier()),
List.of(criteria.criterionIdentifier()));
return new AdvancementsPacket.AdvancementMapping(getIdentifier(), adv);
}
/**
@ -351,16 +315,8 @@ public class Advancement {
* @return the packet to add this advancement
*/
protected AdvancementsPacket getUpdatePacket() {
AdvancementsPacket advancementsPacket = new AdvancementsPacket();
advancementsPacket.resetAdvancements = false;
final AdvancementsPacket.AdvancementMapping mapping = toMapping();
advancementsPacket.identifiersToRemove = new String[]{};
advancementsPacket.advancementMappings = new AdvancementsPacket.AdvancementMapping[]{mapping};
advancementsPacket.progressMappings = new AdvancementsPacket.ProgressMapping[]{toProgressMapping()};
return advancementsPacket;
return new AdvancementsPacket(false, List.of(toMapping()),
List.of(), List.of(toProgressMapping()));
}
/**
@ -379,16 +335,9 @@ public class Advancement {
}
protected void updateCriteria() {
this.criteria = new AdvancementsPacket.Criteria();
{
AdvancementsPacket.CriterionProgress progress = new AdvancementsPacket.CriterionProgress();
progress.achieved = achieved;
if (achieved) {
progress.dateOfAchieving = new Date(System.currentTimeMillis()).getTime();
}
this.criteria.criterionProgress = progress;
this.criteria.criterionIdentifier = identifier;
}
Long achievedDate = achieved ? new Date(System.currentTimeMillis()).getTime() : null;
final var progress = new AdvancementsPacket.CriterionProgress(achievedDate);
this.criteria = new AdvancementsPacket.Criteria(identifier, progress);
}
private int getFlags() {

View File

@ -87,24 +87,14 @@ public class AdvancementTab implements Viewable {
*
* @return the packet adding this advancement tab and all its advancements
*/
@NotNull
protected AdvancementsPacket createPacket() {
AdvancementsPacket advancementsPacket = new AdvancementsPacket();
advancementsPacket.resetAdvancements = false;
protected @NotNull AdvancementsPacket createPacket() {
List<AdvancementsPacket.AdvancementMapping> mappings = new ArrayList<>();
List<AdvancementsPacket.ProgressMapping> progressMappings = new ArrayList<>();
for (Advancement advancement : advancementMap.keySet()) {
mappings.add(advancement.toMapping());
progressMappings.add(advancement.toProgressMapping());
}
advancementsPacket.identifiersToRemove = new String[]{};
advancementsPacket.advancementMappings = mappings.toArray(new AdvancementsPacket.AdvancementMapping[0]);
advancementsPacket.progressMappings = progressMappings.toArray(new AdvancementsPacket.ProgressMapping[0]);
return advancementsPacket;
return new AdvancementsPacket(false, mappings, List.of(), progressMappings);
}
/**

View File

@ -8,6 +8,7 @@ import net.minestom.server.utils.advancement.AdvancementUtils;
import java.sql.Date;
import java.util.Collection;
import java.util.List;
/**
* Used to send one or multiples {@link Notification}.
@ -58,72 +59,23 @@ public class NotificationCenter {
* @return the packet used to show the Toast
*/
private static AdvancementsPacket getCreatePacket(Notification notification) {
// For An advancement to be shown, it must have all of it's criteria achieved (progress 100%)
// For An advancement to be shown, it must have all of its criteria achieved (progress 100%)
// Create a Criteria that we can set to 100% achieved.
// Criteria
final var displayData = new AdvancementsPacket.DisplayData(
notification.getTitle(), Component.text("Articdive was here. #Minestom"),
notification.getIcon(), notification.getFrameType(),
0x6, null, 0f, 0f);
AdvancementsPacket.Criteria criteria = new AdvancementsPacket.Criteria();
{
AdvancementsPacket.CriterionProgress progress = new AdvancementsPacket.CriterionProgress();
progress.achieved = true;
progress.dateOfAchieving = new Date(System.currentTimeMillis()).getTime();
criteria.criterionProgress = progress;
criteria.criterionIdentifier = "minestom:some_criteria";
}
final var criteria = new AdvancementsPacket.Criteria("minestom:some_criteria",
new AdvancementsPacket.CriterionProgress(new Date(System.currentTimeMillis()).getTime()));
// Now create an AdvancementsPacket that we can send:
AdvancementsPacket advancementsPacket = new AdvancementsPacket();
advancementsPacket.resetAdvancements = false;
final var advancement = new AdvancementsPacket.Advancement(null, displayData,
List.of(criteria.criterionIdentifier()), List.of(criteria.criterionIdentifier()));
AdvancementsPacket.AdvancementMapping mapping = new AdvancementsPacket.AdvancementMapping();
{
// Get the advancement
AdvancementsPacket.Advancement advancement = new AdvancementsPacket.Advancement();
// Setup display data for the advancement
AdvancementsPacket.DisplayData displayData = new AdvancementsPacket.DisplayData();
{
displayData.title = notification.getTitle();
// Description is required, but never shown/seen so, small Easter egg.
displayData.description = Component.text("Articdive was here. #Minestom");
displayData.icon = notification.getIcon();
displayData.frameType = notification.getFrameType();
displayData.flags = 0x6;
// No background texture required as we are using 0x6
displayData.x = 0.0F;
displayData.y = 0.0F;
}
advancement.displayData = displayData;
// Add the criteria to the advancement
advancement.criterions = new String[]{criteria.criterionIdentifier};
// Add the requirement of the criteria to the advancement
AdvancementsPacket.Requirement requirement = new AdvancementsPacket.Requirement();
{
requirement.requirements = new String[]{criteria.criterionIdentifier};
}
advancement.requirements = new AdvancementsPacket.Requirement[]{requirement};
final var mapping = new AdvancementsPacket.AdvancementMapping(IDENTIFIER, advancement);
final var progressMapping = new AdvancementsPacket.ProgressMapping(IDENTIFIER,
new AdvancementsPacket.AdvancementProgress(List.of(criteria)));
mapping.key = IDENTIFIER;
mapping.value = advancement;
}
// Add the mapping to the main packet
advancementsPacket.advancementMappings = new AdvancementsPacket.AdvancementMapping[]{mapping};
// We have no identifiers to remove.
advancementsPacket.identifiersToRemove = new String[]{};
// Now we need to set the player's progress for the criteria.
AdvancementsPacket.ProgressMapping progressMapping = new AdvancementsPacket.ProgressMapping();
{
AdvancementsPacket.AdvancementProgress advancementProgress = new AdvancementsPacket.AdvancementProgress();
advancementProgress.criteria = new AdvancementsPacket.Criteria[]{criteria};
progressMapping.key = IDENTIFIER;
progressMapping.value = advancementProgress;
}
advancementsPacket.progressMappings = new AdvancementsPacket.ProgressMapping[]{progressMapping};
return advancementsPacket;
return new AdvancementsPacket(false, List.of(mapping), List.of(), List.of(progressMapping));
}
}

View File

@ -10,6 +10,7 @@ import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.title.Title;
import net.kyori.adventure.title.TitlePart;
import net.minestom.server.coordinate.Pos;
import net.minestom.server.entity.Entity;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.play.*;
@ -110,25 +111,11 @@ public class AdventurePacketConvertor {
public static @NotNull ServerPacket createSoundPacket(@NotNull Sound sound, double x, double y, double z) {
final SoundEvent minestomSound = SoundEvent.fromNamespaceId(sound.name().asString());
if (minestomSound == null) {
final NamedSoundEffectPacket packet = new NamedSoundEffectPacket();
packet.soundName = sound.name().asString();
packet.soundSource = sound.source();
packet.x = (int) x;
packet.y = (int) y;
packet.z = (int) z;
packet.volume = sound.volume();
packet.pitch = sound.pitch();
return packet;
return new NamedSoundEffectPacket(sound.name().asString(), sound.source(),
(int) x, (int) y, (int) z, sound.volume(), sound.pitch());
} else {
final SoundEffectPacket packet = new SoundEffectPacket();
packet.soundId = minestomSound.id();
packet.soundSource = sound.source();
packet.x = (int) x;
packet.y = (int) y;
packet.z = (int) z;
packet.volume = sound.volume();
packet.pitch = sound.pitch();
return packet;
return new SoundEffectPacket(minestomSound.id(), sound.source(),
(int) x, (int) y, (int) z, sound.volume(), sound.pitch());
}
}
@ -148,24 +135,11 @@ public class AdventurePacketConvertor {
final SoundEvent minestomSound = SoundEvent.fromNamespaceId(sound.name().asString());
if (minestomSound != null) {
final EntitySoundEffectPacket packet = new EntitySoundEffectPacket();
packet.soundId = minestomSound.id();
packet.soundSource = sound.source();
packet.entityId = entity.getEntityId();
packet.volume = sound.volume();
packet.pitch = sound.pitch();
return packet;
return new EntitySoundEffectPacket(minestomSound.id(), sound.source(), entity.getEntityId(), sound.volume(), sound.pitch());
} else {
final var pos = entity.getPosition();
final NamedSoundEffectPacket packet = new NamedSoundEffectPacket();
packet.soundName = sound.name().asString();
packet.soundSource = sound.source();
packet.x = (int) pos.x();
packet.y = (int) pos.y();
packet.z = (int) pos.z();
packet.volume = sound.volume();
packet.pitch = sound.pitch();
return packet;
final Pos pos = entity.getPosition();
return new NamedSoundEffectPacket(sound.name().asString(), sound.source(),
(int) pos.x(), (int) pos.y(), (int) pos.z(), sound.volume(), sound.pitch());
}
}
@ -189,30 +163,27 @@ public class AdventurePacketConvertor {
* @return the sound stop packet
*/
public static ServerPacket createSoundStopPacket(@NotNull SoundStop stop) {
StopSoundPacket packet = new StopSoundPacket();
packet.flags = 0x0;
byte flags = 0x0;
Sound.Source source = stop.source();
String sound = null;
final Sound.Source source = stop.source();
if (source != null) {
packet.flags |= 0x1;
packet.source = AdventurePacketConvertor.getSoundSourceValue(source);
if (source != null) flags |= 0x1;
final Key soundKey = stop.sound();
if (soundKey != null) {
flags |= 0x2;
sound = soundKey.asString();
}
final Key sound = stop.sound();
if (sound != null) {
packet.flags |= 0x2;
packet.sound = sound.asString();
}
return packet;
return new StopSoundPacket(flags, source, sound);
}
/**
* Creates one of the three title packets from a title part and a value.
*
* @param part the part
* @param part the part
* @param value the value
* @param <T> the type of the part
* @param <T> the type of the part
* @return the title packet
*/
public static <T> @NotNull ServerPacket createTitlePartPacket(@NotNull TitlePart<T> part, @NotNull T value) {

View File

@ -78,7 +78,7 @@ public interface PacketGroupingAudience extends ForwardingAudience {
@Override
default void clearTitle() {
sendGroupedPacket(new ClearTitlesPacket());
sendGroupedPacket(new ClearTitlesPacket(false));
}
@Override

View File

@ -12,9 +12,6 @@ import java.util.Collections;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.function.Consumer;
import static net.minestom.server.network.packet.server.play.BossBarPacket.Action.*;
/**
* A holder of a boss bar. This class is not intended for public use, instead you should
@ -31,32 +28,23 @@ final class BossBarHolder implements Viewable {
}
@NotNull BossBarPacket createRemovePacket() {
return this.createGenericPacket(REMOVE, packet -> { });
return new BossBarPacket(uuid, new BossBarPacket.RemoveAction());
}
@NotNull BossBarPacket createAddPacket() {
return this.createGenericPacket(ADD, packet -> {
packet.title = bar.name();
packet.color = bar.color();
packet.overlay = bar.overlay();
packet.health = bar.progress();
packet.flags = AdventurePacketConvertor.getBossBarFlagValue(bar.flags());
});
return new BossBarPacket(uuid, new BossBarPacket.AddAction(bar));
}
@NotNull BossBarPacket createPercentUpdate(float newPercent) {
return this.createGenericPacket(UPDATE_HEALTH, packet -> packet.health = newPercent);
return new BossBarPacket(uuid, new BossBarPacket.UpdateHealthAction(newPercent));
}
@NotNull BossBarPacket createColorUpdate(@NotNull BossBar.Color color) {
return this.createGenericPacket(UPDATE_STYLE, packet -> {
packet.color = color;
packet.overlay = bar.overlay();
});
return new BossBarPacket(uuid, new BossBarPacket.UpdateStyleAction(color, bar.overlay()));
}
@NotNull BossBarPacket createTitleUpdate(@NotNull Component title) {
return this.createGenericPacket(UPDATE_TITLE, packet -> packet.title = title);
return new BossBarPacket(uuid, new BossBarPacket.UpdateTitleAction(title));
}
@NotNull BossBarPacket createFlagsUpdate() {
@ -64,22 +52,11 @@ final class BossBarHolder implements Viewable {
}
@NotNull BossBarPacket createFlagsUpdate(@NotNull Set<BossBar.Flag> newFlags) {
return this.createGenericPacket(UPDATE_FLAGS, packet -> packet.flags = AdventurePacketConvertor.getBossBarFlagValue(newFlags));
return new BossBarPacket(uuid, new BossBarPacket.UpdateFlagsAction(AdventurePacketConvertor.getBossBarFlagValue(newFlags)));
}
@NotNull BossBarPacket createOverlayUpdate(@NotNull BossBar.Overlay overlay) {
return this.createGenericPacket(UPDATE_STYLE, packet -> {
packet.overlay = overlay;
packet.color = bar.color();
});
}
private @NotNull BossBarPacket createGenericPacket(@NotNull BossBarPacket.Action action, @NotNull Consumer<BossBarPacket> consumer) {
BossBarPacket packet = new BossBarPacket();
packet.uuid = this.uuid;
packet.action = action;
consumer.accept(packet);
return packet;
return new BossBarPacket(uuid, new BossBarPacket.UpdateStyleAction(bar.color(), overlay));
}
@Override

View File

@ -177,8 +177,6 @@ public final class CommandManager {
* @return the commands packet for the specific player
*/
private @NotNull DeclareCommandsPacket buildPacket(@NotNull Player player) {
DeclareCommandsPacket declareCommandsPacket = new DeclareCommandsPacket();
List<DeclareCommandsPacket.Node> nodes = new ArrayList<>();
// Contains the children of the main node (all commands name)
IntList rootChildren = new IntArrayList();
@ -227,11 +225,7 @@ public final class CommandManager {
}
// Add root node children
rootNode.children = ArrayUtils.toArray(rootChildren);
declareCommandsPacket.nodes = nodes.toArray(new DeclareCommandsPacket.Node[0]);
declareCommandsPacket.rootIndex = 0;
return declareCommandsPacket;
return new DeclareCommandsPacket(nodes, 0);
}
private int serializeCommand(CommandSender sender, Command command,

View File

@ -677,7 +677,7 @@ public class Entity implements Viewable, Tickable, TagHandler, PermissionHandler
final List<TimedPotion> effects = this.effects;
if (effects.isEmpty()) return;
effects.removeIf(timedPotion -> {
final long potionTime = (long) timedPotion.getPotion().getDuration() * MinecraftServer.TICK_MS;
final long potionTime = (long) timedPotion.getPotion().duration() * MinecraftServer.TICK_MS;
// Remove if the potion should be expired
if (time >= timedPotion.getStartingTime() + potionTime) {
// Send the packet that the potion should no longer be applied
@ -1042,17 +1042,7 @@ public class Entity implements Viewable, Tickable, TagHandler, PermissionHandler
}
protected @NotNull SetPassengersPacket getPassengersPacket() {
SetPassengersPacket passengersPacket = new SetPassengersPacket();
passengersPacket.vehicleEntityId = getEntityId();
int[] passengers = new int[this.passengers.size()];
int counter = 0;
for (Entity passenger : this.passengers) {
passengers[counter++] = passenger.getEntityId();
}
passengersPacket.passengersId = passengers;
return passengersPacket;
return new SetPassengersPacket(getEntityId(), passengers.stream().map(Entity::getEntityId).toList());
}
/**
@ -1406,7 +1396,7 @@ public class Entity implements Viewable, Tickable, TagHandler, PermissionHandler
* @param potion The potion to add
*/
public void addEffect(@NotNull Potion potion) {
removeEffect(potion.getEffect());
removeEffect(potion.effect());
this.effects.add(new TimedPotion(potion, System.currentTimeMillis()));
potion.sendAddPacket(this);
EventDispatcher.call(new EntityPotionAddEvent(this, potion));
@ -1419,7 +1409,7 @@ public class Entity implements Viewable, Tickable, TagHandler, PermissionHandler
*/
public void removeEffect(@NotNull PotionEffect effect) {
this.effects.removeIf(timedPotion -> {
if (timedPotion.getPotion().getEffect() == effect) {
if (timedPotion.getPotion().effect() == effect) {
timedPotion.getPotion().sendRemovePacket(this);
EventDispatcher.call(new EntityPotionRemoveEvent(this, timedPotion.getPotion()));
return true;

View File

@ -1,5 +1,7 @@
package net.minestom.server.entity;
import net.minestom.server.coordinate.Point;
import net.minestom.server.coordinate.Pos;
import net.minestom.server.coordinate.Vec;
import net.minestom.server.entity.metadata.ObjectDataProvider;
import net.minestom.server.entity.metadata.other.ExperienceOrbMeta;
@ -11,37 +13,28 @@ public enum EntitySpawnType {
BASE {
@Override
public ServerPacket getSpawnPacket(Entity entity) {
SpawnEntityPacket packet = new SpawnEntityPacket();
packet.entityId = entity.getEntityId();
packet.uuid = entity.getUuid();
packet.type = entity.getEntityType().id();
packet.position = entity.getPosition();
int data = 0;
short velocityX = 0, velocityZ = 0, velocityY = 0;
if (entity.getEntityMeta() instanceof ObjectDataProvider objectDataProvider) {
packet.data = objectDataProvider.getObjectData();
data = objectDataProvider.getObjectData();
if (objectDataProvider.requiresVelocityPacketAtSpawn()) {
final var velocity = entity.getVelocityForPacket();
packet.velocityX = (short) velocity.x();
packet.velocityY = (short) velocity.y();
packet.velocityZ = (short) velocity.z();
velocityX = (short) velocity.x();
velocityY = (short) velocity.y();
velocityZ = (short) velocity.z();
}
}
return packet;
return new SpawnEntityPacket(entity.getEntityId(), entity.getUuid(), entity.getEntityType().id(),
entity.getPosition(), data, velocityX, velocityY, velocityZ);
}
},
LIVING {
@Override
public ServerPacket getSpawnPacket(Entity entity) {
SpawnLivingEntityPacket packet = new SpawnLivingEntityPacket();
packet.entityId = entity.getEntityId();
packet.entityUuid = entity.getUuid();
packet.entityType = entity.getEntityType().id();
packet.position = entity.getPosition();
packet.headPitch = entity.getPosition().pitch();
final var velocity = entity.getVelocityForPacket();
packet.velocityX = (short) velocity.x();
packet.velocityY = (short) velocity.y();
packet.velocityZ = (short) velocity.z();
return packet;
final Pos position = entity.getPosition();
final Vec velocity = entity.getVelocityForPacket();
return new SpawnLivingEntityPacket(entity.getEntityId(), entity.getUuid(), entity.getEntityType().id(),
position, position.yaw(), (short) velocity.x(), (short) velocity.y(), (short) velocity.z());
}
},
PLAYER {
@ -53,41 +46,35 @@ public enum EntitySpawnType {
EXPERIENCE_ORB {
@Override
public ServerPacket getSpawnPacket(Entity entity) {
SpawnExperienceOrbPacket packet = new SpawnExperienceOrbPacket();
packet.entityId = entity.getEntityId();
packet.position = entity.getPosition();
if (entity.getEntityMeta() instanceof ExperienceOrbMeta experienceOrbMeta) {
packet.expCount = (short) experienceOrbMeta.getCount();
}
return packet;
final short expCount = (short) (entity.getEntityMeta() instanceof ExperienceOrbMeta experienceOrbMeta ?
experienceOrbMeta.getCount() : 0);
return new SpawnExperienceOrbPacket(entity.getEntityId(), entity.getPosition(), expCount);
}
},
PAINTING {
@Override
public ServerPacket getSpawnPacket(Entity entity) {
SpawnPaintingPacket packet = new SpawnPaintingPacket();
packet.entityId = entity.getEntityId();
packet.entityUuid = entity.getUuid();
int motive = 0;
Point position = Vec.ZERO;
byte direction = 0;
if (entity.getEntityMeta() instanceof PaintingMeta paintingMeta) {
packet.motive = paintingMeta.getMotive().ordinal();
packet.position = new Vec(
motive = paintingMeta.getMotive().ordinal();
position = new Vec(
Math.max(0, (paintingMeta.getMotive().getWidth() >> 1) - 1),
paintingMeta.getMotive().getHeight() >> 1,
0
);
switch (paintingMeta.getDirection()) {
case SOUTH -> packet.direction = 0;
case WEST -> packet.direction = 1;
case NORTH -> packet.direction = 2;
case EAST -> packet.direction = 3;
}
} else {
packet.position = Vec.ZERO;
direction = switch (paintingMeta.getDirection()) {
case SOUTH -> 0;
case WEST -> 1;
case NORTH -> 2;
case EAST -> 3;
default -> 0;
};
}
return packet;
return new SpawnPaintingPacket(entity.getEntityId(), entity.getUuid(), motive, position, direction);
}
};
public abstract ServerPacket getSpawnPacket(Entity entity);
}

View File

@ -369,12 +369,8 @@ public class LivingEntity extends Entity implements EquipmentHandler {
// TODO: separate living entity categories
soundCategory = Source.HOSTILE;
}
SoundEffectPacket damageSoundPacket =
SoundEffectPacket.create(soundCategory, sound,
getPosition(),
1.0f, 1.0f);
sendPacketToViewersAndSelf(damageSoundPacket);
sendPacketToViewersAndSelf(new SoundEffectPacket(sound, soundCategory,
getPosition(), 1.0f, 1.0f));
}
});
@ -590,32 +586,11 @@ public class LivingEntity extends Entity implements EquipmentHandler {
* @param attributes the attributes to include in the packet
* @return an {@link EntityPropertiesPacket} linked to this entity
*/
@NotNull
protected EntityPropertiesPacket getPropertiesPacket(@NotNull Collection<AttributeInstance> attributes) {
protected @NotNull EntityPropertiesPacket getPropertiesPacket(@NotNull Collection<AttributeInstance> attributes) {
// Get all the attributes which should be sent to the client
final AttributeInstance[] instances = attributes.stream()
.filter(i -> i.getAttribute().isShared())
.toArray(AttributeInstance[]::new);
EntityPropertiesPacket propertiesPacket = new EntityPropertiesPacket();
propertiesPacket.entityId = getEntityId();
EntityPropertiesPacket.Property[] properties = new EntityPropertiesPacket.Property[instances.length];
for (int i = 0; i < properties.length; ++i) {
EntityPropertiesPacket.Property property = new EntityPropertiesPacket.Property();
final float value = instances[i].getBaseValue();
property.instance = instances[i];
property.attribute = instances[i].getAttribute();
property.value = value;
properties[i] = property;
}
propertiesPacket.properties = properties;
return propertiesPacket;
final List<AttributeInstance> properties = attributes.stream()
.filter(i -> i.getAttribute().isShared()).toList();
return new EntityPropertiesPacket(getEntityId(), properties);
}
@Override

View File

@ -1,7 +1,6 @@
package net.minestom.server.entity;
import net.kyori.adventure.text.Component;
import net.minestom.server.MinecraftServer;
import net.minestom.server.coordinate.Point;
import net.minestom.server.coordinate.Vec;
import net.minestom.server.item.ItemStack;
@ -15,9 +14,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.nbt.NBT;
import org.jglrxavpok.hephaistos.nbt.NBTEnd;
import org.jglrxavpok.hephaistos.nbt.NBTException;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Consumer;
@ -136,15 +133,7 @@ public class Metadata {
}
public static Value<NBT> NBT(@NotNull NBT nbt) {
return new Value<>(TYPE_NBT, nbt, writer ->
writer.writeNBT("", nbt), reader -> {
try {
return reader.readTag();
} catch (IOException | NBTException e) {
MinecraftServer.getExceptionManager().handleException(e);
return null;
}
});
return new Value<>(TYPE_NBT, nbt, writer -> writer.writeNBT("", nbt), BinaryReader::readTag);
}
public static Value<int[]> VillagerData(int villagerType,

View File

@ -46,13 +46,14 @@ import net.minestom.server.inventory.PlayerInventory;
import net.minestom.server.item.ItemStack;
import net.minestom.server.item.Material;
import net.minestom.server.item.metadata.WrittenBookMeta;
import net.minestom.server.listener.manager.PacketListenerManager;
import net.minestom.server.message.ChatMessageType;
import net.minestom.server.message.ChatPosition;
import net.minestom.server.message.Messenger;
import net.minestom.server.network.ConnectionManager;
import net.minestom.server.network.ConnectionState;
import net.minestom.server.network.PlayerProvider;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.network.packet.client.play.ClientChatMessagePacket;
import net.minestom.server.network.packet.server.SendablePacket;
import net.minestom.server.network.packet.server.ServerPacket;
@ -83,6 +84,7 @@ import org.jctools.queues.MpscUnboundedXaddArrayQueue;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
@ -101,6 +103,7 @@ import java.util.function.UnaryOperator;
public class Player extends LivingEntity implements CommandSender, Localizable, HoverEventSource<ShowEntity>, Identified, NamedAndIdentified {
private static final Component REMOVE_MESSAGE = Component.text("You have been removed from the server without reason.", NamedTextColor.RED);
private static final PacketListenerManager PACKET_LISTENER_MANAGER = MinecraftServer.getPacketListenerManager();
private long lastKeepAlive;
private boolean answerKeepAlive;
@ -137,7 +140,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
private final AtomicInteger teleportId = new AtomicInteger();
private int receivedTeleportId;
private final MessagePassingQueue<ClientPlayPacket> packets = new MpscUnboundedXaddArrayQueue<>(32);
private final MessagePassingQueue<ClientPacket> packets = new MpscUnboundedXaddArrayQueue<>(32);
private final boolean levelFlat;
private final PlayerSettings settings;
private float exp;
@ -234,15 +237,16 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
public void UNSAFE_init(@NotNull Instance spawnInstance) {
this.dimensionType = spawnInstance.getDimensionType();
JoinGamePacket joinGamePacket = new JoinGamePacket();
joinGamePacket.entityId = getEntityId();
joinGamePacket.gameMode = gameMode;
joinGamePacket.dimensionType = dimensionType;
joinGamePacket.maxPlayers = 0; // Unused
joinGamePacket.viewDistance = MinecraftServer.getChunkViewDistance();
joinGamePacket.simulationDistance = MinecraftServer.getChunkViewDistance();
joinGamePacket.reducedDebugInfo = false;
joinGamePacket.isFlat = levelFlat;
NBTCompound nbt = new NBTCompound();
NBTCompound dimensions = MinecraftServer.getDimensionTypeManager().toNBT();
NBTCompound biomes = MinecraftServer.getBiomeManager().toNBT();
nbt.set("minecraft:dimension_type", dimensions);
nbt.set("minecraft:worldgen/biome", biomes);
final JoinGamePacket joinGamePacket = new JoinGamePacket(getEntityId(), gameMode.isHardcore(), gameMode, null,
List.of("minestom:world"), nbt, dimensionType.toNBT(), dimensionType.getName().asString(),
0, 0, MinecraftServer.getChunkViewDistance(), MinecraftServer.getChunkViewDistance(),
false, true, false, levelFlat);
playerConnection.sendPacket(joinGamePacket);
// Server brand name
@ -268,10 +272,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
// Recipes start
{
RecipeManager recipeManager = MinecraftServer.getRecipeManager();
DeclareRecipesPacket declareRecipesPacket = recipeManager.getDeclareRecipesPacket();
if (declareRecipesPacket.recipes != null) {
playerConnection.sendPacket(declareRecipesPacket);
}
playerConnection.sendPacket(recipeManager.getDeclareRecipesPacket());
List<String> recipesIdentifier = new ArrayList<>();
for (Recipe recipe : recipeManager.getRecipes()) {
@ -281,11 +282,12 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
recipesIdentifier.add(recipe.getRecipeId());
}
if (!recipesIdentifier.isEmpty()) {
final String[] identifiers = recipesIdentifier.toArray(new String[0]);
UnlockRecipesPacket unlockRecipesPacket = new UnlockRecipesPacket();
unlockRecipesPacket.mode = 0;
unlockRecipesPacket.recipesId = identifiers;
unlockRecipesPacket.initRecipesId = identifiers;
UnlockRecipesPacket unlockRecipesPacket = new UnlockRecipesPacket(0,
false, false,
false, false,
false, false,
false, false,
recipesIdentifier, recipesIdentifier);
playerConnection.sendPacket(unlockRecipesPacket);
}
}
@ -315,7 +317,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
this.playerConnection.update();
// Process received packets
this.packets.drain(packet -> packet.process(this));
this.packets.drain(packet -> PACKET_LISTENER_MANAGER.processClientPacket(packet, this));
super.update(time); // Super update (item pickup/fire management)
@ -399,7 +401,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
// #buildDeathScreenText can return null, check here
if (deathText != null) {
playerConnection.sendPacket(DeathCombatEventPacket.of(getEntityId(), -1, deathText));
playerConnection.sendPacket(new DeathCombatEventPacket(getEntityId(), -1, deathText));
}
// #buildDeathMessage can return null, check here
@ -422,10 +424,8 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
setFireForDuration(0);
setOnFire(false);
refreshHealth();
RespawnPacket respawnPacket = new RespawnPacket();
respawnPacket.dimensionType = getDimensionType();
respawnPacket.gameMode = getGameMode();
respawnPacket.isFlat = levelFlat;
RespawnPacket respawnPacket = new RespawnPacket(getDimensionType(), getDimensionType().getName().asString(),
0, gameMode, gameMode, false, levelFlat, true);
getPlayerConnection().sendPacket(respawnPacket);
PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(this);
EventDispatcher.call(respawnEvent);
@ -640,9 +640,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
* @param message the message that the player will send
*/
public void chat(@NotNull String message) {
ClientChatMessagePacket chatMessagePacket = new ClientChatMessagePacket();
chatMessagePacket.message = message;
addPacketToQueue(chatMessagePacket);
addPacketToQueue(new ClientChatMessagePacket(message));
}
@Override
@ -684,12 +682,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
* @param disableRelativeVolume disable volume scaling based on distance
*/
public void playEffect(@NotNull Effects effect, int x, int y, int z, int data, boolean disableRelativeVolume) {
EffectPacket packet = new EffectPacket();
packet.effectId = effect.getId();
packet.position = new Vec(x, y, z);
packet.data = data;
packet.disableRelativeVolume = disableRelativeVolume;
playerConnection.sendPacket(packet);
playerConnection.sendPacket(new EffectPacket(effect.getId(), new Vec(x, y, z), data, disableRelativeVolume));
}
@Override
@ -714,7 +707,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
@Override
public void clearTitle() {
playerConnection.sendPacket(new ClearTitlesPacket());
playerConnection.sendPacket(new ClearTitlesPacket(false));
}
@Override
@ -870,10 +863,8 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
*/
public void setDisplayName(@Nullable Component displayName) {
this.displayName = displayName;
PlayerInfoPacket infoPacket = new PlayerInfoPacket(PlayerInfoPacket.Action.UPDATE_DISPLAY_NAME);
infoPacket.playerInfos.add(new PlayerInfoPacket.UpdateDisplayName(getUuid(), displayName));
sendPacketToViewersAndSelf(infoPacket);
final List<PlayerInfoPacket.Entry> entry = List.of(new PlayerInfoPacket.UpdateDisplayName(getUuid(), displayName));
sendPacketToViewersAndSelf(new PlayerInfoPacket(PlayerInfoPacket.Action.UPDATE_DISPLAY_NAME, entry));
}
/**
@ -904,10 +895,8 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
final PlayerInfoPacket removePlayerPacket = getRemovePlayerToList();
final PlayerInfoPacket addPlayerPacket = getAddPlayerToList();
RespawnPacket respawnPacket = new RespawnPacket();
respawnPacket.dimensionType = getDimensionType();
respawnPacket.gameMode = getGameMode();
respawnPacket.isFlat = levelFlat;
RespawnPacket respawnPacket = new RespawnPacket(getDimensionType(), getDimensionType().getName().asString(),
0, gameMode, gameMode, false, levelFlat, true);
playerConnection.sendPacket(removePlayerPacket);
playerConnection.sendPacket(destroyEntitiesPacket);
@ -982,10 +971,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
}
private void sendChangeGameStatePacket(@NotNull ChangeGameStatePacket.Reason reason, float value) {
ChangeGameStatePacket changeGameStatePacket = new ChangeGameStatePacket();
changeGameStatePacket.reason = reason;
changeGameStatePacket.value = value;
playerConnection.sendPacket(changeGameStatePacket);
playerConnection.sendPacket(new ChangeGameStatePacket(reason, value));
}
/**
@ -1038,18 +1024,13 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
private void facePosition(@NotNull FacePoint facePoint, @NotNull Point targetPosition,
@Nullable Entity entity, @Nullable FacePoint targetPoint) {
FacePlayerPacket facePlayerPacket = new FacePlayerPacket();
facePlayerPacket.entityFacePosition = facePoint == FacePoint.EYE ?
FacePlayerPacket.FacePosition.EYES : FacePlayerPacket.FacePosition.FEET;
facePlayerPacket.targetX = targetPosition.x();
facePlayerPacket.targetY = targetPosition.y();
facePlayerPacket.targetZ = targetPosition.z();
if (entity != null) {
facePlayerPacket.entityId = entity.getEntityId();
facePlayerPacket.entityFacePosition = targetPoint == FacePoint.EYE ?
FacePlayerPacket.FacePosition.EYES : FacePlayerPacket.FacePosition.FEET;
}
playerConnection.sendPacket(facePlayerPacket);
final int entityId = entity != null ? entity.getEntityId() : 0;
playerConnection.sendPacket(new FacePlayerPacket(
facePoint == FacePoint.EYE ?
FacePlayerPacket.FacePosition.EYES : FacePlayerPacket.FacePosition.FEET, targetPosition,
entityId,
targetPoint == FacePoint.EYE ?
FacePlayerPacket.FacePosition.EYES : FacePlayerPacket.FacePosition.FEET));
}
/**
@ -1247,10 +1228,8 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
// Condition to prevent sending the packets before spawning the player
if (isActive()) {
sendChangeGameStatePacket(ChangeGameStatePacket.Reason.CHANGE_GAMEMODE, gameMode.getId());
PlayerInfoPacket infoPacket = new PlayerInfoPacket(PlayerInfoPacket.Action.UPDATE_GAMEMODE);
infoPacket.playerInfos.add(new PlayerInfoPacket.UpdateGamemode(getUuid(), gameMode));
sendPacketToViewersAndSelf(infoPacket);
final List<PlayerInfoPacket.Entry> entry = List.of(new PlayerInfoPacket.UpdateGameMode(getUuid(), gameMode));
sendPacketToViewersAndSelf(new PlayerInfoPacket(PlayerInfoPacket.Action.UPDATE_GAMEMODE, entry));
}
}
@ -1273,11 +1252,8 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
Check.argCondition(dimensionType.equals(getDimensionType()),
"The dimension needs to be different than the current one!");
this.dimensionType = dimensionType;
RespawnPacket respawnPacket = new RespawnPacket();
respawnPacket.dimensionType = dimensionType;
respawnPacket.gameMode = gameMode;
respawnPacket.isFlat = levelFlat;
playerConnection.sendPacket(respawnPacket);
sendPacket(new RespawnPacket(dimensionType, dimensionType.getName().asString(),
0, gameMode, gameMode, false, levelFlat, true));
}
/**
@ -1386,10 +1362,8 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
return;
}
OpenWindowPacket openWindowPacket = new OpenWindowPacket(newInventory.getTitle());
openWindowPacket.windowId = newInventory.getWindowId();
openWindowPacket.windowType = newInventory.getInventoryType().getWindowType();
playerConnection.sendPacket(openWindowPacket);
playerConnection.sendPacket(new OpenWindowPacket(newInventory.getWindowId(),
newInventory.getInventoryType().getWindowType(), newInventory.getTitle()));
newInventory.addViewer(this);
this.openInventory = newInventory;
});
@ -1419,11 +1393,11 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
}
}
CloseWindowPacket closeWindowPacket = new CloseWindowPacket();
CloseWindowPacket closeWindowPacket;
if (openInventory == null) {
closeWindowPacket.windowId = 0;
closeWindowPacket = new CloseWindowPacket((byte) 0);
} else {
closeWindowPacket.windowId = openInventory.getWindowId();
closeWindowPacket = new CloseWindowPacket(openInventory.getWindowId());
openInventory.removeViewer(this); // Clear cache
this.openInventory = null;
}
@ -1707,7 +1681,7 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
*
* @param packet the packet to add in the queue
*/
public void addPacketToQueue(@NotNull ClientPlayPacket packet) {
public void addPacketToQueue(@NotNull ClientPacket packet) {
this.packets.offer(packet);
}
@ -1718,9 +1692,8 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
*/
public void refreshLatency(int latency) {
this.latency = latency;
PlayerInfoPacket playerInfoPacket = new PlayerInfoPacket(PlayerInfoPacket.Action.UPDATE_LATENCY);
playerInfoPacket.playerInfos.add(new PlayerInfoPacket.UpdateLatency(getUuid(), latency));
sendPacketToViewersAndSelf(playerInfoPacket);
final List<PlayerInfoPacket.Entry> entry = List.of(new PlayerInfoPacket.UpdateLatency(getUuid(), latency));
sendPacketToViewersAndSelf(new PlayerInfoPacket(PlayerInfoPacket.Action.UPDATE_LATENCY, entry));
}
public void refreshOnGround(boolean onGround) {
@ -1841,21 +1814,12 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
* @return a {@link PlayerInfoPacket} to add the player
*/
protected @NotNull PlayerInfoPacket getAddPlayerToList() {
PlayerInfoPacket playerInfoPacket = new PlayerInfoPacket(PlayerInfoPacket.Action.ADD_PLAYER);
PlayerInfoPacket.AddPlayer addPlayer =
new PlayerInfoPacket.AddPlayer(getUuid(), getUsername(), getGameMode(), getLatency());
addPlayer.displayName = displayName;
// Skin support
if (skin != null) {
PlayerInfoPacket.AddPlayer.Property prop =
new PlayerInfoPacket.AddPlayer.Property("textures", skin.textures(), skin.signature());
addPlayer.properties.add(prop);
}
playerInfoPacket.playerInfos.add(addPlayer);
return playerInfoPacket;
final PlayerSkin skin = this.skin;
List<PlayerInfoPacket.AddPlayer.Property> prop = skin != null ?
List.of(new PlayerInfoPacket.AddPlayer.Property("textures", skin.textures(), skin.signature())) :
Collections.emptyList();
final PlayerInfoPacket.Entry entry = new PlayerInfoPacket.AddPlayer(getUuid(), getUsername(), prop, getGameMode(), getLatency(), displayName);
return new PlayerInfoPacket(PlayerInfoPacket.Action.ADD_PLAYER, List.of(entry));
}
/**
@ -1864,9 +1828,8 @@ public class Player extends LivingEntity implements CommandSender, Localizable,
* @return a {@link PlayerInfoPacket} to remove the player
*/
protected @NotNull PlayerInfoPacket getRemovePlayerToList() {
PlayerInfoPacket playerInfoPacket = new PlayerInfoPacket(PlayerInfoPacket.Action.REMOVE_PLAYER);
playerInfoPacket.playerInfos.add(new PlayerInfoPacket.RemovePlayer(getUuid()));
return playerInfoPacket;
return new PlayerInfoPacket(PlayerInfoPacket.Action.REMOVE_PLAYER,
List.of(new PlayerInfoPacket.RemovePlayer(getUuid())));
}
/**

View File

@ -8,8 +8,9 @@ import net.minestom.server.inventory.AbstractInventory;
import net.minestom.server.inventory.Inventory;
import net.minestom.server.inventory.PlayerInventory;
import net.minestom.server.item.ItemStack;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.network.packet.client.play.*;
import net.minestom.server.network.packet.server.SendablePacket;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.play.KeepAlivePacket;
import net.minestom.server.network.packet.server.play.PlayerPositionAndLookPacket;
@ -19,10 +20,12 @@ import net.minestom.server.utils.inventory.PlayerInventoryUtils;
import net.minestom.server.utils.validate.Check;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* This class acts as a client controller for {@link FakePlayer}.
* <p>
* The main use is to simulate the receiving of {@link ClientPlayPacket}
* The main use is to simulate the receiving of {@link ClientPacket}
*/
public class FakePlayerController {
@ -54,13 +57,9 @@ public class FakePlayerController {
ItemStack itemStack = abstractInventory.getItemStack(slot);
ClientClickWindowPacket clickWindowPacket = new ClientClickWindowPacket();
clickWindowPacket.windowId = playerInventory ? 0 : inventory.getWindowId();
clickWindowPacket.slot = slot;
clickWindowPacket.button = button;
clickWindowPacket.clickType = clickType;
clickWindowPacket.item = itemStack;
addToQueue(clickWindowPacket);
addToQueue(new ClientClickWindowPacket(playerInventory ? 0 : inventory.getWindowId(), 0,
slot, button, clickType,
List.of(), itemStack));
}
/**
@ -68,10 +67,7 @@ public class FakePlayerController {
*/
public void closeWindow() {
Inventory openInventory = fakePlayer.getOpenInventory();
ClientCloseWindowPacket closeWindow = new ClientCloseWindowPacket();
closeWindow.windowId = openInventory == null ? 0 : openInventory.getWindowId();
addToQueue(closeWindow);
addToQueue(new ClientCloseWindowPacket(openInventory == null ? 0 : openInventory.getWindowId()));
}
/**
@ -81,10 +77,7 @@ public class FakePlayerController {
* @param message The message data.
*/
public void sendPluginMessage(String channel, byte[] message) {
ClientPluginMessagePacket pluginMessagePacket = new ClientPluginMessagePacket();
pluginMessagePacket.channel = channel;
pluginMessagePacket.data = message;
addToQueue(pluginMessagePacket);
addToQueue(new ClientPluginMessagePacket(channel, message));
}
/**
@ -103,10 +96,7 @@ public class FakePlayerController {
* @param entity The entity that is to be attacked.
*/
public void attackEntity(Entity entity) {
ClientInteractEntityPacket interactEntityPacket = new ClientInteractEntityPacket();
interactEntityPacket.targetId = entity.getEntityId();
interactEntityPacket.type = ClientInteractEntityPacket.Type.ATTACK;
addToQueue(interactEntityPacket);
addToQueue(new ClientInteractEntityPacket(entity.getEntityId(), new ClientInteractEntityPacket.Attack(), fakePlayer.isSneaking()));
}
/**
@ -131,10 +121,7 @@ public class FakePlayerController {
*/
public void setHeldItem(short slot) {
Check.argCondition(!MathUtils.isBetween(slot, 0, 8), "Slot has to be between 0 and 8!");
ClientHeldItemChangePacket heldItemChangePacket = new ClientHeldItemChangePacket();
heldItemChangePacket.slot = slot;
addToQueue(heldItemChangePacket);
addToQueue(new ClientHeldItemChangePacket(slot));
}
/**
@ -143,9 +130,7 @@ public class FakePlayerController {
* @param hand The hand of the arm to be animated.
*/
public void sendArmAnimation(Player.Hand hand) {
ClientAnimationPacket animationPacket = new ClientAnimationPacket();
animationPacket.hand = hand;
addToQueue(animationPacket);
addToQueue(new ClientAnimationPacket(hand));
}
/**
@ -154,9 +139,7 @@ public class FakePlayerController {
* @param hand The hand in which an ite mshould be.
*/
public void useItem(Player.Hand hand) {
ClientUseItemPacket useItemPacket = new ClientUseItemPacket();
useItemPacket.hand = hand;
addToQueue(useItemPacket);
addToQueue(new ClientUseItemPacket(hand));
}
/**
@ -166,11 +149,7 @@ public class FakePlayerController {
* @param pitch The new pitch for the fake player.
*/
public void rotate(float yaw, float pitch) {
ClientPlayerRotationPacket playerRotationPacket = new ClientPlayerRotationPacket();
playerRotationPacket.yaw = yaw;
playerRotationPacket.pitch = pitch;
playerRotationPacket.onGround = fakePlayer.isOnGround();
addToQueue(playerRotationPacket);
addToQueue(new ClientPlayerRotationPacket(yaw, pitch, fakePlayer.isOnGround()));
}
/**
@ -180,11 +159,7 @@ public class FakePlayerController {
* @param blockFace From where the block is struck.
*/
public void startDigging(Point blockPosition, BlockFace blockFace) {
ClientPlayerDiggingPacket playerDiggingPacket = new ClientPlayerDiggingPacket();
playerDiggingPacket.status = ClientPlayerDiggingPacket.Status.STARTED_DIGGING;
playerDiggingPacket.blockPosition = blockPosition;
playerDiggingPacket.blockFace = blockFace;
addToQueue(playerDiggingPacket);
addToQueue(new ClientPlayerDiggingPacket(ClientPlayerDiggingPacket.Status.STARTED_DIGGING, blockPosition, blockFace));
}
/**
@ -194,11 +169,7 @@ public class FakePlayerController {
* @param blockFace From where the block is struck.
*/
public void stopDigging(Point blockPosition, BlockFace blockFace) {
ClientPlayerDiggingPacket playerDiggingPacket = new ClientPlayerDiggingPacket();
playerDiggingPacket.status = ClientPlayerDiggingPacket.Status.CANCELLED_DIGGING;
playerDiggingPacket.blockPosition = blockPosition;
playerDiggingPacket.blockFace = blockFace;
addToQueue(playerDiggingPacket);
addToQueue(new ClientPlayerDiggingPacket(ClientPlayerDiggingPacket.Status.CANCELLED_DIGGING, blockPosition, blockFace));
}
/**
@ -208,29 +179,21 @@ public class FakePlayerController {
* @param blockFace From where the block is struck.
*/
public void finishDigging(Point blockPosition, BlockFace blockFace) {
ClientPlayerDiggingPacket playerDiggingPacket = new ClientPlayerDiggingPacket();
playerDiggingPacket.status = ClientPlayerDiggingPacket.Status.FINISHED_DIGGING;
playerDiggingPacket.blockPosition = blockPosition;
playerDiggingPacket.blockFace = blockFace;
addToQueue(playerDiggingPacket);
addToQueue(new ClientPlayerDiggingPacket(ClientPlayerDiggingPacket.Status.FINISHED_DIGGING, blockPosition, blockFace));
}
/**
* Makes the player receives a packet
* WARNING: pretty much unsafe, used internally to redirect packets here,
* you should instead use {@link PlayerConnection#sendPacket(ServerPacket)}
* you should instead use {@link PlayerConnection#sendPacket(SendablePacket)}
*
* @param serverPacket the packet to consume
*/
public void consumePacket(ServerPacket serverPacket) {
if (serverPacket instanceof PlayerPositionAndLookPacket) {
ClientTeleportConfirmPacket teleportConfirmPacket = new ClientTeleportConfirmPacket();
teleportConfirmPacket.teleportId = ((PlayerPositionAndLookPacket) serverPacket).teleportId;
addToQueue(teleportConfirmPacket);
} else if (serverPacket instanceof KeepAlivePacket) {
ClientKeepAlivePacket keepAlivePacket = new ClientKeepAlivePacket();
keepAlivePacket.id = ((KeepAlivePacket) serverPacket).id;
addToQueue(keepAlivePacket);
if (serverPacket instanceof PlayerPositionAndLookPacket playerPositionAndLookPacket) {
addToQueue(new ClientTeleportConfirmPacket(playerPositionAndLookPacket.teleportId()));
} else if (serverPacket instanceof KeepAlivePacket keepAlivePacket) {
addToQueue(new ClientKeepAlivePacket(keepAlivePacket.id()));
}
}
@ -240,7 +203,7 @@ public class FakePlayerController {
*
* @param clientPlayPacket The packet to add in the queue.
*/
private void addToQueue(ClientPlayPacket clientPlayPacket) {
private void addToQueue(ClientPacket clientPlayPacket) {
this.fakePlayer.addPacketToQueue(clientPlayPacket);
}
}

View File

@ -57,30 +57,22 @@ public abstract class Explosion {
*/
public void apply(@NotNull Instance instance) {
List<Point> blocks = prepare(instance);
ExplosionPacket packet = new ExplosionPacket();
packet.x = getCenterX();
packet.y = getCenterY();
packet.z = getCenterZ();
packet.radius = getStrength();
packet.playerMotionX = 0.0f; // TODO: figure out why this is here
packet.playerMotionY = 0.0f; // TODO: figure out why this is here
packet.playerMotionZ = 0.0f; // TODO: figure out why this is here
packet.records = new byte[3 * blocks.size()];
byte[] records = new byte[3 * blocks.size()];
for (int i = 0; i < blocks.size(); i++) {
final var pos = blocks.get(i);
instance.setBlock(pos, Block.AIR);
final byte x = (byte) (pos.x() - Math.floor(getCenterX()));
final byte y = (byte) (pos.y() - Math.floor(getCenterY()));
final byte z = (byte) (pos.z() - Math.floor(getCenterZ()));
packet.records[i * 3 + 0] = x;
packet.records[i * 3 + 1] = y;
packet.records[i * 3 + 2] = z;
records[i * 3 + 0] = x;
records[i * 3 + 1] = y;
records[i * 3 + 2] = z;
}
postExplosion(instance, blocks, packet);
// TODO send only to close players
ExplosionPacket packet = new ExplosionPacket(centerX, centerY, centerZ, strength,
records, 0, 0, 0);
postExplosion(instance, blocks, packet);
PacketUtils.sendGroupedPacket(instance.getPlayers(), packet);
postSend(instance, blocks);

View File

@ -102,7 +102,7 @@ public class WorldBorder {
*/
public void setWarningTime(int warningTime) {
this.warningTime = warningTime;
sendPacket(WorldBorderWarningDelayPacket.of(warningTime));
sendPacket(new WorldBorderWarningDelayPacket(warningTime));
}
public int getWarningBlocks() {
@ -114,7 +114,7 @@ public class WorldBorder {
*/
public void setWarningBlocks(int warningBlocks) {
this.warningBlocks = warningBlocks;
sendPacket(WorldBorderWarningReachPacket.of(warningBlocks));
sendPacket(new WorldBorderWarningReachPacket(warningBlocks));
}
/**
@ -131,7 +131,7 @@ public class WorldBorder {
this.newDiameter = diameter;
this.speed = speed;
this.lerpStartTime = System.currentTimeMillis();
sendPacket(WorldBorderLerpSizePacket.of(oldDiameter, newDiameter, speed));
sendPacket(new WorldBorderLerpSizePacket(oldDiameter, newDiameter, speed));
}
/**
@ -154,7 +154,7 @@ public class WorldBorder {
this.oldDiameter = diameter;
this.newDiameter = diameter;
this.lerpStartTime = 0;
sendPacket(WorldBorderSizePacket.of(diameter));
sendPacket(new WorldBorderSizePacket(diameter));
}
/**
@ -229,9 +229,8 @@ public class WorldBorder {
*/
@ApiStatus.Internal
public void init(@NotNull Player player) {
player.getPlayerConnection().sendPacket(
InitializeWorldBorderPacket.of(centerX, centerZ, oldDiameter, newDiameter, speed,
portalTeleportBoundary, warningTime, warningBlocks));
player.getPlayerConnection().sendPacket(new InitializeWorldBorderPacket(centerX, centerZ,
oldDiameter, newDiameter, speed, portalTeleportBoundary, warningTime, warningBlocks));
}
/**
@ -248,7 +247,7 @@ public class WorldBorder {
* Sends the new world border centers to all instance players.
*/
private void refreshCenter() {
sendPacket(WorldBorderCenterPacket.of(centerX, centerZ));
sendPacket(new WorldBorderCenterPacket(centerX, centerZ));
}
private void sendPacket(@NotNull ServerPacket packet) {

View File

@ -8,6 +8,8 @@ import net.minestom.server.network.packet.server.play.EntityEquipmentPacket;
import net.minestom.server.utils.validate.Check;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
/**
* Represents an {@link Entity} which can have {@link ItemStack} in hands and armor slots.
*/
@ -164,15 +166,8 @@ public interface EquipmentHandler {
Check.stateCondition(!(this instanceof Entity), "Only accessible for Entity");
Entity entity = (Entity) this;
final ItemStack itemStack = getEquipment(slot);
EntityEquipmentPacket entityEquipmentPacket = new EntityEquipmentPacket();
entityEquipmentPacket.entityId = entity.getEntityId();
entityEquipmentPacket.slots = new EquipmentSlot[]{slot};
entityEquipmentPacket.itemStacks = new ItemStack[]{itemStack};
entity.sendPacketToViewers(entityEquipmentPacket);
entity.sendPacketToViewers(new EntityEquipmentPacket(entity.getEntityId(), Map.of(slot, itemStack)));
}
/**
@ -183,18 +178,13 @@ public interface EquipmentHandler {
*/
default @NotNull EntityEquipmentPacket getEquipmentsPacket() {
Check.stateCondition(!(this instanceof Entity), "Only accessible for Entity");
final EquipmentSlot[] slots = EquipmentSlot.values();
ItemStack[] equipments = new ItemStack[slots.length];
for (int i = 0; i < equipments.length; i++) {
final EquipmentSlot slot = slots[i];
equipments[i] = getEquipment(slot);
}
// Create equipment packet
EntityEquipmentPacket equipmentPacket = new EntityEquipmentPacket();
equipmentPacket.entityId = ((Entity) this).getEntityId();
equipmentPacket.slots = slots;
equipmentPacket.itemStacks = equipments;
return equipmentPacket;
return new EntityEquipmentPacket(((Entity) this).getEntityId(), Map.of(
EquipmentSlot.MAIN_HAND, getItemInMainHand(),
EquipmentSlot.OFF_HAND, getItemInOffHand(),
EquipmentSlot.BOOTS, getBoots(),
EquipmentSlot.LEGGINGS, getLeggings(),
EquipmentSlot.CHESTPLATE, getChestplate(),
EquipmentSlot.HELMET, getHelmet()));
}
}

View File

@ -16,6 +16,7 @@ import net.minestom.server.utils.inventory.PlayerInventoryUtils;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
@ -93,14 +94,8 @@ public non-sealed class Inventory extends AbstractInventory implements Viewable
*/
public void setTitle(@NotNull Component title) {
this.title = title;
OpenWindowPacket packet = new OpenWindowPacket(title);
packet.windowId = getWindowId();
packet.windowType = getInventoryType().getWindowType();
// Re-open the inventory
sendPacketToViewers(packet);
sendPacketToViewers(new OpenWindowPacket(getWindowId(), getInventoryType().getWindowType(), title));
// Send inventory items
update();
}
@ -226,7 +221,7 @@ public non-sealed class Inventory extends AbstractInventory implements Viewable
* @return a new {@link WindowItemsPacket} packet
*/
private @NotNull WindowItemsPacket createNewWindowItemsPacket(Player player) {
return new WindowItemsPacket(getWindowId(), 0, getItemStacks(), cursorPlayersItem.getOrDefault(player, ItemStack.AIR));
return new WindowItemsPacket(getWindowId(), 0, List.of(getItemStacks()), cursorPlayersItem.getOrDefault(player, ItemStack.AIR));
}
/**

View File

@ -13,6 +13,8 @@ import net.minestom.server.network.packet.server.play.SetSlotPacket;
import net.minestom.server.network.packet.server.play.WindowItemsPacket;
import org.jetbrains.annotations.NotNull;
import java.util.List;
import static net.minestom.server.utils.inventory.PlayerInventoryUtils.*;
/**
@ -194,7 +196,7 @@ public non-sealed class PlayerInventory extends AbstractInventory implements Equ
final int slot = convertToPacketSlot(i);
convertedSlots[slot] = itemStacks[i];
}
return new WindowItemsPacket((byte) 0, 0, convertedSlots, cursorItem);
return new WindowItemsPacket((byte) 0, 0, List.of(convertedSlots), cursorItem);
}
@Override

View File

@ -4,105 +4,95 @@ import net.kyori.adventure.text.Component;
import net.minestom.server.entity.Player;
import net.minestom.server.inventory.Inventory;
import net.minestom.server.inventory.InventoryType;
import net.minestom.server.network.packet.server.CachedPacket;
import net.minestom.server.network.packet.server.play.TradeListPacket;
import net.minestom.server.utils.ArrayUtils;
import org.jetbrains.annotations.NotNull;
public class VillagerInventory extends Inventory {
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
protected TradeListPacket tradeListPacket;
public class VillagerInventory extends Inventory {
private final CachedPacket tradeCache = new CachedPacket(this::createTradePacket);
private final List<TradeListPacket.Trade> trades = new ArrayList<>();
private int villagerLevel;
private int experience;
private boolean regularVillager;
private boolean canRestock;
public VillagerInventory(@NotNull Component title) {
super(InventoryType.MERCHANT, title);
setupPacket();
}
public VillagerInventory(@NotNull String title) {
super(InventoryType.MERCHANT, title);
setupPacket();
}
public TradeListPacket.Trade[] getTrades() {
return tradeListPacket.trades;
public List<TradeListPacket.Trade> getTrades() {
return Collections.unmodifiableList(trades);
}
public void addTrade(TradeListPacket.Trade trade) {
TradeListPacket.Trade[] oldTrades = getTrades();
final int length = oldTrades.length + 1;
TradeListPacket.Trade[] trades = new TradeListPacket.Trade[length];
System.arraycopy(oldTrades, 0, trades, 0, oldTrades.length);
trades[length - 1] = trade;
this.tradeListPacket.trades = trades;
this.trades.add(trade);
update();
}
public void removeTrade(int index) {
TradeListPacket.Trade[] oldTrades = getTrades();
final int length = oldTrades.length - 1;
TradeListPacket.Trade[] trades = new TradeListPacket.Trade[length];
ArrayUtils.removeElement(trades, index);
this.tradeListPacket.trades = trades;
this.trades.remove(index);
update();
}
public int getVillagerLevel() {
return tradeListPacket.villagerLevel;
return villagerLevel;
}
public void setVillagerLevel(int level) {
this.tradeListPacket.villagerLevel = level;
this.villagerLevel = level;
update();
}
public int getExperience() {
return tradeListPacket.experience;
return experience;
}
public void setExperience(int experience) {
this.tradeListPacket.experience = experience;
this.experience = experience;
update();
}
public boolean isRegularVillager() {
return tradeListPacket.regularVillager;
return regularVillager;
}
public void setRegularVillager(boolean regularVillager) {
this.tradeListPacket.regularVillager = regularVillager;
this.regularVillager = regularVillager;
update();
}
public boolean canRestock() {
return tradeListPacket.canRestock;
return canRestock;
}
public void setCanRestock(boolean canRestock) {
this.tradeListPacket.canRestock = canRestock;
this.canRestock = canRestock;
update();
}
@Override
public void update() {
super.update();
sendPacketToViewers(tradeListPacket); // Refresh window
this.tradeCache.invalidate();
sendPacketToViewers(tradeCache.retrieve());
}
@Override
public boolean addViewer(@NotNull Player player) {
final boolean result = super.addViewer(player);
if (result) {
player.getPlayerConnection().sendPacket(tradeListPacket);
}
if (result) player.sendPacket(tradeCache.retrieve());
return result;
}
private void setupPacket() {
this.tradeListPacket = new TradeListPacket();
this.tradeListPacket.windowId = getWindowId();
this.tradeListPacket.trades = new TradeListPacket.Trade[0];
this.tradeListPacket.villagerLevel = 0;
this.tradeListPacket.experience = 0;
this.tradeListPacket.regularVillager = false;
this.tradeListPacket.canRestock = false;
private TradeListPacket createTradePacket() {
return new TradeListPacket(getWindowId(), trades, villagerLevel, experience, regularVillager, canRestock);
}
}

View File

@ -12,7 +12,7 @@ public class AbilitiesListener {
final boolean canFly = player.isAllowFlying() || player.isCreative();
if (canFly) {
final boolean isFlying = (packet.flags & 0x2) > 0;
final boolean isFlying = (packet.flags() & 0x2) > 0;
player.refreshFlying(isFlying);

View File

@ -1,6 +1,5 @@
package net.minestom.server.listener;
import net.minestom.server.advancements.AdvancementAction;
import net.minestom.server.entity.Player;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.player.AdvancementTabEvent;
@ -9,10 +8,9 @@ import net.minestom.server.network.packet.client.play.ClientAdvancementTabPacket
public class AdvancementTabListener {
public static void listener(ClientAdvancementTabPacket packet, Player player) {
final AdvancementAction action = packet.action;
final String tabId = packet.tabIdentifier;
AdvancementTabEvent advancementTabEvent = new AdvancementTabEvent(player, action, tabId);
EventDispatcher.call(advancementTabEvent);
final String tabIdentifier = packet.tabIdentifier();
if (tabIdentifier != null) {
EventDispatcher.call(new AdvancementTabEvent(player, packet.action(), tabIdentifier));
}
}
}

View File

@ -9,7 +9,7 @@ import net.minestom.server.network.packet.client.play.ClientAnimationPacket;
public class AnimationListener {
public static void animationListener(ClientAnimationPacket packet, Player player) {
final Player.Hand hand = packet.hand;
final Player.Hand hand = packet.hand();
final ItemStack itemStack = player.getItemInHand(hand);
//itemStack.onLeftClick(player, hand);
PlayerHandAnimationEvent handAnimationEvent = new PlayerHandAnimationEvent(player, hand);

View File

@ -34,9 +34,9 @@ public class BlockPlacementListener {
public static void listener(ClientPlayerBlockPlacementPacket packet, Player player) {
final PlayerInventory playerInventory = player.getInventory();
final Player.Hand hand = packet.hand;
final BlockFace blockFace = packet.blockFace;
final Point blockPosition = packet.blockPosition;
final Player.Hand hand = packet.hand();
final BlockFace blockFace = packet.blockFace();
final Point blockPosition = packet.blockPosition();
final Direction direction = blockFace.toDirection();
final Instance instance = player.getInstance();
@ -134,7 +134,7 @@ public class BlockPlacementListener {
return;
}
// BlockPlaceEvent check
PlayerBlockPlaceEvent playerBlockPlaceEvent = new PlayerBlockPlaceEvent(player, placedBlock, blockFace, placementPosition, packet.hand);
PlayerBlockPlaceEvent playerBlockPlaceEvent = new PlayerBlockPlaceEvent(player, placedBlock, blockFace, placementPosition, packet.hand());
playerBlockPlaceEvent.consumeBlock(player.getGameMode() != GameMode.CREATIVE);
EventDispatcher.call(playerBlockPlaceEvent);
if (playerBlockPlaceEvent.isCancelled()) {
@ -155,7 +155,7 @@ public class BlockPlacementListener {
}
// Place the block
instance.placeBlock(new BlockHandler.PlayerPlacement(resultBlock, instance, placementPosition, player, hand, blockFace,
packet.cursorPositionX, packet.cursorPositionY, packet.cursorPositionZ));
packet.cursorPositionX(), packet.cursorPositionY(), packet.cursorPositionZ()));
// Block consuming
if (playerBlockPlaceEvent.doesConsumeBlock()) {
// Consume the block in the player's hand

View File

@ -22,7 +22,7 @@ public class ChatMessageListener {
private static final ConnectionManager CONNECTION_MANAGER = MinecraftServer.getConnectionManager();
public static void listener(ClientChatMessagePacket packet, Player player) {
String message = packet.message;
String message = packet.message();
final String cmdPrefix = CommandManager.COMMAND_PREFIX;
if (message.startsWith(cmdPrefix)) {

View File

@ -11,8 +11,8 @@ import java.util.Objects;
public final class CreativeInventoryActionListener {
public static void listener(ClientCreativeInventoryActionPacket packet, Player player) {
if (!player.isCreative()) return;
short slot = packet.slot;
final ItemStack item = packet.item;
short slot = packet.slot();
final ItemStack item = packet.item();
if (slot == -1) {
// Drop item
player.dropItem(item);

View File

@ -8,8 +8,7 @@ import net.minestom.server.network.packet.client.play.ClientEntityActionPacket;
public class EntityActionListener {
public static void listener(ClientEntityActionPacket packet, Player player) {
ClientEntityActionPacket.Action action = packet.action;
switch (action) {
switch (packet.action()) {
case START_SNEAKING -> EntityActionListener.setSneaking(player, true);
case STOP_SNEAKING -> EntityActionListener.setSneaking(player, false);
case START_SPRINTING -> EntityActionListener.setSprinting(player, true);

View File

@ -9,7 +9,7 @@ public final class KeepAliveListener {
private static final Component KICK_MESSAGE = Component.text("Bad Keep Alive packet", NamedTextColor.RED);
public static void listener(ClientKeepAlivePacket packet, Player player) {
final long packetId = packet.id;
final long packetId = packet.id();
if (packetId != player.getLastKeepAlive()) {
player.kick(KICK_MESSAGE);
return;

View File

@ -21,8 +21,8 @@ import org.jetbrains.annotations.NotNull;
public final class PlayerDiggingListener {
public static void playerDiggingListener(ClientPlayerDiggingPacket packet, Player player) {
final ClientPlayerDiggingPacket.Status status = packet.status;
final Point blockPosition = packet.blockPosition;
final ClientPlayerDiggingPacket.Status status = packet.status();
final Point blockPosition = packet.blockPosition();
final Instance instance = player.getInstance();
if (instance == null) return;

View File

@ -9,12 +9,12 @@ import net.minestom.server.utils.MathUtils;
public class PlayerHeldListener {
public static void heldListener(ClientHeldItemChangePacket packet, Player player) {
if (!MathUtils.isBetween(packet.slot, 0, 8)) {
if (!MathUtils.isBetween(packet.slot(), 0, 8)) {
// Incorrect packet, ignore
return;
}
final byte slot = (byte) packet.slot;
final byte slot = (byte) packet.slot();
PlayerChangeHeldSlotEvent changeHeldSlotEvent = new PlayerChangeHeldSlotEvent(player, slot);
EventDispatcher.call(changeHeldSlotEvent);

View File

@ -14,23 +14,23 @@ import org.jetbrains.annotations.NotNull;
public class PlayerPositionListener {
public static void playerPacketListener(ClientPlayerPacket packet, Player player) {
player.refreshOnGround(packet.onGround);
player.refreshOnGround(packet.onGround());
}
public static void playerLookListener(ClientPlayerRotationPacket packet, Player player) {
processMovement(player, player.getPosition().withView(packet.yaw, packet.pitch), packet.onGround);
processMovement(player, player.getPosition().withView(packet.yaw(), packet.pitch()), packet.onGround());
}
public static void playerPositionListener(ClientPlayerPositionPacket packet, Player player) {
processMovement(player, player.getPosition().withCoord(packet.x, packet.y, packet.z), packet.onGround);
processMovement(player, player.getPosition().withCoord(packet.position()), packet.onGround());
}
public static void playerPositionAndLookListener(ClientPlayerPositionAndRotationPacket packet, Player player) {
processMovement(player, new Pos(packet.x, packet.y, packet.z, packet.yaw, packet.pitch), packet.onGround);
processMovement(player, packet.position(), packet.onGround());
}
public static void teleportConfirmListener(ClientTeleportConfirmPacket packet, Player player) {
player.refreshReceivedTeleportId(packet.teleportId);
player.refreshReceivedTeleportId(packet.teleportId());
}
private static void processMovement(@NotNull Player player, @NotNull Pos packetPosition, boolean onGround) {

View File

@ -1,6 +1,5 @@
package net.minestom.server.listener;
import net.minestom.server.coordinate.Pos;
import net.minestom.server.entity.Entity;
import net.minestom.server.entity.Player;
import net.minestom.server.entity.metadata.other.BoatMeta;
@ -11,10 +10,10 @@ import net.minestom.server.network.packet.client.play.ClientVehicleMovePacket;
public class PlayerVehicleListener {
public static void steerVehicleListener(ClientSteerVehiclePacket packet, Player player) {
final byte flags = packet.flags;
final byte flags = packet.flags();
final boolean jump = (flags & 0x1) != 0;
final boolean unmount = (flags & 0x2) != 0;
player.refreshVehicleSteer(packet.sideways, packet.forward, jump, unmount);
player.refreshVehicleSteer(packet.sideways(), packet.forward(), jump, unmount);
}
public static void vehicleMoveListener(ClientVehicleMovePacket packet, Player player) {
@ -22,8 +21,7 @@ public class PlayerVehicleListener {
if (vehicle == null)
return;
final var newPosition = new Pos(packet.x, packet.y, packet.z, packet.yaw, packet.pitch);
vehicle.refreshPosition(newPosition);
vehicle.refreshPosition(packet.position());
// This packet causes weird screen distortion
/*VehicleMovePacket vehicleMovePacket = new VehicleMovePacket();
@ -39,7 +37,7 @@ public class PlayerVehicleListener {
public static void boatSteerListener(ClientSteerBoatPacket packet, Player player) {
final Entity vehicle = player.getVehicle();
if (!(vehicle.getEntityMeta() instanceof BoatMeta boat)) return;
boat.setLeftPaddleTurning(packet.leftPaddleTurning);
boat.setRightPaddleTurning(packet.rightPaddleTurning);
boat.setLeftPaddleTurning(packet.leftPaddleTurning());
boat.setRightPaddleTurning(packet.rightPaddleTurning());
}
}

View File

@ -8,7 +8,7 @@ import net.minestom.server.network.packet.client.play.ClientPluginMessagePacket;
public class PluginMessageListener {
public static void listener(ClientPluginMessagePacket packet, Player player) {
PlayerPluginMessageEvent pluginMessageEvent = new PlayerPluginMessageEvent(player, packet.channel, packet.data);
PlayerPluginMessageEvent pluginMessageEvent = new PlayerPluginMessageEvent(player, packet.channel(), packet.data());
EventDispatcher.call(pluginMessageEvent);
}

View File

@ -7,9 +7,6 @@ import net.minestom.server.network.packet.server.play.CraftRecipeResponse;
public class RecipeListener {
public static void listener(ClientCraftRecipeRequest packet, Player player) {
CraftRecipeResponse recipeResponse = new CraftRecipeResponse();
recipeResponse.windowId = packet.windowId;
recipeResponse.recipe = packet.recipe;
player.getPlayerConnection().sendPacket(recipeResponse);
player.getPlayerConnection().sendPacket(new CraftRecipeResponse(packet.windowId(), packet.recipe()));
}
}

View File

@ -4,13 +4,10 @@ import net.minestom.server.entity.Player;
import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.player.PlayerResourcePackStatusEvent;
import net.minestom.server.network.packet.client.play.ClientResourcePackStatusPacket;
import net.minestom.server.resourcepack.ResourcePackStatus;
public class ResourcePackListener {
public static void listener(ClientResourcePackStatusPacket packet, Player player) {
final ResourcePackStatus result = packet.result;
PlayerResourcePackStatusEvent resourcePackStatusEvent = new PlayerResourcePackStatusEvent(player, result);
EventDispatcher.call(resourcePackStatusEvent);
EventDispatcher.call(new PlayerResourcePackStatusEvent(player, packet.status()));
}
}

View File

@ -8,8 +8,8 @@ import net.minestom.server.network.packet.client.play.ClientSettingsPacket;
public final class SettingsListener {
public static void listener(ClientSettingsPacket packet, Player player) {
Player.PlayerSettings settings = player.getSettings();
final byte viewDistance = (byte) Math.abs(packet.viewDistance);
settings.refresh(packet.locale, viewDistance, packet.chatMessageType, packet.chatColors, packet.displayedSkinParts, packet.mainHand);
final byte viewDistance = (byte) Math.abs(packet.viewDistance());
settings.refresh(packet.locale(), viewDistance, packet.chatMessageType(), packet.chatColors(), packet.displayedSkinParts(), packet.mainHand());
EventDispatcher.call(new PlayerSettingsChangeEvent(player));
}
}

View File

@ -9,7 +9,7 @@ import java.util.UUID;
public class SpectateListener {
public static void listener(ClientSpectatePacket packet, Player player) {
final UUID targetUuid = packet.targetUuid;
final UUID targetUuid = packet.target();
final Entity target = Entity.getEntity(targetUuid);
// Check if the target is valid

View File

@ -12,24 +12,18 @@ import java.util.Map;
public class StatusListener {
public static void listener(ClientStatusPacket packet, Player player) {
switch (packet.action) {
switch (packet.action()) {
case PERFORM_RESPAWN -> player.respawn();
case REQUEST_STATS -> {
List<StatisticsPacket.Statistic> statisticList = new ArrayList<>();
StatisticsPacket statisticsPacket = new StatisticsPacket();
final Map<PlayerStatistic, Integer> playerStatisticValueMap = player.getStatisticValueMap();
for (var entry : playerStatisticValueMap.entrySet()) {
final PlayerStatistic playerStatistic = entry.getKey();
final int value = entry.getValue();
StatisticsPacket.Statistic statistic = new StatisticsPacket.Statistic();
statistic.category = playerStatistic.getCategory();
statistic.statisticId = playerStatistic.getStatisticId();
statistic.value = value;
statisticList.add(statistic);
statisticList.add(new StatisticsPacket.Statistic(playerStatistic.getCategory(),
playerStatistic.getStatisticId(), value));
}
statisticsPacket.statistics = statisticList.toArray(new StatisticsPacket.Statistic[0]);
StatisticsPacket statisticsPacket = new StatisticsPacket(statisticList);
player.getPlayerConnection().sendPacket(statisticsPacket);
}
}

View File

@ -19,9 +19,9 @@ import java.util.regex.Pattern;
public class TabCompleteListener {
public static void listener(ClientTabCompletePacket packet, Player player) {
final String text = packet.text;
final String text = packet.text();
String commandString = packet.text.replaceFirst(CommandManager.COMMAND_PREFIX, "");
String commandString = text.replaceFirst(CommandManager.COMMAND_PREFIX, "");
String[] split = commandString.split(StringUtils.SPACE);
String commandName = split[0];
String args = commandString.replaceFirst(Pattern.quote(commandName), "");
@ -56,24 +56,10 @@ public class TabCompleteListener {
Suggestion suggestion = new Suggestion(input, start, inputLength);
suggestionCallback.apply(player, queryResult.context, suggestion);
TabCompletePacket tabCompletePacket = new TabCompletePacket();
tabCompletePacket.transactionId = packet.transactionId;
tabCompletePacket.start = suggestion.getStart();
tabCompletePacket.length = suggestion.getLength();
tabCompletePacket.matches = suggestion.getEntries()
.stream()
.map(suggestionEntry -> {
TabCompletePacket.Match match = new TabCompletePacket.Match();
match.match = suggestionEntry.getEntry();
match.hasTooltip = suggestionEntry.getTooltip() != null;
match.tooltip = suggestionEntry.getTooltip();
return match;
}).toArray(TabCompletePacket.Match[]::new);
player.getPlayerConnection().sendPacket(tabCompletePacket);
player.getPlayerConnection().sendPacket(new TabCompletePacket(packet.transactionId(), suggestion.getStart(), suggestion.getLength(),
suggestion.getEntries().stream()
.map(suggestionEntry -> new TabCompletePacket.Match(suggestionEntry.getEntry(), suggestionEntry.getTooltip())).toList()));
}
}
}

View File

@ -11,23 +11,22 @@ import net.minestom.server.network.packet.client.play.ClientInteractEntityPacket
public class UseEntityListener {
public static void useEntityListener(ClientInteractEntityPacket packet, Player player) {
final Entity entity = Entity.getEntity(packet.targetId);
final Entity entity = Entity.getEntity(packet.targetId());
if (entity == null)
return;
ClientInteractEntityPacket.Type type = packet.type;
ClientInteractEntityPacket.Type type = packet.type();
// Player cannot interact with entities he cannot see
if (!entity.isViewer(player))
return;
if (type == ClientInteractEntityPacket.Type.ATTACK) {
if (type instanceof ClientInteractEntityPacket.Attack) {
if (entity instanceof LivingEntity && ((LivingEntity) entity).isDead()) // Can't attack dead entities
return;
EntityAttackEvent entityAttackEvent = new EntityAttackEvent(player, entity);
EventDispatcher.call(entityAttackEvent);
} else if (type == ClientInteractEntityPacket.Type.INTERACT) {
PlayerEntityInteractEvent playerEntityInteractEvent = new PlayerEntityInteractEvent(player, entity, packet.hand);
} else if (type instanceof ClientInteractEntityPacket.Interact interact) {
PlayerEntityInteractEvent playerEntityInteractEvent = new PlayerEntityInteractEvent(player, entity, interact.hand());
EventDispatcher.call(playerEntityInteractEvent);
} else {
// TODO find difference with INTERACT

View File

@ -15,7 +15,7 @@ public class UseItemListener {
public static void useItemListener(ClientUseItemPacket packet, Player player) {
final PlayerInventory inventory = player.getInventory();
final Player.Hand hand = packet.hand;
final Player.Hand hand = packet.hand();
ItemStack itemStack = hand == Player.Hand.MAIN ? inventory.getItemInMainHand() : inventory.getItemInOffHand();
//itemStack.onRightClick(player, hand);
PlayerUseItemEvent useItemEvent = new PlayerUseItemEvent(player, hand, itemStack);

View File

@ -16,16 +16,16 @@ import net.minestom.server.network.packet.server.play.SetSlotPacket;
public class WindowListener {
public static void clickWindowListener(ClientClickWindowPacket packet, Player player) {
final int windowId = packet.windowId;
final int windowId = packet.windowId();
final AbstractInventory inventory = windowId == 0 ? player.getInventory() : player.getOpenInventory();
if (inventory == null) {
// Invalid packet
return;
}
final short slot = packet.slot;
final byte button = packet.button;
final ClientClickWindowPacket.ClickType clickType = packet.clickType;
final short slot = packet.slot();
final byte button = packet.button();
final ClientClickWindowPacket.ClickType clickType = packet.clickType();
//System.out.println("Window id: " + windowId + " | slot: " + slot + " | button: " + button + " | clickType: " + clickType);
@ -56,7 +56,7 @@ public class WindowListener {
} else if (clickType == ClientClickWindowPacket.ClickType.CLONE) {
successful = player.isCreative();
if (successful) {
setCursor(player, inventory, packet.item);
setCursor(player, inventory, packet.clickedItem());
}
} else if (clickType == ClientClickWindowPacket.ClickType.THROW) {
successful = inventory.drop(player, false, slot, button);
@ -78,9 +78,7 @@ public class WindowListener {
refreshCursorItem(player, inventory);
// (Why is the ping packet necessary?)
PingPacket pingPacket = new PingPacket();
pingPacket.id = (1 << 30) | (windowId << 16);
player.getPlayerConnection().sendPacket(pingPacket);
player.getPlayerConnection().sendPacket(new PingPacket((1 << 30) | (windowId << 16)));
}
public static void pong(ClientPongPacket packet, Player player) {

View File

@ -2,7 +2,7 @@ package net.minestom.server.listener.manager;
import net.minestom.server.entity.Player;
import net.minestom.server.network.ConnectionManager;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import org.jetbrains.annotations.NotNull;
/**
@ -18,5 +18,5 @@ public interface ClientPacketConsumer {
* @param packetController the packet controller, can be used to cancel the packet
* @param packet the packet
*/
void accept(@NotNull Player player, @NotNull PacketController packetController, @NotNull ClientPlayPacket packet);
void accept(@NotNull Player player, @NotNull PacketController packetController, @NotNull ClientPacket packet);
}

View File

@ -1,13 +1,13 @@
package net.minestom.server.listener.manager;
import net.minestom.server.entity.Player;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.network.packet.server.ServerPacket;
import java.util.Collection;
/**
* Used to control the output of a packet in {@link ClientPacketConsumer#accept(Player, PacketController, ClientPlayPacket)}
* Used to control the output of a packet in {@link ClientPacketConsumer#accept(Player, PacketController, ClientPacket)}
* and {@link ServerPacketConsumer#accept(Collection, PacketController, ServerPacket)}.
*/
public class PacketController {

View File

@ -1,7 +1,7 @@
package net.minestom.server.listener.manager;
import net.minestom.server.entity.Player;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
/**
* Small convenient interface to use method references with {@link PacketListenerManager#setListener(Class, PacketListenerConsumer)}.
@ -9,6 +9,6 @@ import net.minestom.server.network.packet.client.ClientPlayPacket;
* @param <T> the packet type
*/
@FunctionalInterface
public interface PacketListenerConsumer<T extends ClientPlayPacket> {
public interface PacketListenerConsumer<T extends ClientPacket> {
void accept(T packet, Player player);
}

View File

@ -6,7 +6,7 @@ import net.minestom.server.event.GlobalHandles;
import net.minestom.server.event.player.PlayerPacketEvent;
import net.minestom.server.listener.*;
import net.minestom.server.network.ConnectionManager;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.network.packet.client.play.*;
import net.minestom.server.network.packet.server.ServerPacket;
import org.jetbrains.annotations.NotNull;
@ -23,7 +23,7 @@ public final class PacketListenerManager {
public final static Logger LOGGER = LoggerFactory.getLogger(PacketListenerManager.class);
private static final ConnectionManager CONNECTION_MANAGER = MinecraftServer.getConnectionManager();
private final Map<Class<? extends ClientPlayPacket>, PacketListenerConsumer> listeners = new ConcurrentHashMap<>();
private final Map<Class<? extends ClientPacket>, PacketListenerConsumer> listeners = new ConcurrentHashMap<>();
public PacketListenerManager() {
setListener(ClientKeepAlivePacket.class, KeepAliveListener::listener);
@ -65,7 +65,7 @@ public final class PacketListenerManager {
* @param player the player who sent the packet
* @param <T> the packet type
*/
public <T extends ClientPlayPacket> void processClientPacket(@NotNull T packet, @NotNull Player player) {
public <T extends ClientPacket> void processClientPacket(@NotNull T packet, @NotNull Player player) {
final Class clazz = packet.getClass();
@ -135,7 +135,7 @@ public final class PacketListenerManager {
* @param consumer the new packet's listener
* @param <T> the type of the packet
*/
public <T extends ClientPlayPacket> void setListener(@NotNull Class<T> packetClass, @NotNull PacketListenerConsumer<T> consumer) {
public <T extends ClientPacket> void setListener(@NotNull Class<T> packetClass, @NotNull PacketListenerConsumer<T> consumer) {
this.listeners.put(packetClass, consumer);
}

View File

@ -2,6 +2,8 @@ package net.minestom.server.map;
import net.minestom.server.network.packet.server.play.MapDataPacket;
import java.util.List;
/**
* Framebuffer to render to a map
*/
@ -12,11 +14,11 @@ public interface Framebuffer {
byte[] toMapColors();
default void preparePacket(MapDataPacket packet) {
preparePacket(packet, 0, 0, WIDTH, HEIGHT);
default MapDataPacket preparePacket(int mapId) {
return preparePacket(mapId, 0, 0, WIDTH, HEIGHT);
}
default void preparePacket(MapDataPacket packet, int minX, int minY, int width, int height) {
default MapDataPacket preparePacket(int mapId, int minX, int minY, int width, int height) {
byte[] colors;
if (minX == 0 && minY == 0 && width == WIDTH && height == HEIGHT) {
colors = toMapColors();
@ -30,13 +32,11 @@ public interface Framebuffer {
}
}
}
packet.columns = (short) width;
packet.rows = (short) height;
packet.icons = new MapDataPacket.Icon[0];
packet.x = (byte) minX;
packet.z = (byte) minY;
packet.data = colors;
return new MapDataPacket(mapId, (byte) 0, false,
false, List.of(),
(byte) width, (byte) height,
(byte) minX, (byte) minY,
colors);
}
static int index(int x, int z) {

View File

@ -2,6 +2,8 @@ package net.minestom.server.map;
import net.minestom.server.network.packet.server.play.MapDataPacket;
import java.util.List;
/**
* Framebuffer that is meant to be split in sub-framebuffers.
* Contrary to {@link Framebuffer}, LargeFramebuffer supports sizes over 128x128 pixels.
@ -26,12 +28,8 @@ public interface LargeFramebuffer {
/**
* Prepares the packet to render a 128x128 sub view of this framebuffer
*
* @param packet the {@link MapDataPacket} to prepare
* @param left
* @param top
*/
default void preparePacket(MapDataPacket packet, int left, int top) {
default MapDataPacket preparePacket(int mapId, int left, int top) {
byte[] colors = new byte[Framebuffer.WIDTH * Framebuffer.WIDTH];
final int width = Math.min(width(), left + Framebuffer.WIDTH) - left;
final int height = Math.min(height(), top + Framebuffer.HEIGHT) - top;
@ -41,12 +39,10 @@ public interface LargeFramebuffer {
colors[Framebuffer.index(x - left, y - top)] = color;
}
}
packet.columns = (short) width;
packet.rows = (short) height;
packet.icons = new MapDataPacket.Icon[0];
packet.x = 0;
packet.z = 0;
packet.data = colors;
return new MapDataPacket(mapId, (byte) 0, false,
false, List.of(),
(byte) width, (byte) height,
(byte) 0, (byte) 0,
colors);
}
}

View File

@ -2,19 +2,13 @@ package net.minestom.server.network;
import net.minestom.server.MinecraftServer;
import net.minestom.server.entity.Player;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.network.packet.client.ClientPacketsHandler;
import net.minestom.server.network.packet.client.ClientPreplayPacket;
import net.minestom.server.network.packet.client.handler.ClientLoginPacketsHandler;
import net.minestom.server.network.packet.client.handler.ClientPlayPacketsHandler;
import net.minestom.server.network.packet.client.handler.ClientStatusPacketsHandler;
import net.minestom.server.network.packet.client.handshake.HandshakePacket;
import net.minestom.server.network.player.PlayerConnection;
import net.minestom.server.network.player.PlayerSocketConnection;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.Readable;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.nio.ByteBuffer;
@ -22,113 +16,47 @@ import java.nio.ByteBuffer;
* Responsible for processing client packets.
* <p>
* You can retrieve the different packet handlers per state (status/login/play)
* from the {@link net.minestom.server.network.packet.client.handler.ClientPacketsHandler} class.
* <p>
* Packet handlers are cached here and can be retrieved with {@link #getStatusPacketsHandler()}, {@link #getLoginPacketsHandler()}
* and {@link #getPlayPacketsHandler()}. The one to use depend on the type of packet you need to retrieve (the packet id 0 does not have
* the same meaning as it is a login or play packet).
* from the {@link ClientPacketsHandler} classes.
*/
public final class PacketProcessor {
private final static Logger LOGGER = LoggerFactory.getLogger(PacketProcessor.class);
// Protocols state
private final ClientStatusPacketsHandler statusPacketsHandler;
private final ClientLoginPacketsHandler loginPacketsHandler;
private final ClientPlayPacketsHandler playPacketsHandler;
public record PacketProcessor(@NotNull ClientPacketsHandler statusHandler,
@NotNull ClientPacketsHandler loginHandler,
@NotNull ClientPacketsHandler playHandler) {
public PacketProcessor() {
this.statusPacketsHandler = new ClientStatusPacketsHandler();
this.loginPacketsHandler = new ClientLoginPacketsHandler();
this.playPacketsHandler = new ClientPlayPacketsHandler();
this(new ClientPacketsHandler.Status(),
new ClientPacketsHandler.Login(),
new ClientPacketsHandler.Play());
}
public void process(@NotNull PlayerSocketConnection playerConnection, int packetId, ByteBuffer body) {
public void process(@NotNull PlayerSocketConnection connection, int packetId, ByteBuffer body) {
if (MinecraftServer.getRateLimit() > 0) {
// Increment packet count (checked in PlayerConnection#update)
playerConnection.getPacketCounter().incrementAndGet();
connection.getPacketCounter().incrementAndGet();
}
BinaryReader binaryReader = new BinaryReader(body);
final ConnectionState connectionState = playerConnection.getConnectionState();
final ConnectionState connectionState = connection.getConnectionState();
if (connectionState == ConnectionState.UNKNOWN) {
// Should be handshake packet
if (packetId == 0) {
HandshakePacket handshakePacket = new HandshakePacket();
safeRead(playerConnection, handshakePacket, binaryReader);
handshakePacket.process(playerConnection);
final HandshakePacket handshakePacket = new HandshakePacket(binaryReader);
handshakePacket.process(connection);
}
return;
}
switch (connectionState) {
case PLAY -> {
final Player player = playerConnection.getPlayer();
ClientPlayPacket playPacket = (ClientPlayPacket) playPacketsHandler.getPacketInstance(packetId);
safeRead(playerConnection, playPacket, binaryReader);
final Player player = connection.getPlayer();
ClientPacket playPacket = playHandler.create(packetId, binaryReader);
assert player != null;
player.addPacketToQueue(playPacket);
}
case LOGIN -> {
final ClientPreplayPacket loginPacket = (ClientPreplayPacket) loginPacketsHandler.getPacketInstance(packetId);
safeRead(playerConnection, loginPacket, binaryReader);
loginPacket.process(playerConnection);
final ClientPreplayPacket loginPacket = (ClientPreplayPacket) loginHandler.create(packetId, binaryReader);
loginPacket.process(connection);
}
case STATUS -> {
final ClientPreplayPacket statusPacket = (ClientPreplayPacket) statusPacketsHandler.getPacketInstance(packetId);
safeRead(playerConnection, statusPacket, binaryReader);
statusPacket.process(playerConnection);
final ClientPreplayPacket statusPacket = (ClientPreplayPacket) statusHandler.create(packetId, binaryReader);
statusPacket.process(connection);
}
}
}
/**
* Gets the handler for client status packets.
*
* @return the status packets handler
* @see <a href="https://wiki.vg/Protocol#Status">Status packets</a>
*/
public @NotNull ClientStatusPacketsHandler getStatusPacketsHandler() {
return statusPacketsHandler;
}
/**
* Gets the handler for client login packets.
*
* @return the status login handler
* @see <a href="https://wiki.vg/Protocol#Login">Login packets</a>
*/
public @NotNull ClientLoginPacketsHandler getLoginPacketsHandler() {
return loginPacketsHandler;
}
/**
* Gets the handler for client play packets.
*
* @return the play packets handler
* @see <a href="https://wiki.vg/Protocol#Play">Play packets</a>
*/
public @NotNull ClientPlayPacketsHandler getPlayPacketsHandler() {
return playPacketsHandler;
}
/**
* Calls {@link Readable#read(BinaryReader)} and catch all the exceptions to be printed using the packet processor logger.
*
* @param connection the connection who sent the packet
* @param readable the readable interface
* @param reader the buffer containing the packet
*/
private void safeRead(@NotNull PlayerConnection connection, @NotNull Readable readable, @NotNull BinaryReader reader) {
final int readableBytes = reader.available();
// Check if there is anything to read
if (readableBytes == 0) {
return;
}
try {
readable.read(reader);
} catch (Exception e) {
final Player player = connection.getPlayer();
final String username = player != null ? player.getUsername() : "null";
LOGGER.warn("Connection {} ({}) sent an unexpected packet.", connection.getRemoteAddress(), username);
MinecraftServer.getExceptionManager().handleException(e);
}
}
}

View File

@ -1,18 +1,9 @@
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, 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.");
}
public interface ClientPacket extends Writeable {
}

View File

@ -0,0 +1,106 @@
package net.minestom.server.network.packet.client;
import net.minestom.server.network.packet.client.login.EncryptionResponsePacket;
import net.minestom.server.network.packet.client.login.LoginPluginResponsePacket;
import net.minestom.server.network.packet.client.login.LoginStartPacket;
import net.minestom.server.network.packet.client.play.*;
import net.minestom.server.network.packet.client.status.PingPacket;
import net.minestom.server.network.packet.client.status.StatusRequestPacket;
import net.minestom.server.utils.ObjectArray;
import net.minestom.server.utils.binary.BinaryReader;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.UnknownNullability;
import java.util.function.Function;
/**
* Contains registered packets and a way to instantiate them.
* <p>
* Packets are registered using {@link #register(int, Function)} and created using {@link #create(int, BinaryReader)}.
*/
public sealed class ClientPacketsHandler permits ClientPacketsHandler.Status, ClientPacketsHandler.Login, ClientPacketsHandler.Play {
private final ObjectArray<Function<BinaryReader, ClientPacket>> suppliers = new ObjectArray<>(0x10);
private ClientPacketsHandler() {
}
public void register(int id, @NotNull Function<@NotNull BinaryReader, @NotNull ClientPacket> packetSupplier) {
this.suppliers.set(id, packetSupplier);
}
public @UnknownNullability ClientPacket create(int packetId, @NotNull BinaryReader reader) {
final Function<BinaryReader, ClientPacket> supplier = suppliers.get(packetId);
if (supplier == null)
throw new IllegalStateException("Packet id 0x" + Integer.toHexString(packetId) + " isn't registered!");
return supplier.apply(reader);
}
public static final class Status extends ClientPacketsHandler {
public Status() {
register(0x00, StatusRequestPacket::new);
register(0x01, PingPacket::new);
}
}
public static final class Login extends ClientPacketsHandler {
public Login() {
register(0x00, LoginStartPacket::new);
register(0x01, EncryptionResponsePacket::new);
register(0x02, LoginPluginResponsePacket::new);
}
}
public static final class Play extends ClientPacketsHandler {
public Play() {
register(0x00, ClientTeleportConfirmPacket::new);
register(0x01, ClientQueryBlockNbtPacket::new);
register(0x03, ClientChatMessagePacket::new);
register(0x04, ClientStatusPacket::new);
register(0x05, ClientSettingsPacket::new);
register(0x06, ClientTabCompletePacket::new);
register(0x07, ClientClickWindowButtonPacket::new);
register(0x08, ClientClickWindowPacket::new);
register(0x09, ClientCloseWindowPacket::new);
register(0x0A, ClientPluginMessagePacket::new);
register(0x0B, ClientEditBookPacket::new);
register(0x0C, ClientQueryEntityNbtPacket::new);
register(0x0D, ClientInteractEntityPacket::new);
register(0x0E, ClientGenerateStructurePacket::new);
register(0x0F, ClientKeepAlivePacket::new);
// 0x10 packet not used server-side
register(0x11, ClientPlayerPositionPacket::new);
register(0x12, ClientPlayerPositionAndRotationPacket::new);
register(0x13, ClientPlayerRotationPacket::new);
register(0x14, ClientPlayerPacket::new);
register(0x15, ClientVehicleMovePacket::new);
register(0x16, ClientSteerBoatPacket::new);
register(0x17, ClientPickItemPacket::new);
register(0x18, ClientCraftRecipeRequest::new);
register(0x19, ClientPlayerAbilitiesPacket::new);
register(0x1A, ClientPlayerDiggingPacket::new);
register(0x1B, ClientEntityActionPacket::new);
register(0x1C, ClientSteerVehiclePacket::new);
register(0x1D, ClientPongPacket::new);
register(0x1E, ClientSetRecipeBookStatePacket::new);
register(0x1F, ClientSetDisplayedRecipePacket::new);
register(0x20, ClientNameItemPacket::new);
register(0x21, ClientResourcePackStatusPacket::new);
register(0x22, ClientAdvancementTabPacket::new);
register(0x23, ClientSelectTradePacket::new);
register(0x24, ClientSetBeaconEffectPacket::new);
register(0x25, ClientHeldItemChangePacket::new);
register(0x26, ClientUpdateCommandBlockPacket::new);
register(0x27, ClientUpdateCommandBlockMinecartPacket::new);
register(0x28, ClientCreativeInventoryActionPacket::new);
//Update Jigsaw Block??
register(0x2A, ClientUpdateStructureBlockPacket::new);
register(0x2B, ClientUpdateSignPacket::new);
register(0x2C, ClientAnimationPacket::new);
register(0x2D, ClientSpectatePacket::new);
register(0x2E, ClientPlayerBlockPlacementPacket::new);
register(0x2F, ClientUseItemPacket::new);
}
}
}

View File

@ -1,21 +0,0 @@
package net.minestom.server.network.packet.client;
import net.minestom.server.MinecraftServer;
import net.minestom.server.entity.Player;
import net.minestom.server.listener.manager.PacketListenerManager;
import org.jetbrains.annotations.NotNull;
public abstract class ClientPlayPacket implements ClientPacket {
private static final PacketListenerManager PACKET_LISTENER_MANAGER = MinecraftServer.getPacketListenerManager();
/**
* Processes the packet for {@code player}.
* <p>
* Called during the player tick and forwarded to the {@link PacketListenerManager}.
*
* @param player the player who sent the packet
*/
public void process(@NotNull Player player) {
PACKET_LISTENER_MANAGER.processClientPacket(this, player);
}
}

View File

@ -1,15 +0,0 @@
package net.minestom.server.network.packet.client.handler;
import net.minestom.server.network.packet.client.login.EncryptionResponsePacket;
import net.minestom.server.network.packet.client.login.LoginPluginResponsePacket;
import net.minestom.server.network.packet.client.login.LoginStartPacket;
public class ClientLoginPacketsHandler extends ClientPacketsHandler {
public ClientLoginPacketsHandler() {
register(0, LoginStartPacket::new);
register(1, EncryptionResponsePacket::new);
register(2, LoginPluginResponsePacket::new);
}
}

View File

@ -1,60 +0,0 @@
package net.minestom.server.network.packet.client.handler;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import org.jetbrains.annotations.NotNull;
import java.util.function.Supplier;
/**
* Contains registered packets and a way to instantiate them.
* <p>
* Packets are register using {@link #register(int, ClientPacketSupplier)}
* (you can override a packet id even if not recommended and not officially supported) and retrieved with {@link #getPacketInstance(int)}.
* <p>
* If you want to fill the packet from a buffer, consider using {@link ClientPacket#read(BinaryReader)} after getting the packet instance.
*/
public class ClientPacketsHandler {
// Max packet id
private static final int SIZE = 0x30;
private final ClientPacketSupplier[] supplierAccesses = new ClientPacketSupplier[SIZE];
/**
* Registers a client packet which can be retrieved later using {@link #getPacketInstance(int)}.
*
* @param id the packet id
* @param packetSupplier the supplier of the packet
*/
public void register(int id, @NotNull ClientPacketSupplier packetSupplier) {
this.supplierAccesses[id] = packetSupplier;
}
/**
* Retrieves a {@link net.minestom.server.network.packet.client.ClientPlayPacket} from its id.
*
* @param id the packet id
* @return the associated client packet
* @throws IllegalStateException if {@code id} is not a valid packet id, or unregistered
*/
public ClientPacket getPacketInstance(int id) {
if (id > SIZE)
throw new IllegalStateException("Packet ID 0x" + Integer.toHexString(id) + " has been tried to be parsed, debug needed");
ClientPacketSupplier supplier = supplierAccesses[id];
if (supplierAccesses[id] == null)
throw new IllegalStateException("Packet id 0x" + Integer.toHexString(id) + " isn't registered!");
//ClientPacket packet = supplier.get();
//System.out.println("RECEIVED PACKET 0x" + Integer.toHexString(id)+" : "+packet.getClass().getSimpleName());
return supplier.get();
}
/**
* Convenient interface to supply a {@link ClientPacket}.
*/
protected interface ClientPacketSupplier extends Supplier<ClientPacket> {
}
}

View File

@ -1,59 +0,0 @@
package net.minestom.server.network.packet.client.handler;
import net.minestom.server.network.packet.client.play.*;
public class ClientPlayPacketsHandler extends ClientPacketsHandler {
public ClientPlayPacketsHandler() {
register(0x00, ClientTeleportConfirmPacket::new);
register(0x01, ClientQueryBlockNbtPacket::new);
register(0x03, ClientChatMessagePacket::new);
register(0x04, ClientStatusPacket::new);
register(0x05, ClientSettingsPacket::new);
register(0x06, ClientTabCompletePacket::new);
register(0x07, ClientClickWindowButtonPacket::new);
register(0x08, ClientClickWindowPacket::new);
register(0x09, ClientCloseWindowPacket::new);
register(0x0A, ClientPluginMessagePacket::new);
register(0x0B, ClientEditBookPacket::new);
register(0x0C, ClientQueryEntityNbtPacket::new);
register(0x0D, ClientInteractEntityPacket::new);
register(0x0E, ClientGenerateStructurePacket::new);
register(0x0F, ClientKeepAlivePacket::new);
// 0x10 packet not used server-side
register(0x11, ClientPlayerPositionPacket::new);
register(0x12, ClientPlayerPositionAndRotationPacket::new);
register(0x13, ClientPlayerRotationPacket::new);
register(0x14, ClientPlayerPacket::new);
register(0x15, ClientVehicleMovePacket::new);
register(0x16, ClientSteerBoatPacket::new);
register(0x17, ClientPickItemPacket::new);
register(0x18, ClientCraftRecipeRequest::new);
register(0x19, ClientPlayerAbilitiesPacket::new);
register(0x1A, ClientPlayerDiggingPacket::new);
register(0x1B, ClientEntityActionPacket::new);
register(0x1C, ClientSteerVehiclePacket::new);
register(0x1D, ClientPongPacket::new);
register(0x1E, ClientSetRecipeBookStatePacket::new);
register(0x1F, ClientSetDisplayedRecipePacket::new);
register(0x20, ClientNameItemPacket::new);
register(0x21, ClientResourcePackStatusPacket::new);
register(0x22, ClientAdvancementTabPacket::new);
register(0x23, ClientSelectTradePacket::new);
register(0x24, ClientSetBeaconEffectPacket::new);
register(0x25, ClientHeldItemChangePacket::new);
register(0x26, ClientUpdateCommandBlockPacket::new);
register(0x27, ClientUpdateCommandBlockMinecartPacket::new);
register(0x28, ClientCreativeInventoryActionPacket::new);
//Update Jigsaw Block??
register(0x2A, ClientUpdateStructureBlockPacket::new);
register(0x2B, ClientUpdateSignPacket::new);
register(0x2C, ClientAnimationPacket::new);
register(0x2D, ClientSpectatePacket::new);
register(0x2E, ClientPlayerBlockPlacementPacket::new);
register(0x2F, ClientUseItemPacket::new);
}
}

View File

@ -1,11 +0,0 @@
package net.minestom.server.network.packet.client.handler;
import net.minestom.server.network.packet.client.status.PingPacket;
import net.minestom.server.network.packet.client.status.StatusRequestPacket;
public class ClientStatusPacketsHandler extends ClientPacketsHandler {
public ClientStatusPacketsHandler() {
register(0x00, StatusRequestPacket::new);
register(0x01, PingPacket::new);
}
}

View File

@ -17,7 +17,8 @@ import org.jetbrains.annotations.NotNull;
import java.net.SocketAddress;
import java.util.UUID;
public class HandshakePacket implements ClientPreplayPacket {
public record HandshakePacket(int protocolVersion, @NotNull String serverAddress,
int serverPort, int nextState) implements ClientPreplayPacket {
/**
* Text sent if a player tries to connect with an invalid version of the client
@ -25,24 +26,9 @@ public class HandshakePacket implements ClientPreplayPacket {
private static final Component INVALID_VERSION_TEXT = Component.text("Invalid Version, please use " + MinecraftServer.VERSION_NAME, NamedTextColor.RED);
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 int serverPort;
private int nextState;
@Override
public void read(@NotNull BinaryReader reader) {
this.protocolVersion = reader.readVarInt();
try {
this.serverAddress = reader.readSizedString(BungeeCordProxy.isEnabled() ? Short.MAX_VALUE : 255);
} catch (Exception e) {
if (BungeeCordProxy.isEnabled()) {
System.err.println("Legacy proxy forwarding is enabled but the read did underflow. Please check your proxy.");
}
e.printStackTrace();
}
this.serverPort = reader.readUnsignedShort();
this.nextState = reader.readVarInt();
public HandshakePacket(BinaryReader reader) {
this(reader.readVarInt(), reader.readSizedString(BungeeCordProxy.isEnabled() ? Short.MAX_VALUE : 255),
reader.readUnsignedShort(), reader.readVarInt());
}
@Override
@ -60,13 +46,14 @@ public class HandshakePacket implements ClientPreplayPacket {
@Override
public void process(@NotNull PlayerConnection connection) {
String address = serverAddress;
// Bungee support (IP forwarding)
if (BungeeCordProxy.isEnabled() && connection instanceof PlayerSocketConnection socketConnection) {
if (serverAddress != null) {
final String[] split = serverAddress.split("\00");
if (address != null) {
final String[] split = address.split("\00");
if (split.length == 3 || split.length == 4) {
this.serverAddress = split[0];
address = split[0];
final SocketAddress socketAddress = new java.net.InetSocketAddress(split[1],
((java.net.InetSocketAddress) connection.getRemoteAddress()).getPort());
@ -99,7 +86,7 @@ public class HandshakePacket implements ClientPreplayPacket {
if (connection instanceof PlayerSocketConnection) {
// Give to the connection the server info that the client used
((PlayerSocketConnection) connection).refreshServerInformation(serverAddress, serverPort, protocolVersion);
((PlayerSocketConnection) connection).refreshServerInformation(address, serverPort, protocolVersion);
}
switch (nextState) {

View File

@ -25,15 +25,12 @@ import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.UUID;
public class EncryptionResponsePacket implements ClientPreplayPacket {
public record EncryptionResponsePacket(byte[] sharedSecret, byte[] verifyToken) implements ClientPreplayPacket {
private static final String MOJANG_AUTH_URL = System.getProperty("minestom.auth.url", "https://sessionserver.mojang.com/session/minecraft/hasJoined").concat("?username=%s&serverId=%s");
private static final Gson GSON = new Gson();
private byte[] sharedSecret;
private byte[] verifyToken;
public EncryptionResponsePacket() {
sharedSecret = new byte[0];
verifyToken = new byte[0];
public EncryptionResponsePacket(BinaryReader reader) {
this(reader.readBytes(reader.readVarInt()), reader.readBytes(reader.readVarInt()));
}
@Override
@ -92,12 +89,6 @@ public class EncryptionResponsePacket implements ClientPreplayPacket {
});
}
@Override
public void read(@NotNull BinaryReader reader) {
this.sharedSecret = ByteArrayData.decodeByteArray(reader);
this.verifyToken = ByteArrayData.decodeByteArray(reader);
}
@Override
public void write(@NotNull BinaryWriter writer) {
ByteArrayData.encodeByteArray(writer, sharedSecret);

View File

@ -14,19 +14,20 @@ import net.minestom.server.network.player.PlayerSocketConnection;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.UUID;
public class LoginPluginResponsePacket implements ClientPreplayPacket {
public record LoginPluginResponsePacket(int messageId, byte @Nullable [] data) implements ClientPreplayPacket {
private final static ConnectionManager CONNECTION_MANAGER = MinecraftServer.getConnectionManager();
public static final Component INVALID_PROXY_RESPONSE = Component.text("Invalid proxy response!", NamedTextColor.RED);
public int messageId;
public boolean successful;
public byte[] data = new byte[0];
public LoginPluginResponsePacket(BinaryReader reader) {
this(reader.readVarInt(), reader.readBoolean() ? reader.readRemainingBytes() : null);
}
@Override
public void process(@NotNull PlayerConnection connection) {
@ -82,21 +83,10 @@ public class LoginPluginResponsePacket implements ClientPreplayPacket {
}
}
@Override
public void read(@NotNull BinaryReader reader) {
this.messageId = reader.readVarInt();
this.successful = reader.readBoolean();
if (successful) {
this.data = reader.readRemainingBytes();
}
}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeVarInt(messageId);
writer.writeBoolean(successful);
if (successful) {
writer.writeBytes(data);
}
writer.writeBoolean(data != null);
if (data != null) writer.writeBytes(data);
}
}

View File

@ -21,11 +21,12 @@ import org.jetbrains.annotations.NotNull;
import java.util.UUID;
import java.util.concurrent.ThreadLocalRandom;
public class LoginStartPacket implements ClientPreplayPacket {
public record LoginStartPacket(@NotNull String username) implements ClientPreplayPacket {
private static final Component ALREADY_CONNECTED = Component.text("You are already on this server", NamedTextColor.RED);
public String username = "";
public LoginStartPacket(BinaryReader reader) {
this(reader.readSizedString(16));
}
@Override
public void process(@NotNull PlayerConnection connection) {
@ -50,12 +51,7 @@ public class LoginStartPacket implements ClientPreplayPacket {
final String channel = VelocityProxy.PLAYER_INFO_CHANNEL;
// Important in order to retrieve the channel in the response packet
socketConnection.addPluginRequestEntry(messageId, channel);
LoginPluginRequestPacket loginPluginRequestPacket = new LoginPluginRequestPacket();
loginPluginRequestPacket.messageId = messageId;
loginPluginRequestPacket.channel = channel;
loginPluginRequestPacket.data = null;
connection.sendPacket(loginPluginRequestPacket);
connection.sendPacket(new LoginPluginRequestPacket(messageId, channel, null));
return;
}
}
@ -69,8 +65,12 @@ public class LoginStartPacket implements ClientPreplayPacket {
}
final PlayerSocketConnection socketConnection = (PlayerSocketConnection) connection;
socketConnection.setConnectionState(ConnectionState.LOGIN);
EncryptionRequestPacket encryptionRequestPacket = new EncryptionRequestPacket(socketConnection);
socketConnection.sendPacket(encryptionRequestPacket);
final byte[] publicKey = MojangAuth.getKeyPair().getPublic().getEncoded();
byte[] nonce = new byte[4];
ThreadLocalRandom.current().nextBytes(nonce);
socketConnection.setNonce(nonce);
socketConnection.sendPacket(new EncryptionRequestPacket("", publicKey, nonce));
} else {
final boolean bungee = BungeeCordProxy.isEnabled();
// Offline
@ -85,11 +85,6 @@ public class LoginStartPacket implements ClientPreplayPacket {
}
}
@Override
public void read(@NotNull BinaryReader reader) {
this.username = reader.readSizedString(16);
}
@Override
public void write(@NotNull BinaryWriter writer) {
if (username.length() > 16)

View File

@ -1,31 +1,34 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.advancements.AdvancementAction;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class ClientAdvancementTabPacket extends ClientPlayPacket {
public record ClientAdvancementTabPacket(@NotNull AdvancementAction action,
@Nullable String tabIdentifier) implements ClientPacket {
public ClientAdvancementTabPacket(BinaryReader reader) {
this(read(reader));
}
public AdvancementAction action = AdvancementAction.OPENED_TAB;
public String tabIdentifier = "";
private ClientAdvancementTabPacket(ClientAdvancementTabPacket packet) {
this(packet.action, packet.tabIdentifier);
}
@Override
public void read(@NotNull BinaryReader reader) {
this.action = AdvancementAction.values()[reader.readVarInt()];
if (action == AdvancementAction.OPENED_TAB) {
this.tabIdentifier = reader.readSizedString(256);
}
private static ClientAdvancementTabPacket read(BinaryReader reader) {
var action = AdvancementAction.values()[reader.readVarInt()];
var tabIdentifier = action == AdvancementAction.OPENED_TAB ? reader.readSizedString(256) : null;
return new ClientAdvancementTabPacket(action, tabIdentifier);
}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeVarInt(action.ordinal());
if(action == AdvancementAction.OPENED_TAB) {
if(tabIdentifier.length() > 256) {
if (action == AdvancementAction.OPENED_TAB) {
assert tabIdentifier != null;
if (tabIdentifier.length() > 256) {
throw new IllegalArgumentException("Tab identifier cannot be longer than 256 characters.");
}
writer.writeSizedString(tabIdentifier);

View File

@ -1,18 +1,14 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.entity.Player;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ClientAnimationPacket extends ClientPlayPacket {
public Player.Hand hand = Player.Hand.MAIN;
@Override
public void read(@NotNull BinaryReader reader) {
this.hand = Player.Hand.values()[reader.readVarInt()];
public record ClientAnimationPacket(@NotNull Player.Hand hand) implements ClientPacket {
public ClientAnimationPacket(BinaryReader reader) {
this(Player.Hand.values()[reader.readVarInt()]);
}
@Override

View File

@ -1,22 +1,18 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ClientChatMessagePacket extends ClientPlayPacket {
public String message = "";
@Override
public void read(@NotNull BinaryReader reader) {
this.message = reader.readSizedString(256);
public record ClientChatMessagePacket(@NotNull String message) implements ClientPacket {
public ClientChatMessagePacket(BinaryReader reader) {
this(reader.readSizedString(256));
}
@Override
public void write(@NotNull BinaryWriter writer) {
if(message.length() > 256) {
if (message.length() > 256) {
throw new IllegalArgumentException("Message cannot be more than 256 characters long.");
}
writer.writeSizedString(message);

View File

@ -1,19 +1,13 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ClientClickWindowButtonPacket extends ClientPlayPacket {
public byte windowId;
public byte buttonId;
@Override
public void read(@NotNull BinaryReader reader) {
this.windowId = reader.readByte();
this.buttonId = reader.readByte();
public record ClientClickWindowButtonPacket(byte windowId, byte buttonId) implements ClientPacket {
public ClientClickWindowButtonPacket(BinaryReader reader) {
this(reader.readByte(), reader.readByte());
}
@Override

View File

@ -1,39 +1,26 @@
package net.minestom.server.network.packet.client.play;
import it.unimi.dsi.fastutil.shorts.Short2ObjectMap;
import it.unimi.dsi.fastutil.shorts.Short2ObjectOpenHashMap;
import net.minestom.server.item.ItemStack;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import net.minestom.server.utils.binary.Writeable;
import org.jetbrains.annotations.NotNull;
public class ClientClickWindowPacket extends ClientPlayPacket {
import java.util.List;
public byte windowId;
public int stateId;
public short slot;
public byte button;
public ClickType clickType = ClickType.PICKUP;
public Short2ObjectMap<ItemStack> changedSlots = new Short2ObjectOpenHashMap<>();
public ItemStack item = ItemStack.AIR;
public record ClientClickWindowPacket(byte windowId, int stateId,
short slot, byte button, @NotNull ClickType clickType,
@NotNull List<ChangedSlot> changedSlots,
@NotNull ItemStack clickedItem) implements ClientPacket {
public ClientClickWindowPacket {
changedSlots = List.copyOf(changedSlots);
}
@Override
public void read(@NotNull BinaryReader reader) {
this.windowId = reader.readByte();
this.stateId = reader.readVarInt();
this.slot = reader.readShort();
this.button = reader.readByte();
this.clickType = ClickType.values()[reader.readVarInt()];
final int length = reader.readVarInt();
this.changedSlots = new Short2ObjectOpenHashMap<>(length);
for (int i = 0; i < length; i++) {
short slot = reader.readShort();
ItemStack item = reader.readItemStack();
changedSlots.put(slot, item);
}
this.item = reader.readItemStack();
public ClientClickWindowPacket(BinaryReader reader) {
this(reader.readByte(), reader.readVarInt(),
reader.readShort(), reader.readByte(), ClickType.values()[reader.readVarInt()],
reader.readVarIntList(ChangedSlot::new), reader.readItemStack());
}
@Override
@ -43,13 +30,20 @@ public class ClientClickWindowPacket extends ClientPlayPacket {
writer.writeShort(slot);
writer.writeByte(button);
writer.writeVarInt(clickType.ordinal());
writer.writeVarIntList(changedSlots, BinaryWriter::write);
writer.writeItemStack(clickedItem);
}
writer.writeVarInt(changedSlots.size());
changedSlots.forEach((slot, itemStack) -> {
public record ChangedSlot(short slot, @NotNull ItemStack item) implements Writeable {
public ChangedSlot(BinaryReader reader) {
this(reader.readShort(), reader.readItemStack());
}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeShort(slot);
writer.writeItemStack(itemStack);
});
writer.writeItemStack(item);
writer.writeItemStack(item);
}
}
public enum ClickType {

View File

@ -1,17 +1,13 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ClientCloseWindowPacket extends ClientPlayPacket {
public byte windowId;
@Override
public void read(@NotNull BinaryReader reader) {
this.windowId = reader.readByte();
public record ClientCloseWindowPacket(byte windowId) implements ClientPacket {
public ClientCloseWindowPacket(BinaryReader reader) {
this(reader.readByte());
}
@Override

View File

@ -1,29 +1,24 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ClientCraftRecipeRequest extends ClientPlayPacket {
public record ClientCraftRecipeRequest(byte windowId, String recipe, boolean makeAll) implements ClientPacket {
public ClientCraftRecipeRequest {
if (recipe.length() > 256) {
throw new IllegalArgumentException("'recipe' cannot be longer than 256 characters.");
}
}
public byte windowId;
public String recipe = "";
public boolean makeAll;
@Override
public void read(@NotNull BinaryReader reader) {
this.windowId = reader.readByte();
this.recipe = reader.readSizedString(256);
this.makeAll = reader.readBoolean();
public ClientCraftRecipeRequest(BinaryReader reader) {
this(reader.readByte(), reader.readSizedString(256), reader.readBoolean());
}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeByte(windowId);
if(recipe.length() > 256) {
throw new IllegalArgumentException("'recipe' cannot be longer than 256 characters.");
}
writer.writeSizedString(recipe);
writer.writeBoolean(makeAll);
}

View File

@ -1,20 +1,14 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.item.ItemStack;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ClientCreativeInventoryActionPacket extends ClientPlayPacket {
public short slot;
public ItemStack item = ItemStack.AIR;
@Override
public void read(@NotNull BinaryReader reader) {
this.slot = reader.readShort();
this.item = reader.readItemStack();
public record ClientCreativeInventoryActionPacket(short slot, @NotNull ItemStack item) implements ClientPacket {
public ClientCreativeInventoryActionPacket(BinaryReader reader) {
this(reader.readShort(), reader.readItemStack());
}
@Override

View File

@ -1,45 +1,29 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class ClientEditBookPacket extends ClientPlayPacket {
import java.util.List;
public int slot;
public String[] pages;
public String title;
public ClientEditBookPacket(int slot, String[] pages, String title) {
this.slot = slot;
this.pages = pages;
this.title = title;
public record ClientEditBookPacket(int slot, @NotNull List<String> pages,
@Nullable String title) implements ClientPacket {
public ClientEditBookPacket {
pages = List.copyOf(pages);
}
public ClientEditBookPacket() {
this(0, null, "");
}
@Override
public void read(@NotNull BinaryReader reader) {
this.slot = reader.readVarInt();
final int pageLength = reader.readVarInt();
this.pages = new String[pageLength];
for (int i = 0; i < pageLength; i++) {
pages[i] = reader.readSizedString(8192);
}
this.title = reader.readBoolean() ? reader.readSizedString(128) : null;
public ClientEditBookPacket(BinaryReader reader) {
this(reader.readVarInt(), reader.readVarIntList(BinaryReader::readSizedString),
reader.readBoolean() ? reader.readSizedString(128) : null);
}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeVarInt(slot);
writer.writeStringArray(pages);
final boolean hasTitle = title != null;
writer.writeBoolean(hasTitle);
if (hasTitle) {
writer.writeSizedString(title);
}
writer.writeVarIntList(pages, BinaryWriter::writeSizedString);
writer.writeBoolean(title != null);
if (title != null) writer.writeSizedString(title);
}
}

View File

@ -1,21 +1,15 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ClientEntityActionPacket extends ClientPlayPacket {
public int playerId;
public Action action = Action.START_SNEAKING;
public int horseJumpBoost;
@Override
public void read(@NotNull BinaryReader reader) {
this.playerId = reader.readVarInt();
this.action = Action.values()[reader.readVarInt()];
this.horseJumpBoost = reader.readVarInt();
public record ClientEntityActionPacket(int playerId, @NotNull Action action,
int horseJumpBoost) implements ClientPacket {
public ClientEntityActionPacket(BinaryReader reader) {
this(reader.readVarInt(), Action.values()[reader.readVarInt()],
reader.readVarInt());
}
@Override
@ -36,5 +30,4 @@ public class ClientEntityActionPacket extends ClientPlayPacket {
OPEN_HORSE_INVENTORY,
START_FLYING_ELYTRA
}
}

View File

@ -1,23 +1,15 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.coordinate.Point;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import net.minestom.server.coordinate.Point;
import net.minestom.server.coordinate.Vec;
import org.jetbrains.annotations.NotNull;
public class ClientGenerateStructurePacket extends ClientPlayPacket {
public Point blockPosition = Vec.ZERO;
public int level;
public boolean keepJigsaws;
@Override
public void read(@NotNull BinaryReader reader) {
this.blockPosition = reader.readBlockPosition();
this.level = reader.readVarInt();
this.keepJigsaws = reader.readBoolean();
public record ClientGenerateStructurePacket(@NotNull Point blockPosition,
int level, boolean keepJigsaws) implements ClientPacket {
public ClientGenerateStructurePacket(BinaryReader reader) {
this(reader.readBlockPosition(), reader.readVarInt(), reader.readBoolean());
}
@Override

View File

@ -1,17 +1,13 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ClientHeldItemChangePacket extends ClientPlayPacket {
public short slot;
@Override
public void read(@NotNull BinaryReader reader) {
this.slot = reader.readShort();
public record ClientHeldItemChangePacket(short slot) implements ClientPacket {
public ClientHeldItemChangePacket(BinaryReader reader) {
this(reader.readShort());
}
@Override

View File

@ -1,66 +1,81 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.entity.Player;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import net.minestom.server.utils.binary.Writeable;
import org.jetbrains.annotations.NotNull;
public class ClientInteractEntityPacket extends ClientPlayPacket {
public int targetId;
public Type type = Type.INTERACT;
public float x;
public float y;
public float z;
public Player.Hand hand = Player.Hand.MAIN;
public boolean sneaking;
@Override
public void read(@NotNull BinaryReader reader) {
this.targetId = reader.readVarInt();
this.type = Type.values()[reader.readVarInt()];
switch (type) {
case INTERACT:
this.hand = Player.Hand.values()[reader.readVarInt()];
break;
case ATTACK:
break;
case INTERACT_AT:
this.x = reader.readFloat();
this.y = reader.readFloat();
this.z = reader.readFloat();
this.hand = Player.Hand.values()[reader.readVarInt()];
break;
}
this.sneaking = reader.readBoolean();
public record ClientInteractEntityPacket(int targetId, @NotNull Type type, boolean sneaking) implements ClientPacket {
public ClientInteractEntityPacket(BinaryReader reader) {
this(reader.readVarInt(), switch (reader.readVarInt()) {
case 0 -> new Interact(reader);
case 1 -> new Attack();
case 2 -> new InteractAt(reader);
default -> throw new RuntimeException("Unknown action id");
}, reader.readBoolean());
}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeVarInt(targetId);
writer.writeVarInt(type.ordinal());
switch (type) {
case INTERACT:
writer.writeVarInt(hand.ordinal());
break;
case ATTACK:
break;
case INTERACT_AT:
writer.writeFloat(x);
writer.writeFloat(y);
writer.writeFloat(z);
writer.writeVarInt(hand.ordinal());
break;
}
writer.writeVarInt(type.id());
writer.write(type);
writer.writeBoolean(sneaking);
}
public enum Type {
INTERACT,
ATTACK,
INTERACT_AT
public sealed interface Type extends Writeable
permits Interact, Attack, InteractAt {
int id();
}
public record Interact(@NotNull Player.Hand hand) implements Type {
public Interact(BinaryReader reader) {
this(Player.Hand.values()[reader.readVarInt()]);
}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeVarInt(hand.ordinal());
}
@Override
public int id() {
return 0;
}
}
public record Attack() implements Type {
@Override
public void write(@NotNull BinaryWriter writer) {
// Empty
}
@Override
public int id() {
return 1;
}
}
public record InteractAt(float targetX, float targetY, float targetZ,
Player.Hand hand) implements Type {
public InteractAt(BinaryReader reader) {
this(reader.readFloat(), reader.readFloat(), reader.readFloat(),
Player.Hand.values()[reader.readVarInt()]);
}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeFloat(targetX);
writer.writeFloat(targetY);
writer.writeFloat(targetZ);
writer.writeVarInt(hand.ordinal());
}
@Override
public int id() {
return 2;
}
}
}

View File

@ -1,17 +1,13 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ClientKeepAlivePacket extends ClientPlayPacket {
public long id;
@Override
public void read(@NotNull BinaryReader reader) {
this.id = reader.readLong();
public record ClientKeepAlivePacket(long id) implements ClientPacket {
public ClientKeepAlivePacket(BinaryReader reader) {
this(reader.readLong());
}
@Override

View File

@ -1,24 +1,23 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ClientNameItemPacket extends ClientPlayPacket {
public record ClientNameItemPacket(@NotNull String itemName) implements ClientPacket {
public ClientNameItemPacket {
if (itemName.length() > Short.MAX_VALUE) {
throw new IllegalArgumentException("ItemStack name cannot be longer than Short.MAX_VALUE characters!");
}
}
public String itemName = "";
@Override
public void read(@NotNull BinaryReader reader) {
this.itemName = reader.readSizedString(Short.MAX_VALUE);
public ClientNameItemPacket(BinaryReader reader) {
this(reader.readSizedString(Short.MAX_VALUE));
}
@Override
public void write(@NotNull BinaryWriter writer) {
if(itemName.length() > Short.MAX_VALUE) {
throw new IllegalArgumentException("ItemStack name cannot be longer than Short.MAX_VALUE characters!");
}
writer.writeSizedString(itemName);
}
}

View File

@ -1,21 +1,17 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ClientPickItemPacket extends ClientPlayPacket {
public int slotToUse;
@Override
public void read(@NotNull BinaryReader reader) {
this.slotToUse = reader.readVarInt();
public record ClientPickItemPacket(int slot) implements ClientPacket {
public ClientPickItemPacket(BinaryReader reader) {
this(reader.readVarInt());
}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeVarInt(slotToUse);
writer.writeVarInt(slot);
}
}

View File

@ -1,17 +1,13 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ClientPlayerAbilitiesPacket extends ClientPlayPacket {
public byte flags;
@Override
public void read(@NotNull BinaryReader reader) {
this.flags = reader.readByte();
public record ClientPlayerAbilitiesPacket(byte flags) implements ClientPacket {
public ClientPlayerAbilitiesPacket(BinaryReader reader) {
this(reader.readByte());
}
@Override

View File

@ -1,31 +1,22 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.coordinate.Point;
import net.minestom.server.entity.Player;
import net.minestom.server.instance.block.BlockFace;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import net.minestom.server.coordinate.Point;
import net.minestom.server.coordinate.Vec;
import org.jetbrains.annotations.NotNull;
public class ClientPlayerBlockPlacementPacket extends ClientPlayPacket {
public Player.Hand hand = Player.Hand.MAIN;
public Point blockPosition = Vec.ZERO;
public BlockFace blockFace = BlockFace.TOP;
public float cursorPositionX, cursorPositionY, cursorPositionZ;
public boolean insideBlock;
@Override
public void read(@NotNull BinaryReader reader) {
this.hand = Player.Hand.values()[reader.readVarInt()];
this.blockPosition = reader.readBlockPosition();
this.blockFace = BlockFace.values()[reader.readVarInt()];
this.cursorPositionX = reader.readFloat();
this.cursorPositionY = reader.readFloat();
this.cursorPositionZ = reader.readFloat();
this.insideBlock = reader.readBoolean();
public record ClientPlayerBlockPlacementPacket(@NotNull Player.Hand hand, @NotNull Point blockPosition,
@NotNull BlockFace blockFace,
float cursorPositionX, float cursorPositionY, float cursorPositionZ,
boolean insideBlock) implements ClientPacket {
public ClientPlayerBlockPlacementPacket(BinaryReader reader) {
this(Player.Hand.values()[reader.readVarInt()], reader.readBlockPosition(),
BlockFace.values()[reader.readVarInt()],
reader.readFloat(), reader.readFloat(), reader.readFloat(),
reader.readBoolean());
}
@Override

View File

@ -1,24 +1,17 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.coordinate.Point;
import net.minestom.server.instance.block.BlockFace;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import net.minestom.server.coordinate.Point;
import net.minestom.server.coordinate.Vec;
import org.jetbrains.annotations.NotNull;
public class ClientPlayerDiggingPacket extends ClientPlayPacket {
public Status status = Status.SWAP_ITEM_HAND;
public Point blockPosition = Vec.ZERO;
public BlockFace blockFace = BlockFace.TOP;
@Override
public void read(@NotNull BinaryReader reader) {
this.status = Status.values()[reader.readVarInt()];
this.blockPosition = reader.readBlockPosition();
this.blockFace = BlockFace.values()[reader.readByte()];
public record ClientPlayerDiggingPacket(@NotNull Status status, @NotNull Point blockPosition,
@NotNull BlockFace blockFace) implements ClientPacket {
public ClientPlayerDiggingPacket(BinaryReader reader) {
this(Status.values()[reader.readVarInt()], reader.readBlockPosition(),
BlockFace.values()[reader.readByte()]);
}
@Override
@ -37,5 +30,4 @@ public class ClientPlayerDiggingPacket extends ClientPlayPacket {
UPDATE_ITEM_STATE,
SWAP_ITEM_HAND
}
}

View File

@ -1,17 +1,13 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ClientPlayerPacket extends ClientPlayPacket {
public boolean onGround;
@Override
public void read(@NotNull BinaryReader reader) {
this.onGround = reader.readBoolean();
public record ClientPlayerPacket(boolean onGround) implements ClientPacket {
public ClientPlayerPacket(BinaryReader reader) {
this(reader.readBoolean());
}
@Override

View File

@ -1,37 +1,25 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.coordinate.Pos;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ClientPlayerPositionAndRotationPacket extends ClientPlayPacket {
public double x, y, z;
public float yaw, pitch;
public boolean onGround;
@Override
public void read(@NotNull BinaryReader reader) {
this.x = reader.readDouble();
this.y = reader.readDouble();
this.z = reader.readDouble();
this.yaw = reader.readFloat();
this.pitch = reader.readFloat();
this.onGround = reader.readBoolean();
public record ClientPlayerPositionAndRotationPacket(@NotNull Pos position,
boolean onGround) implements ClientPacket {
public ClientPlayerPositionAndRotationPacket(BinaryReader reader) {
this(new Pos(reader.readDouble(), reader.readDouble(), reader.readDouble(),
reader.readFloat(), reader.readFloat()), reader.readBoolean());
}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeDouble(x);
writer.writeDouble(y);
writer.writeDouble(z);
writer.writeFloat(yaw);
writer.writeFloat(pitch);
writer.writeDouble(position.x());
writer.writeDouble(position.y());
writer.writeDouble(position.z());
writer.writeFloat(position.yaw());
writer.writeFloat(position.pitch());
writer.writeBoolean(onGround);
}
}

View File

@ -1,30 +1,24 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.coordinate.Point;
import net.minestom.server.coordinate.Vec;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ClientPlayerPositionPacket extends ClientPlayPacket {
public double x, y, z;
public boolean onGround;
@Override
public void read(@NotNull BinaryReader reader) {
this.x = reader.readDouble();
this.y = reader.readDouble();
this.z = reader.readDouble();
this.onGround = reader.readBoolean();
public record ClientPlayerPositionPacket(@NotNull Point position,
boolean onGround) implements ClientPacket {
public ClientPlayerPositionPacket(BinaryReader reader) {
this(new Vec(reader.readDouble(), reader.readDouble(), reader.readDouble()),
reader.readBoolean());
}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeDouble(x);
writer.writeDouble(y);
writer.writeDouble(z);
writer.writeDouble(position.x());
writer.writeDouble(position.y());
writer.writeDouble(position.z());
writer.writeBoolean(onGround);
}
}

View File

@ -1,20 +1,13 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ClientPlayerRotationPacket extends ClientPlayPacket {
public float yaw, pitch;
public boolean onGround;
@Override
public void read(@NotNull BinaryReader reader) {
this.yaw = reader.readFloat();
this.pitch = reader.readFloat();
this.onGround = reader.readBoolean();
public record ClientPlayerRotationPacket(float yaw, float pitch, boolean onGround) implements ClientPacket {
public ClientPlayerRotationPacket(BinaryReader reader) {
this(reader.readFloat(), reader.readFloat(), reader.readBoolean());
}
@Override

View File

@ -1,25 +1,22 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ClientPluginMessagePacket extends ClientPlayPacket {
public record ClientPluginMessagePacket(@NotNull String channel, byte[] data) implements ClientPacket {
public ClientPluginMessagePacket {
if (channel.length() > 256)
throw new IllegalArgumentException("Channel cannot be more than 256 characters long");
}
public String channel = "";
public byte[] data = new byte[0];
@Override
public void read(@NotNull BinaryReader reader) {
this.channel = reader.readSizedString(256);
this.data = reader.readRemainingBytes();
public ClientPluginMessagePacket(BinaryReader reader) {
this(reader.readSizedString(256), reader.readRemainingBytes());
}
@Override
public void write(@NotNull BinaryWriter writer) {
if(channel.length() > 256)
throw new IllegalArgumentException("Channel cannot be more than 256 characters long");
writer.writeSizedString(channel);
writer.writeBytes(data);
}

View File

@ -1,17 +1,13 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ClientPongPacket extends ClientPlayPacket {
public int id;
@Override
public void read(@NotNull BinaryReader reader) {
this.id = reader.readInt();
public record ClientPongPacket(int id) implements ClientPacket {
public ClientPongPacket(BinaryReader reader) {
this(reader.readInt());
}
@Override

View File

@ -1,21 +1,14 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.coordinate.Point;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import net.minestom.server.coordinate.Point;
import net.minestom.server.coordinate.Vec;
import org.jetbrains.annotations.NotNull;
public class ClientQueryBlockNbtPacket extends ClientPlayPacket {
public int transactionId;
public Point blockPosition = Vec.ZERO;
@Override
public void read(@NotNull BinaryReader reader) {
this.transactionId = reader.readVarInt();
this.blockPosition = reader.readBlockPosition();
public record ClientQueryBlockNbtPacket(int transactionId, @NotNull Point blockPosition) implements ClientPacket {
public ClientQueryBlockNbtPacket(BinaryReader reader) {
this(reader.readVarInt(), reader.readBlockPosition());
}
@Override

View File

@ -1,19 +1,13 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ClientQueryEntityNbtPacket extends ClientPlayPacket {
public int transactionId;
public int entityId;
@Override
public void read(@NotNull BinaryReader reader) {
this.transactionId = reader.readVarInt();
this.entityId = reader.readVarInt();
public record ClientQueryEntityNbtPacket(int transactionId, int entityId) implements ClientPacket {
public ClientQueryEntityNbtPacket(BinaryReader reader) {
this(reader.readVarInt(), reader.readVarInt());
}
@Override

View File

@ -1,22 +1,18 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.resourcepack.ResourcePackStatus;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ClientResourcePackStatusPacket extends ClientPlayPacket {
public ResourcePackStatus result = ResourcePackStatus.SUCCESS;
@Override
public void read(@NotNull BinaryReader reader) {
this.result = ResourcePackStatus.values()[reader.readVarInt()];
public record ClientResourcePackStatusPacket(@NotNull ResourcePackStatus status) implements ClientPacket {
public ClientResourcePackStatusPacket(BinaryReader reader) {
this(ResourcePackStatus.values()[reader.readVarInt()]);
}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeVarInt(result.ordinal());
writer.writeVarInt(status.ordinal());
}
}

View File

@ -1,17 +1,13 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ClientSelectTradePacket extends ClientPlayPacket {
public int selectedSlot;
@Override
public void read(@NotNull BinaryReader reader) {
this.selectedSlot = reader.readVarInt();
public record ClientSelectTradePacket(int selectedSlot) implements ClientPacket {
public ClientSelectTradePacket(BinaryReader reader) {
this(reader.readVarInt());
}
@Override

View File

@ -1,19 +1,13 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ClientSetBeaconEffectPacket extends ClientPlayPacket {
public int primaryEffect;
public int secondaryEffect;
@Override
public void read(@NotNull BinaryReader reader) {
this.primaryEffect = reader.readVarInt();
this.secondaryEffect = reader.readVarInt();
public record ClientSetBeaconEffectPacket(int primaryEffect, int secondaryEffect) implements ClientPacket {
public ClientSetBeaconEffectPacket(BinaryReader reader) {
this(reader.readVarInt(), reader.readVarInt());
}
@Override

View File

@ -1,17 +1,13 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ClientSetDisplayedRecipePacket extends ClientPlayPacket {
public String recipeId = "";
@Override
public void read(@NotNull BinaryReader reader) {
this.recipeId = reader.readSizedString(256);
public record ClientSetDisplayedRecipePacket(@NotNull String recipeId) implements ClientPacket {
public ClientSetDisplayedRecipePacket(BinaryReader reader) {
this(reader.readSizedString(256));
}
@Override

View File

@ -1,26 +1,19 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ClientSetRecipeBookStatePacket extends ClientPlayPacket {
public BookType type = BookType.CRAFTING;
public boolean bookOpen;
public boolean filterActive;
@Override
public void read(@NotNull BinaryReader reader) {
this.type = BookType.values()[reader.readVarInt()];
this.bookOpen = reader.readBoolean();
this.filterActive = reader.readBoolean();
public record ClientSetRecipeBookStatePacket(@NotNull BookType bookType,
boolean bookOpen, boolean filterActive) implements ClientPacket {
public ClientSetRecipeBookStatePacket(BinaryReader reader) {
this(BookType.values()[reader.readVarInt()], reader.readBoolean(), reader.readBoolean());
}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeVarInt(type.ordinal());
writer.writeVarInt(bookType.ordinal());
writer.writeBoolean(bookOpen);
writer.writeBoolean(filterActive);
}

View File

@ -2,32 +2,20 @@ package net.minestom.server.network.packet.client.play;
import net.minestom.server.entity.Player;
import net.minestom.server.message.ChatMessageType;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ClientSettingsPacket extends ClientPlayPacket {
public String locale = "";
public byte viewDistance;
public ChatMessageType chatMessageType = ChatMessageType.FULL;
public boolean chatColors;
public byte displayedSkinParts;
public Player.MainHand mainHand = Player.MainHand.RIGHT;
public boolean disableTextFiltering;
public boolean allowsListing;
@Override
public void read(@NotNull BinaryReader reader) {
this.locale = reader.readSizedString(128);
this.viewDistance = reader.readByte();
this.chatMessageType = ChatMessageType.fromPacketID(reader.readVarInt());
this.chatColors = reader.readBoolean();
this.displayedSkinParts = reader.readByte();
this.mainHand = Player.MainHand.values()[reader.readVarInt()];
this.disableTextFiltering = reader.readBoolean();
this.allowsListing = reader.readBoolean();
public record ClientSettingsPacket(@NotNull String locale, byte viewDistance,
@NotNull ChatMessageType chatMessageType, boolean chatColors,
byte displayedSkinParts, @NotNull Player.MainHand mainHand,
boolean disableTextFiltering, boolean allowsListing) implements ClientPacket {
public ClientSettingsPacket(BinaryReader reader) {
this(reader.readSizedString(128), reader.readByte(),
ChatMessageType.fromPacketID(reader.readVarInt()), reader.readBoolean(),
reader.readByte(), Player.MainHand.values()[reader.readVarInt()],
reader.readBoolean(), reader.readBoolean());
}
@Override

View File

@ -1,23 +1,19 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
public class ClientSpectatePacket extends ClientPlayPacket {
public UUID targetUuid = new UUID(0,0);
@Override
public void read(@NotNull BinaryReader reader) {
this.targetUuid = reader.readUuid();
public record ClientSpectatePacket(@NotNull UUID target) implements ClientPacket {
public ClientSpectatePacket(BinaryReader reader) {
this(reader.readUuid());
}
@Override
public void write(@NotNull BinaryWriter writer) {
writer.writeUuid(targetUuid);
writer.writeUuid(target);
}
}

View File

@ -1,21 +1,13 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ClientStatusPacket extends ClientPlayPacket {
public Action action;
public ClientStatusPacket() {
action = Action.REQUEST_STATS;
}
@Override
public void read(@NotNull BinaryReader reader) {
this.action = Action.values()[reader.readVarInt()];
public record ClientStatusPacket(@NotNull Action action) implements ClientPacket {
public ClientStatusPacket(BinaryReader reader) {
this(Action.values()[reader.readVarInt()]);
}
@Override
@ -27,5 +19,4 @@ public class ClientStatusPacket extends ClientPlayPacket {
PERFORM_RESPAWN,
REQUEST_STATS
}
}

View File

@ -1,19 +1,13 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ClientSteerBoatPacket extends ClientPlayPacket {
public boolean leftPaddleTurning;
public boolean rightPaddleTurning;
@Override
public void read(@NotNull BinaryReader reader) {
this.leftPaddleTurning = reader.readBoolean();
this.rightPaddleTurning = reader.readBoolean();
public record ClientSteerBoatPacket(boolean leftPaddleTurning, boolean rightPaddleTurning) implements ClientPacket {
public ClientSteerBoatPacket(BinaryReader reader) {
this(reader.readBoolean(), reader.readBoolean());
}
@Override

View File

@ -1,21 +1,14 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ClientSteerVehiclePacket extends ClientPlayPacket {
public float sideways;
public float forward;
public byte flags;
@Override
public void read(@NotNull BinaryReader reader) {
this.sideways = reader.readFloat();
this.forward = reader.readFloat();
this.flags = reader.readByte();
public record ClientSteerVehiclePacket(float sideways, float forward,
byte flags) implements ClientPacket {
public ClientSteerVehiclePacket(BinaryReader reader) {
this(reader.readFloat(), reader.readFloat(), reader.readByte());
}
@Override

View File

@ -1,19 +1,13 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ClientTabCompletePacket extends ClientPlayPacket {
public int transactionId;
public String text = "";
@Override
public void read(@NotNull BinaryReader reader) {
this.transactionId = reader.readVarInt();
this.text = reader.readSizedString(Short.MAX_VALUE);
public record ClientTabCompletePacket(int transactionId, @NotNull String text) implements ClientPacket {
public ClientTabCompletePacket(BinaryReader reader) {
this(reader.readVarInt(), reader.readSizedString(Short.MAX_VALUE));
}
@Override

View File

@ -1,17 +1,13 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ClientTeleportConfirmPacket extends ClientPlayPacket {
public int teleportId;
@Override
public void read(@NotNull BinaryReader reader) {
this.teleportId = reader.readVarInt();
public record ClientTeleportConfirmPacket(int teleportId) implements ClientPacket {
public ClientTeleportConfirmPacket(BinaryReader reader) {
this(reader.readVarInt());
}
@Override

View File

@ -1,21 +1,14 @@
package net.minestom.server.network.packet.client.play;
import net.minestom.server.network.packet.client.ClientPlayPacket;
import net.minestom.server.network.packet.client.ClientPacket;
import net.minestom.server.utils.binary.BinaryReader;
import net.minestom.server.utils.binary.BinaryWriter;
import org.jetbrains.annotations.NotNull;
public class ClientUpdateCommandBlockMinecartPacket extends ClientPlayPacket {
public int entityId;
public String command = "";
public boolean trackOutput;
@Override
public void read(@NotNull BinaryReader reader) {
this.entityId = reader.readVarInt();
this.command = reader.readSizedString(Short.MAX_VALUE);
this.trackOutput = reader.readBoolean();
public record ClientUpdateCommandBlockMinecartPacket(int entityId, @NotNull String command,
boolean trackOutput) implements ClientPacket {
public ClientUpdateCommandBlockMinecartPacket(BinaryReader reader) {
this(reader.readVarInt(), reader.readSizedString(Short.MAX_VALUE), reader.readBoolean());
}
@Override

Some files were not shown because too many files have changed in this diff Show More