From 39a09233261f664af2ec7a1b21e7d0906e957370 Mon Sep 17 00:00:00 2001 From: themode Date: Wed, 22 Dec 2021 08:06:00 +0100 Subject: [PATCH] Add LazyPacket --- .../net/minestom/server/entity/Entity.java | 3 +- .../minestom/server/entity/LivingEntity.java | 5 +-- .../network/packet/server/LazyPacket.java | 34 +++++++++++++++++++ .../network/packet/server/SendablePacket.java | 4 ++- .../player/PlayerSocketConnection.java | 2 ++ 5 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 src/main/java/net/minestom/server/network/packet/server/LazyPacket.java diff --git a/src/main/java/net/minestom/server/entity/Entity.java b/src/main/java/net/minestom/server/entity/Entity.java index 4cd2e2ecb..73c4c9859 100644 --- a/src/main/java/net/minestom/server/entity/Entity.java +++ b/src/main/java/net/minestom/server/entity/Entity.java @@ -27,6 +27,7 @@ import net.minestom.server.instance.InstanceManager; import net.minestom.server.instance.block.Block; import net.minestom.server.instance.block.BlockHandler; import net.minestom.server.network.packet.server.CachedPacket; +import net.minestom.server.network.packet.server.LazyPacket; import net.minestom.server.network.packet.server.ServerPacket; import net.minestom.server.network.packet.server.play.*; import net.minestom.server.permission.Permission; @@ -431,7 +432,7 @@ public class Entity implements Viewable, Tickable, Schedulable, TagHandler, Perm public void updateNewViewer(@NotNull Player player) { player.sendPacket(getEntityType().registry().spawnType().getSpawnPacket(this)); if (hasVelocity()) player.sendPacket(getVelocityPacket()); - player.sendPacket(getMetadataPacket()); + player.sendPacket(new LazyPacket(this::getMetadataPacket)); // Passengers final Set passengers = this.passengers; if (!passengers.isEmpty()) { diff --git a/src/main/java/net/minestom/server/entity/LivingEntity.java b/src/main/java/net/minestom/server/entity/LivingEntity.java index 48ebbf9ad..71022cd3b 100644 --- a/src/main/java/net/minestom/server/entity/LivingEntity.java +++ b/src/main/java/net/minestom/server/entity/LivingEntity.java @@ -19,6 +19,7 @@ import net.minestom.server.instance.EntityTracker; import net.minestom.server.inventory.EquipmentHandler; import net.minestom.server.item.ItemStack; import net.minestom.server.network.ConnectionState; +import net.minestom.server.network.packet.server.LazyPacket; import net.minestom.server.network.packet.server.play.CollectItemPacket; import net.minestom.server.network.packet.server.play.EntityAnimationPacket; import net.minestom.server.network.packet.server.play.EntityPropertiesPacket; @@ -514,8 +515,8 @@ public class LivingEntity extends Entity implements EquipmentHandler { @Override public void updateNewViewer(@NotNull Player player) { super.updateNewViewer(player); - player.sendPacket(getEquipmentsPacket()); - player.sendPacket(getPropertiesPacket()); + player.sendPacket(new LazyPacket(this::getEquipmentsPacket)); + player.sendPacket(new LazyPacket(this::getPropertiesPacket)); if (getTeam() != null) player.sendPacket(getTeam().createTeamsCreationPacket()); } diff --git a/src/main/java/net/minestom/server/network/packet/server/LazyPacket.java b/src/main/java/net/minestom/server/network/packet/server/LazyPacket.java new file mode 100644 index 000000000..4f924bda7 --- /dev/null +++ b/src/main/java/net/minestom/server/network/packet/server/LazyPacket.java @@ -0,0 +1,34 @@ +package net.minestom.server.network.packet.server; + +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; + +import java.util.function.Supplier; + +/** + * Represents a packet that is lazily allocated. Potentially in a different thread. + *

+ * Supplier must be thread-safe. + */ +@ApiStatus.Internal +public final class LazyPacket implements SendablePacket { + private final Supplier packetSupplier; + private volatile ServerPacket packet; + + public LazyPacket(@NotNull Supplier<@NotNull ServerPacket> packetSupplier) { + this.packetSupplier = packetSupplier; + } + + public @NotNull ServerPacket packet() { + ServerPacket packet = this.packet; + if (packet == null) { + synchronized (this) { + packet = this.packet; + if (packet == null) { + packet = this.packet = packetSupplier.get(); + } + } + } + return packet; + } +} diff --git a/src/main/java/net/minestom/server/network/packet/server/SendablePacket.java b/src/main/java/net/minestom/server/network/packet/server/SendablePacket.java index 6dbcefae4..f69d01f11 100644 --- a/src/main/java/net/minestom/server/network/packet/server/SendablePacket.java +++ b/src/main/java/net/minestom/server/network/packet/server/SendablePacket.java @@ -9,7 +9,7 @@ import org.jetbrains.annotations.NotNull; */ @ApiStatus.Experimental public sealed interface SendablePacket - permits ServerPacket, CachedPacket, FramedPacket { + permits CachedPacket, FramedPacket, LazyPacket, ServerPacket { @ApiStatus.Experimental static @NotNull ServerPacket extractServerPacket(@NotNull SendablePacket packet) { @@ -19,6 +19,8 @@ public sealed interface SendablePacket return cachedPacket.packet(); } else if (packet instanceof FramedPacket framedPacket) { return framedPacket.packet(); + } else if (packet instanceof LazyPacket lazyPacket) { + return lazyPacket.packet(); } else { throw new RuntimeException("Unknown packet type: " + packet.getClass().getName()); } diff --git a/src/main/java/net/minestom/server/network/player/PlayerSocketConnection.java b/src/main/java/net/minestom/server/network/player/PlayerSocketConnection.java index 352eca8f2..ff1e9e79a 100644 --- a/src/main/java/net/minestom/server/network/player/PlayerSocketConnection.java +++ b/src/main/java/net/minestom/server/network/player/PlayerSocketConnection.java @@ -357,6 +357,8 @@ public class PlayerSocketConnection extends PlayerConnection { writeFramedPacketSync(framedPacket); } else if (packet instanceof CachedPacket cachedPacket) { writeBufferSync(cachedPacket.body()); + } else if (packet instanceof LazyPacket lazyPacket) { + writeServerPacketSync(lazyPacket.packet(), compressed); } else { throw new RuntimeException("Unknown packet type: " + packet.getClass().getName()); }