diff --git a/src/main/java/net/minestom/server/MinecraftServer.java b/src/main/java/net/minestom/server/MinecraftServer.java index c4b33591e..4e116ca9e 100644 --- a/src/main/java/net/minestom/server/MinecraftServer.java +++ b/src/main/java/net/minestom/server/MinecraftServer.java @@ -31,7 +31,6 @@ import net.minestom.server.item.Material; import net.minestom.server.listener.manager.PacketListenerManager; import net.minestom.server.network.ConnectionManager; import net.minestom.server.network.PacketProcessor; -import net.minestom.server.network.PacketWriterUtils; import net.minestom.server.network.netty.NettyServer; import net.minestom.server.network.packet.server.play.PluginMessagePacket; import net.minestom.server.network.packet.server.play.ServerDifficultyPacket; @@ -49,6 +48,7 @@ import net.minestom.server.storage.StorageLocation; import net.minestom.server.storage.StorageManager; import net.minestom.server.timer.SchedulerManager; import net.minestom.server.utils.MathUtils; +import net.minestom.server.utils.PacketUtils; import net.minestom.server.utils.thread.MinestomThread; import net.minestom.server.utils.validate.Check; import net.minestom.server.world.Difficulty; @@ -242,8 +242,7 @@ public final class MinecraftServer { Check.notNull(brandName, "The brand name cannot be null"); MinecraftServer.brandName = brandName; - PluginMessagePacket brandMessage = PluginMessagePacket.getBrandPacket(); - PacketWriterUtils.writeAndSend(connectionManager.getOnlinePlayers(), brandMessage); + PacketUtils.sendGroupedPacket(connectionManager.getOnlinePlayers(), PluginMessagePacket.getBrandPacket()); } /** @@ -301,12 +300,11 @@ public final class MinecraftServer { Check.notNull(difficulty, "The server difficulty cannot be null."); MinecraftServer.difficulty = difficulty; - // The difficulty packet + // Send the packet to all online players ServerDifficultyPacket serverDifficultyPacket = new ServerDifficultyPacket(); serverDifficultyPacket.difficulty = difficulty; serverDifficultyPacket.locked = true; // Can only be modified on single-player - // Send the packet to all online players - PacketWriterUtils.writeAndSend(connectionManager.getOnlinePlayers(), serverDifficultyPacket); + PacketUtils.sendGroupedPacket(connectionManager.getOnlinePlayers(), serverDifficultyPacket); } /** @@ -468,14 +466,16 @@ public final class MinecraftServer { "The chunk view distance must be between 2 and 32"); MinecraftServer.chunkViewDistance = chunkViewDistance; if (started) { - UpdateViewDistancePacket updateViewDistancePacket = new UpdateViewDistancePacket(); - updateViewDistancePacket.viewDistance = chunkViewDistance; final Collection players = connectionManager.getOnlinePlayers(); - PacketWriterUtils.writeAndSend(players, updateViewDistancePacket); + UpdateViewDistancePacket updateViewDistancePacket = new UpdateViewDistancePacket(); + updateViewDistancePacket.viewDistance = chunkViewDistance; - connectionManager.getOnlinePlayers().forEach(player -> { + // Send packet to all online players + PacketUtils.sendGroupedPacket(players, updateViewDistancePacket); + + players.forEach(player -> { final Chunk playerChunk = player.getChunk(); if (playerChunk != null) { player.refreshVisibleChunks(playerChunk); diff --git a/src/main/java/net/minestom/server/UpdateManager.java b/src/main/java/net/minestom/server/UpdateManager.java index 08e7e1237..b68cb4e13 100644 --- a/src/main/java/net/minestom/server/UpdateManager.java +++ b/src/main/java/net/minestom/server/UpdateManager.java @@ -71,10 +71,10 @@ public final class UpdateManager { final long tickTime = System.nanoTime() - currentTime; // Tick end callbacks - doTickCallback(tickEndCallbacks, tickTime / 1000000); + doTickCallback(tickEndCallbacks, tickTime / 1000000L); // Sleep until next tick - final long sleepTime = Math.max(1, (tickDistance - tickTime) / 1000000); + final long sleepTime = Math.max(1, (tickDistance - tickTime) / 1000000L); try { Thread.sleep(sleepTime); diff --git a/src/main/java/net/minestom/server/Viewable.java b/src/main/java/net/minestom/server/Viewable.java index 467dd019f..b615a6892 100644 --- a/src/main/java/net/minestom/server/Viewable.java +++ b/src/main/java/net/minestom/server/Viewable.java @@ -1,11 +1,10 @@ package net.minestom.server; import net.minestom.server.entity.Player; -import net.minestom.server.network.PacketWriterUtils; import net.minestom.server.network.packet.server.ServerPacket; +import net.minestom.server.utils.PacketUtils; import org.jetbrains.annotations.NotNull; -import java.util.HashSet; import java.util.Set; /** @@ -56,7 +55,7 @@ public interface Viewable { * @param packet the packet to send to all viewers */ default void sendPacketToViewers(@NotNull ServerPacket packet) { - PacketWriterUtils.writeAndSend(getViewers(), packet); + PacketUtils.sendGroupedPacket(getViewers(), packet); } /** @@ -69,40 +68,22 @@ public interface Viewable { */ default void sendPacketsToViewers(@NotNull ServerPacket... packets) { for (ServerPacket packet : packets) { - PacketWriterUtils.writeAndSend(getViewers(), packet); + PacketUtils.sendGroupedPacket(getViewers(), packet); } } /** * Sends a packet to all viewers and the viewable element if it is a player. *

- * If 'this' isn't a player, then {@link #sendPacketToViewers(ServerPacket)} is called instead. + * If 'this' isn't a player, then {only @link #sendPacketToViewers(ServerPacket)} is called. * * @param packet the packet to send */ default void sendPacketToViewersAndSelf(@NotNull ServerPacket packet) { if (this instanceof Player) { - if (getViewers().isEmpty()) { - PacketWriterUtils.writeAndSend((Player) this, packet); - } else { - UNSAFE_sendPacketToViewersAndSelf(packet); - } - } else { - sendPacketToViewers(packet); + ((Player) this).getPlayerConnection().sendPacket(packet); } - } - - /** - * Sends a packet to all the viewers and 'this'. - *

- * Unsafe because of a cast to {@link Player} without any check beforehand. - * - * @param packet the packet to send - */ - private void UNSAFE_sendPacketToViewersAndSelf(@NotNull ServerPacket packet) { - Set recipients = new HashSet<>(getViewers()); - recipients.add((Player) this); - PacketWriterUtils.writeAndSend(recipients, packet); + sendPacketToViewers(packet); } } diff --git a/src/main/java/net/minestom/server/advancements/Advancement.java b/src/main/java/net/minestom/server/advancements/Advancement.java index 9b169cd6a..150ab31ea 100644 --- a/src/main/java/net/minestom/server/advancements/Advancement.java +++ b/src/main/java/net/minestom/server/advancements/Advancement.java @@ -1,15 +1,16 @@ package net.minestom.server.advancements; -import io.netty.buffer.ByteBuf; import net.minestom.server.chat.ColoredText; +import net.minestom.server.entity.Player; import net.minestom.server.item.ItemStack; import net.minestom.server.item.Material; import net.minestom.server.network.packet.server.play.AdvancementsPacket; -import net.minestom.server.network.player.PlayerConnection; +import net.minestom.server.utils.PacketUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Date; +import java.util.Set; /** * Represents an advancement located in an {@link AdvancementTab}. @@ -373,17 +374,11 @@ public class Advancement { updateCriteria(); if (tab != null) { - // Update the tab cached packet - tab.updatePacket(); + final Set viewers = tab.getViewers(); + AdvancementsPacket createPacket = tab.createPacket(); - final ByteBuf createBuffer = tab.createBuffer; - final ByteBuf removeBuffer = tab.removeBuffer; - tab.getViewers().forEach(player -> { - final PlayerConnection playerConnection = player.getPlayerConnection(); - // Receive order is important - playerConnection.sendPacket(removeBuffer, true); - playerConnection.sendPacket(createBuffer, true); - }); + PacketUtils.sendGroupedPacket(viewers, tab.removePacket); + PacketUtils.sendGroupedPacket(viewers, createPacket); } } diff --git a/src/main/java/net/minestom/server/advancements/AdvancementTab.java b/src/main/java/net/minestom/server/advancements/AdvancementTab.java index df25b1e25..3bc1241b2 100644 --- a/src/main/java/net/minestom/server/advancements/AdvancementTab.java +++ b/src/main/java/net/minestom/server/advancements/AdvancementTab.java @@ -1,11 +1,9 @@ package net.minestom.server.advancements; -import io.netty.buffer.ByteBuf; import net.minestom.server.Viewable; import net.minestom.server.entity.Player; import net.minestom.server.network.packet.server.play.AdvancementsPacket; import net.minestom.server.network.player.PlayerConnection; -import net.minestom.server.utils.PacketUtils; import net.minestom.server.utils.advancement.AdvancementUtils; import net.minestom.server.utils.validate.Check; import org.jetbrains.annotations.NotNull; @@ -33,19 +31,16 @@ public class AdvancementTab implements Viewable { // Advancement -> its parent private final Map advancementMap = new HashMap<>(); - // Packet cache, updated every time the tab changes - protected ByteBuf createBuffer; // the packet used to clear the tab (used to remove it and to update an advancement) // will never change (since the root identifier is always the same) - protected final ByteBuf removeBuffer; + protected final AdvancementsPacket removePacket; protected AdvancementTab(@NotNull String rootIdentifier, @NotNull AdvancementRoot root) { this.root = root; cacheAdvancement(rootIdentifier, root, null); - final AdvancementsPacket removePacket = AdvancementUtils.getRemovePacket(new String[]{rootIdentifier}); - this.removeBuffer = PacketUtils.writePacket(removePacket); + this.removePacket = AdvancementUtils.getRemovePacket(new String[]{rootIdentifier}); } /** @@ -88,13 +83,6 @@ public class AdvancementTab implements Viewable { } - /** - * Updates the packet buffer. - */ - protected void updatePacket() { - this.createBuffer = PacketUtils.writePacket(createPacket()); - } - /** * Builds the packet which build the whole advancement tab. * @@ -135,8 +123,6 @@ public class AdvancementTab implements Viewable { advancement.setParent(parent); advancement.updateCriteria(); this.advancementMap.put(advancement, parent); - - updatePacket(); } @Override @@ -149,7 +135,7 @@ public class AdvancementTab implements Viewable { final PlayerConnection playerConnection = player.getPlayerConnection(); // Send the tab to the player - playerConnection.sendPacket(createBuffer, true); + playerConnection.sendPacket(createPacket()); addPlayer(player); @@ -166,7 +152,7 @@ public class AdvancementTab implements Viewable { // Remove the tab if (!player.isRemoved()) { - playerConnection.sendPacket(removeBuffer, true); + playerConnection.sendPacket(removePacket); } removePlayer(player); diff --git a/src/main/java/net/minestom/server/entity/Player.java b/src/main/java/net/minestom/server/entity/Player.java index 4a6d4b9c2..3edfdfd37 100644 --- a/src/main/java/net/minestom/server/entity/Player.java +++ b/src/main/java/net/minestom/server/entity/Player.java @@ -291,9 +291,6 @@ public class Player extends LivingEntity implements CommandSender { @Override public void update(long time) { - // Flush all pending packets - playerConnection.flush(); - playerConnection.updateStats(); // Process received packets @@ -1687,7 +1684,7 @@ public class Player extends LivingEntity implements CommandSender { public void setTeam(Team team) { super.setTeam(team); if (team != null) - getPlayerConnection().sendPacket(team.getTeamsCreationPacket()); + getPlayerConnection().sendPacket(team.createTeamsCreationPacket()); } /** @@ -2338,7 +2335,7 @@ public class Player extends LivingEntity implements CommandSender { // Team if (this.getTeam() != null) - connection.sendPacket(this.getTeam().getTeamsCreationPacket()); + connection.sendPacket(this.getTeam().createTeamsCreationPacket()); EntityHeadLookPacket entityHeadLookPacket = new EntityHeadLookPacket(); entityHeadLookPacket.entityId = getEntityId(); diff --git a/src/main/java/net/minestom/server/instance/Chunk.java b/src/main/java/net/minestom/server/instance/Chunk.java index b58097042..623e096f1 100644 --- a/src/main/java/net/minestom/server/instance/Chunk.java +++ b/src/main/java/net/minestom/server/instance/Chunk.java @@ -13,7 +13,6 @@ import net.minestom.server.instance.batch.ChunkBatch; import net.minestom.server.instance.block.Block; import net.minestom.server.instance.block.BlockManager; import net.minestom.server.instance.block.CustomBlock; -import net.minestom.server.network.PacketWriterUtils; import net.minestom.server.network.packet.server.play.ChunkDataPacket; import net.minestom.server.network.packet.server.play.UpdateLightPacket; import net.minestom.server.network.player.PlayerConnection; @@ -464,7 +463,8 @@ public abstract class Chunk implements Viewable, DataContainer { } updateLightPacket.skyLight = temp; updateLightPacket.blockLight = temp2; - PacketWriterUtils.writeAndSend(player, updateLightPacket); + + playerConnection.sendPacket(updateLightPacket); } } @@ -496,6 +496,7 @@ public abstract class Chunk implements Viewable, DataContainer { * * @param section the section to update * @param player the player to send the packet to + * @throws IllegalArgumentException if {@code section} is not a valid section */ public void sendChunkSectionUpdate(int section, @NotNull Player player) { if (!PlayerUtils.isNettyClient(player)) @@ -503,7 +504,7 @@ public abstract class Chunk implements Viewable, DataContainer { Check.argCondition(!MathUtils.isBetween(section, 0, CHUNK_SECTION_COUNT), "The chunk section " + section + " does not exist"); - PacketWriterUtils.writeAndSend(player, getChunkSectionUpdatePacket(section)); + player.getPlayerConnection().sendPacket(createChunkSectionUpdatePacket(section)); } /** @@ -513,7 +514,7 @@ public abstract class Chunk implements Viewable, DataContainer { * @return the {@link ChunkDataPacket} to update a single chunk section */ @NotNull - protected ChunkDataPacket getChunkSectionUpdatePacket(int section) { + protected ChunkDataPacket createChunkSectionUpdatePacket(int section) { ChunkDataPacket chunkDataPacket = getFreshPartialDataPacket(); chunkDataPacket.fullChunk = false; int[] sections = new int[CHUNK_SECTION_COUNT]; diff --git a/src/main/java/net/minestom/server/instance/Explosion.java b/src/main/java/net/minestom/server/instance/Explosion.java index b10da5581..5e57a13d1 100644 --- a/src/main/java/net/minestom/server/instance/Explosion.java +++ b/src/main/java/net/minestom/server/instance/Explosion.java @@ -1,9 +1,10 @@ package net.minestom.server.instance; import net.minestom.server.instance.block.Block; -import net.minestom.server.network.PacketWriterUtils; import net.minestom.server.network.packet.server.play.ExplosionPacket; import net.minestom.server.utils.BlockPosition; +import net.minestom.server.utils.PacketUtils; +import org.jetbrains.annotations.NotNull; import java.util.List; @@ -54,7 +55,7 @@ public abstract class Explosion { * * @param instance instance to perform this explosion in */ - public void apply(Instance instance) { + public void apply(@NotNull Instance instance) { List blocks = prepare(instance); ExplosionPacket packet = new ExplosionPacket(); packet.x = getCenterX(); @@ -80,7 +81,7 @@ public abstract class Explosion { postExplosion(instance, blocks, packet); // TODO send only to close players - PacketWriterUtils.writeAndSend(instance.getPlayers(), packet); + PacketUtils.sendGroupedPacket(instance.getPlayers(), packet); postSend(instance, blocks); } diff --git a/src/main/java/net/minestom/server/instance/Instance.java b/src/main/java/net/minestom/server/instance/Instance.java index 8b22da131..a454318eb 100644 --- a/src/main/java/net/minestom/server/instance/Instance.java +++ b/src/main/java/net/minestom/server/instance/Instance.java @@ -16,12 +16,12 @@ import net.minestom.server.instance.batch.ChunkBatch; import net.minestom.server.instance.block.Block; import net.minestom.server.instance.block.BlockManager; import net.minestom.server.instance.block.CustomBlock; -import net.minestom.server.network.PacketWriterUtils; import net.minestom.server.network.packet.server.play.BlockActionPacket; import net.minestom.server.network.packet.server.play.TimeUpdatePacket; import net.minestom.server.storage.StorageLocation; import net.minestom.server.thread.ThreadProvider; import net.minestom.server.utils.BlockPosition; +import net.minestom.server.utils.PacketUtils; import net.minestom.server.utils.Position; import net.minestom.server.utils.chunk.ChunkCallback; import net.minestom.server.utils.chunk.ChunkUtils; @@ -369,7 +369,7 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta */ public void setTime(long time) { this.time = time; - PacketWriterUtils.writeAndSend(getPlayers(), getTimePacket()); + PacketUtils.sendGroupedPacket(getPlayers(), createTimePacket()); } /** @@ -417,12 +417,12 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta } /** - * Gets a {@link TimeUpdatePacket} with the current age and time of this instance + * Creates a {@link TimeUpdatePacket} with the current age and time of this instance * * @return the {@link TimeUpdatePacket} with this instance data */ @NotNull - private TimeUpdatePacket getTimePacket() { + private TimeUpdatePacket createTimePacket() { TimeUpdatePacket timeUpdatePacket = new TimeUpdatePacket(); timeUpdatePacket.worldAge = worldAge; timeUpdatePacket.timeOfDay = time; @@ -996,7 +996,7 @@ public abstract class Instance implements BlockModifier, EventHandler, DataConta // time needs to be send to players if (timeUpdate != null && !CooldownUtils.hasCooldown(time, lastTimeUpdate, timeUpdate)) { - PacketWriterUtils.writeAndSend(getPlayers(), getTimePacket()); + PacketUtils.sendGroupedPacket(getPlayers(), createTimePacket()); this.lastTimeUpdate = time; } diff --git a/src/main/java/net/minestom/server/instance/WorldBorder.java b/src/main/java/net/minestom/server/instance/WorldBorder.java index 813eec4e4..aa1a99c0b 100644 --- a/src/main/java/net/minestom/server/instance/WorldBorder.java +++ b/src/main/java/net/minestom/server/instance/WorldBorder.java @@ -2,8 +2,8 @@ package net.minestom.server.instance; import net.minestom.server.entity.Entity; import net.minestom.server.entity.Player; -import net.minestom.server.network.PacketWriterUtils; import net.minestom.server.network.packet.server.play.WorldBorderPacket; +import net.minestom.server.utils.PacketUtils; import net.minestom.server.utils.Position; import org.jetbrains.annotations.NotNull; @@ -100,6 +100,7 @@ public class WorldBorder { */ public void setWarningTime(int warningTime) { this.warningTime = warningTime; + WorldBorderPacket worldBorderPacket = new WorldBorderPacket(); worldBorderPacket.action = WorldBorderPacket.Action.SET_WARNING_TIME; worldBorderPacket.wbAction = new WorldBorderPacket.WBSetWarningTime(warningTime); @@ -115,6 +116,7 @@ public class WorldBorder { */ public void setWarningBlocks(int warningBlocks) { this.warningBlocks = warningBlocks; + WorldBorderPacket worldBorderPacket = new WorldBorderPacket(); worldBorderPacket.action = WorldBorderPacket.Action.SET_WARNING_BLOCKS; worldBorderPacket.wbAction = new WorldBorderPacket.WBSetWarningBlocks(warningBlocks); @@ -137,6 +139,7 @@ public class WorldBorder { this.speed = speed; this.lerpStartTime = System.currentTimeMillis(); + WorldBorderPacket worldBorderPacket = new WorldBorderPacket(); worldBorderPacket.action = WorldBorderPacket.Action.LERP_SIZE; worldBorderPacket.wbAction = new WorldBorderPacket.WBLerpSize(oldDiameter, newDiameter, speed); @@ -270,10 +273,10 @@ public class WorldBorder { /** * Sends a {@link WorldBorderPacket} to all the instance players. * - * @param worldBorderPacket the packet to send + * @param packet the packet to send */ - private void sendPacket(@NotNull WorldBorderPacket worldBorderPacket) { - PacketWriterUtils.writeAndSend(instance.getPlayers(), worldBorderPacket); + private void sendPacket(@NotNull WorldBorderPacket packet) { + PacketUtils.sendGroupedPacket(instance.getPlayers(), packet); } public enum CollisionAxis { diff --git a/src/main/java/net/minestom/server/inventory/PlayerInventory.java b/src/main/java/net/minestom/server/inventory/PlayerInventory.java index b467d8eb0..683c6497c 100644 --- a/src/main/java/net/minestom/server/inventory/PlayerInventory.java +++ b/src/main/java/net/minestom/server/inventory/PlayerInventory.java @@ -13,7 +13,6 @@ import net.minestom.server.inventory.click.InventoryClickResult; import net.minestom.server.inventory.condition.InventoryCondition; import net.minestom.server.item.ItemStack; import net.minestom.server.item.StackingRule; -import net.minestom.server.network.PacketWriterUtils; import net.minestom.server.network.packet.server.play.EntityEquipmentPacket; import net.minestom.server.network.packet.server.play.SetSlotPacket; import net.minestom.server.network.packet.server.play.WindowItemsPacket; @@ -214,7 +213,7 @@ public class PlayerInventory implements InventoryModifier, InventoryClickHandler * the inventory items */ public void update() { - PacketWriterUtils.writeAndSend(player, createWindowItemsPacket()); + player.getPlayerConnection().sendPacket(createWindowItemsPacket()); } /** diff --git a/src/main/java/net/minestom/server/listener/ChatMessageListener.java b/src/main/java/net/minestom/server/listener/ChatMessageListener.java index 933d9fad3..395deda3f 100644 --- a/src/main/java/net/minestom/server/listener/ChatMessageListener.java +++ b/src/main/java/net/minestom/server/listener/ChatMessageListener.java @@ -9,9 +9,9 @@ import net.minestom.server.command.CommandManager; import net.minestom.server.entity.Player; import net.minestom.server.event.player.PlayerChatEvent; import net.minestom.server.network.ConnectionManager; -import net.minestom.server.network.PacketWriterUtils; import net.minestom.server.network.packet.client.play.ClientChatMessagePacket; import net.minestom.server.network.packet.server.play.ChatMessagePacket; +import net.minestom.server.utils.PacketUtils; import java.util.Collection; import java.util.function.Function; @@ -62,7 +62,7 @@ public class ChatMessageListener { ChatMessagePacket chatMessagePacket = new ChatMessagePacket(jsonMessage, ChatMessagePacket.Position.CHAT, player.getUuid()); - PacketWriterUtils.writeAndSend(recipients, chatMessagePacket); + PacketUtils.sendGroupedPacket(recipients, chatMessagePacket); } }); diff --git a/src/main/java/net/minestom/server/listener/manager/PacketConsumer.java b/src/main/java/net/minestom/server/listener/manager/PacketConsumer.java index 5d88111ae..689db0669 100644 --- a/src/main/java/net/minestom/server/listener/manager/PacketConsumer.java +++ b/src/main/java/net/minestom/server/listener/manager/PacketConsumer.java @@ -1,21 +1,24 @@ 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.ConnectionManager; import org.jetbrains.annotations.NotNull; /** - * Interface used to add a listener for incoming packets with {@link net.minestom.server.network.ConnectionManager#onPacketReceive(PacketConsumer)}. + * Interface used to add a listener for incoming/outgoing packets with + * {@link ConnectionManager#onPacketReceive(PacketConsumer)} and {@link ConnectionManager#onPacketSend(PacketConsumer)}. + * + * @param the packet type */ @FunctionalInterface -public interface PacketConsumer { +public interface PacketConsumer { /** - * Called when a packet is received from the client. + * Called when a packet is received/sent from/to a client. * - * @param player the player who sent the packet - * @param packetController the packet controller, used to cancel or control which listener will be called - * @param packet the received packet + * @param player the player concerned by the packet + * @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 T packet); } diff --git a/src/main/java/net/minestom/server/listener/manager/PacketController.java b/src/main/java/net/minestom/server/listener/manager/PacketController.java index 6c3c02a28..1716777f3 100644 --- a/src/main/java/net/minestom/server/listener/manager/PacketController.java +++ b/src/main/java/net/minestom/server/listener/manager/PacketController.java @@ -1,19 +1,15 @@ package net.minestom.server.listener.manager; import net.minestom.server.entity.Player; -import net.minestom.server.network.packet.client.ClientPlayPacket; -import org.jetbrains.annotations.Nullable; /** - * Used to control the output of a packet in {@link PacketConsumer#accept(Player, PacketController, ClientPlayPacket)}. + * Used to control the output of a packet in {@link PacketConsumer#accept(Player, PacketController, Object)}. */ public class PacketController { private boolean cancel; - private PacketListenerConsumer packetListenerConsumer; - protected PacketController(@Nullable PacketListenerConsumer packetListenerConsumer) { - this.packetListenerConsumer = packetListenerConsumer; + protected PacketController() { } /** @@ -33,25 +29,4 @@ public class PacketController { public void setCancel(boolean cancel) { this.cancel = cancel; } - - /** - * Gets the listener associated with the packet. - * - * @return the packet's listener, null if not present - */ - @Nullable - public PacketListenerConsumer getPacketListenerConsumer() { - return packetListenerConsumer; - } - - /** - * Changes the packet listener, setting it to null cancel the listener. - *

- * WARNING: this will overwrite the default minestom listener, be sure to know what you are doing. - * - * @param packetListenerConsumer the new packet listener, can be null - */ - public void setPacketListenerConsumer(@Nullable PacketListenerConsumer packetListenerConsumer) { - this.packetListenerConsumer = packetListenerConsumer; - } } diff --git a/src/main/java/net/minestom/server/listener/manager/PacketListenerManager.java b/src/main/java/net/minestom/server/listener/manager/PacketListenerManager.java index cb7eadfcd..40fe44110 100644 --- a/src/main/java/net/minestom/server/listener/manager/PacketListenerManager.java +++ b/src/main/java/net/minestom/server/listener/manager/PacketListenerManager.java @@ -6,13 +6,17 @@ 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.play.*; +import net.minestom.server.network.packet.server.ServerPacket; import org.jetbrains.annotations.NotNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; public final class PacketListenerManager { + public final static Logger LOGGER = LoggerFactory.getLogger(PacketListenerManager.class); private static final ConnectionManager CONNECTION_MANAGER = MinecraftServer.getConnectionManager(); private final Map, PacketListenerConsumer> listeners = new ConcurrentHashMap<>(); @@ -56,7 +60,7 @@ public final class PacketListenerManager { * @param player the player who sent the packet * @param the packet type */ - public void process(@NotNull T packet, @NotNull Player player) { + public void processClientPacket(@NotNull T packet, @NotNull Player player) { final Class clazz = packet.getClass(); @@ -64,26 +68,29 @@ public final class PacketListenerManager { // Listener can be null if none has been set before, call PacketConsumer anyway if (packetListenerConsumer == null) { - System.err.println("Packet " + clazz + " does not have any default listener! (The issue comes from Minestom)"); + LOGGER.error("Packet " + clazz + " does not have any default listener! (The issue comes from Minestom)"); + return; } - - final PacketController packetController = new PacketController(packetListenerConsumer); - for (PacketConsumer packetConsumer : CONNECTION_MANAGER.getReceivePacketConsumers()) { + final PacketController packetController = new PacketController(); + for (PacketConsumer packetConsumer : CONNECTION_MANAGER.getReceivePacketConsumers()) { packetConsumer.accept(player, packetController, packet); } if (packetController.isCancel()) return; - // Get the new listener (or the same) from the packet controller - packetListenerConsumer = packetController.getPacketListenerConsumer(); + // Finally execute the listener + packetListenerConsumer.accept(packet, player); + } - // Call the listener if not null - // (can be null because no listener is set, or because it has been changed by the controller) - if (packetListenerConsumer != null) { - packetListenerConsumer.accept(packet, player); + public boolean processServerPacket(@NotNull T packet, @NotNull Player player) { + final PacketController packetController = new PacketController(); + for (PacketConsumer packetConsumer : CONNECTION_MANAGER.getSendPacketConsumers()) { + packetConsumer.accept(player, packetController, packet); } + + return !packetController.isCancel(); } /** diff --git a/src/main/java/net/minestom/server/network/ConnectionManager.java b/src/main/java/net/minestom/server/network/ConnectionManager.java index e18558b01..2b970db88 100644 --- a/src/main/java/net/minestom/server/network/ConnectionManager.java +++ b/src/main/java/net/minestom/server/network/ConnectionManager.java @@ -4,10 +4,13 @@ import net.minestom.server.chat.JsonMessage; import net.minestom.server.entity.Player; import net.minestom.server.entity.fakeplayer.FakePlayer; import net.minestom.server.listener.manager.PacketConsumer; +import net.minestom.server.network.packet.client.ClientPlayPacket; import net.minestom.server.network.packet.client.login.LoginStartPacket; +import net.minestom.server.network.packet.server.ServerPacket; import net.minestom.server.network.packet.server.login.LoginSuccessPacket; import net.minestom.server.network.packet.server.play.ChatMessagePacket; import net.minestom.server.network.player.PlayerConnection; +import net.minestom.server.utils.PacketUtils; import net.minestom.server.utils.callback.validator.PlayerValidator; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -26,7 +29,9 @@ public final class ConnectionManager { private final Map connectionPlayerMap = Collections.synchronizedMap(new HashMap<>()); // All the consumers to call once a packet is received - private final List receivePacketConsumers = new CopyOnWriteArrayList<>(); + private final List> receivePacketConsumers = new CopyOnWriteArrayList<>(); + // All the consumers to call once a packet is sent + private final List> sendPacketConsumers = new CopyOnWriteArrayList<>(); // The uuid provider once a player login private UuidProvider uuidProvider; // The player provider to have your own Player implementation @@ -115,7 +120,8 @@ public final class ConnectionManager { private void broadcastJson(@NotNull String json, @NotNull Collection recipients) { ChatMessagePacket chatMessagePacket = new ChatMessagePacket(json, ChatMessagePacket.Position.SYSTEM_MESSAGE); - PacketWriterUtils.writeAndSend(recipients, chatMessagePacket); + + PacketUtils.sendGroupedPacket(recipients, chatMessagePacket); } private Collection getRecipients(@Nullable PlayerValidator condition) { @@ -142,7 +148,7 @@ public final class ConnectionManager { * @return an unmodifiable list of packet's consumers */ @NotNull - public List getReceivePacketConsumers() { + public List> getReceivePacketConsumers() { return Collections.unmodifiableList(receivePacketConsumers); } @@ -151,10 +157,29 @@ public final class ConnectionManager { * * @param packetConsumer the packet consumer */ - public void onPacketReceive(@NotNull PacketConsumer packetConsumer) { + public void onPacketReceive(@NotNull PacketConsumer packetConsumer) { this.receivePacketConsumers.add(packetConsumer); } + /** + * Gets all the listeners which are called for each packet sent. + * + * @return an unmodifiable list of packet's consumers + */ + @NotNull + public List> getSendPacketConsumers() { + return Collections.unmodifiableList(sendPacketConsumers); + } + + /** + * Adds a consumer to call once a packet is sent. + * + * @param packetConsumer the packet consumer + */ + public void onPacketSend(@NotNull PacketConsumer packetConsumer) { + this.sendPacketConsumers.add(packetConsumer); + } + /** * Changes how {@link UUID} are attributed to players. *

diff --git a/src/main/java/net/minestom/server/network/PacketWriterUtils.java b/src/main/java/net/minestom/server/network/PacketWriterUtils.java deleted file mode 100644 index f305ea761..000000000 --- a/src/main/java/net/minestom/server/network/PacketWriterUtils.java +++ /dev/null @@ -1,101 +0,0 @@ -package net.minestom.server.network; - -import io.netty.buffer.ByteBuf; -import net.minestom.server.MinecraftServer; -import net.minestom.server.entity.Player; -import net.minestom.server.network.packet.server.ServerPacket; -import net.minestom.server.network.player.PlayerConnection; -import net.minestom.server.utils.PacketUtils; -import net.minestom.server.utils.player.PlayerUtils; -import net.minestom.server.utils.thread.MinestomThread; -import org.jetbrains.annotations.NotNull; - -import java.util.Collection; -import java.util.concurrent.ExecutorService; -import java.util.function.Consumer; - -/** - * Utils class used to write {@link ServerPacket} in the appropriate thread pool. - *

- * WARNING: those methods do not guarantee a receive order. - */ -public final class PacketWriterUtils { - - private static final ExecutorService PACKET_WRITER_POOL = new MinestomThread(MinecraftServer.THREAD_COUNT_PACKET_WRITER, MinecraftServer.THREAD_NAME_PACKET_WRITER); - - /** - * Writes the {@link ServerPacket} in the writer thread pool. - *

- * WARNING: should not be used if the packet receive order is important - * - * @param serverPacket the packet to write - * @param consumer the consumer called once the packet has been written - */ - public static void writeCallbackPacket(@NotNull ServerPacket serverPacket, @NotNull Consumer consumer) { - PACKET_WRITER_POOL.execute(() -> { - final ByteBuf buffer = PacketUtils.writePacket(serverPacket); - consumer.accept(buffer); - }); - } - - /** - * Writes a {@link ServerPacket} in the writer thread pool and send it to every players in {@code players}. - *

- * WARNING: should not be used if the packet receive order is important - * - * @param players the players list to send the packet to - * @param serverPacket the packet to write and send - */ - public static void writeAndSend(@NotNull Collection players, @NotNull ServerPacket serverPacket) { - PACKET_WRITER_POOL.execute(() -> { - if (players.isEmpty()) - return; - - final ByteBuf buffer = PacketUtils.writePacket(serverPacket); - for (Player player : players) { - final PlayerConnection playerConnection = player.getPlayerConnection(); - if (PlayerUtils.isNettyClient(player)) { - playerConnection.writePacket(buffer, true); - } else { - playerConnection.sendPacket(serverPacket); - } - } - buffer.release(); - }); - } - - /** - * Writes a {@link ServerPacket} and send it to a {@link PlayerConnection}. - *

- * WARNING: should not be used if the packet receive order is important - * - * @param playerConnection the connection to send the packet to - * @param serverPacket the packet to write and send - */ - public static void writeAndSend(@NotNull PlayerConnection playerConnection, @NotNull ServerPacket serverPacket) { - PACKET_WRITER_POOL.execute(() -> { - if (PlayerUtils.isNettyClient(playerConnection)) { - final ByteBuf buffer = PacketUtils.writePacket(serverPacket); - buffer.retain(); - playerConnection.writePacket(buffer, false); - buffer.release(); - } else { - playerConnection.sendPacket(serverPacket); - } - }); - } - - /** - * Writes a {@link ServerPacket} and send it to a {@link Player}. - *

- * WARNING: should not be used if the packet receive order is important - * - * @param player the player to send the packet to - * @param serverPacket the packet to write and send - */ - public static void writeAndSend(@NotNull Player player, @NotNull ServerPacket serverPacket) { - final PlayerConnection playerConnection = player.getPlayerConnection(); - writeAndSend(playerConnection, serverPacket); - } - -} diff --git a/src/main/java/net/minestom/server/network/packet/client/ClientPlayPacket.java b/src/main/java/net/minestom/server/network/packet/client/ClientPlayPacket.java index f23360efc..75d045ac0 100644 --- a/src/main/java/net/minestom/server/network/packet/client/ClientPlayPacket.java +++ b/src/main/java/net/minestom/server/network/packet/client/ClientPlayPacket.java @@ -17,7 +17,7 @@ public abstract class ClientPlayPacket implements ClientPacket { * @param player the player who sent the packet */ public void process(@NotNull Player player) { - PACKET_LISTENER_MANAGER.process(this, player); + PACKET_LISTENER_MANAGER.processClientPacket(this, player); } } diff --git a/src/main/java/net/minestom/server/network/packet/server/play/PluginMessagePacket.java b/src/main/java/net/minestom/server/network/packet/server/play/PluginMessagePacket.java index 4b41e7dfb..da702096a 100644 --- a/src/main/java/net/minestom/server/network/packet/server/play/PluginMessagePacket.java +++ b/src/main/java/net/minestom/server/network/packet/server/play/PluginMessagePacket.java @@ -34,8 +34,9 @@ public class PluginMessagePacket implements ServerPacket { PluginMessagePacket brandMessage = new PluginMessagePacket(); brandMessage.channel = "minecraft:brand"; - BinaryWriter writer = new BinaryWriter(); - writer.writeSizedString(MinecraftServer.getBrandName()); + final String brandName = MinecraftServer.getBrandName(); + BinaryWriter writer = new BinaryWriter(4 + brandName.length()); + writer.writeSizedString(brandName); brandMessage.data = writer.toByteArray(); diff --git a/src/main/java/net/minestom/server/network/packet/server/play/TeamsPacket.java b/src/main/java/net/minestom/server/network/packet/server/play/TeamsPacket.java index 9b3189cb3..4ab69c9ea 100644 --- a/src/main/java/net/minestom/server/network/packet/server/play/TeamsPacket.java +++ b/src/main/java/net/minestom/server/network/packet/server/play/TeamsPacket.java @@ -1,5 +1,6 @@ package net.minestom.server.network.packet.server.play; +import net.minestom.server.chat.JsonMessage; import net.minestom.server.network.packet.server.ServerPacket; import net.minestom.server.network.packet.server.ServerPacketIdentifier; import net.minestom.server.utils.binary.BinaryWriter; @@ -22,7 +23,7 @@ public class TeamsPacket implements ServerPacket { /** * The display name for the team */ - public String teamDisplayName; + public JsonMessage teamDisplayName; /** * The friendly flags to */ @@ -42,11 +43,11 @@ public class TeamsPacket implements ServerPacket { /** * The prefix of the team */ - public String teamPrefix; + public JsonMessage teamPrefix; /** * The suffix of the team */ - public String teamSuffix; + public JsonMessage teamSuffix; /** * An array with all entities in the team */ @@ -65,13 +66,13 @@ public class TeamsPacket implements ServerPacket { switch (action) { case CREATE_TEAM: case UPDATE_TEAM_INFO: - writer.writeSizedString(this.teamDisplayName); + writer.writeSizedString(this.teamDisplayName.toString()); writer.writeByte(this.friendlyFlags); writer.writeSizedString(this.nameTagVisibility.getIdentifier()); writer.writeSizedString(this.collisionRule.getIdentifier()); writer.writeVarInt(this.teamColor); - writer.writeSizedString(this.teamPrefix); - writer.writeSizedString(this.teamSuffix); + writer.writeSizedString(this.teamPrefix.toString()); + writer.writeSizedString(this.teamSuffix.toString()); break; case REMOVE_TEAM: diff --git a/src/main/java/net/minestom/server/network/player/FakePlayerConnection.java b/src/main/java/net/minestom/server/network/player/FakePlayerConnection.java index 14a2cd7f5..74a4a4a55 100644 --- a/src/main/java/net/minestom/server/network/player/FakePlayerConnection.java +++ b/src/main/java/net/minestom/server/network/player/FakePlayerConnection.java @@ -1,6 +1,5 @@ package net.minestom.server.network.player; -import io.netty.buffer.ByteBuf; import net.minestom.server.MinecraftServer; import net.minestom.server.entity.Player; import net.minestom.server.entity.fakeplayer.FakePlayer; @@ -13,24 +12,11 @@ import java.net.SocketAddress; public class FakePlayerConnection extends PlayerConnection { - @Override - public void sendPacket(@NotNull ByteBuf buffer, boolean copy) { - throw new UnsupportedOperationException("FakePlayer cannot read Bytebuf"); - } - - @Override - public void writePacket(@NotNull ByteBuf buffer, boolean copy) { - throw new UnsupportedOperationException("FakePlayer cannot write to Bytebuf"); - } - @Override public void sendPacket(@NotNull ServerPacket serverPacket) { - getFakePlayer().getController().consumePacket(serverPacket); - } - - @Override - public void flush() { - // Does nothing + if (shouldSendPacket(serverPacket)) { + getFakePlayer().getController().consumePacket(serverPacket); + } } @NotNull diff --git a/src/main/java/net/minestom/server/network/player/NettyPlayerConnection.java b/src/main/java/net/minestom/server/network/player/NettyPlayerConnection.java index cebb7fbab..3848b5c45 100644 --- a/src/main/java/net/minestom/server/network/player/NettyPlayerConnection.java +++ b/src/main/java/net/minestom/server/network/player/NettyPlayerConnection.java @@ -1,6 +1,5 @@ package net.minestom.server.network.player; -import io.netty.buffer.ByteBuf; import io.netty.channel.Channel; import io.netty.channel.socket.SocketChannel; import lombok.Getter; @@ -81,38 +80,11 @@ public class NettyPlayerConnection extends PlayerConnection { channel.pipeline().addAfter("framer", "compressor", new PacketCompressor(threshold)); } - @Override - public void sendPacket(@NotNull ByteBuf buffer, boolean copy) { - if (copy) { - buffer = buffer.copy(); - buffer.retain(); - channel.writeAndFlush(buffer); - buffer.release(); - } else { - channel.writeAndFlush(buffer); - } - } - - @Override - public void writePacket(@NotNull ByteBuf buffer, boolean copy) { - if (copy) { - buffer = buffer.copy(); - buffer.retain(); - channel.write(buffer); - buffer.release(); - } else { - channel.write(buffer); - } - } - @Override public void sendPacket(@NotNull ServerPacket serverPacket) { - channel.writeAndFlush(serverPacket); - } - - @Override - public void flush() { - getChannel().flush(); + if (shouldSendPacket(serverPacket)) { + channel.writeAndFlush(serverPacket); + } } @NotNull diff --git a/src/main/java/net/minestom/server/network/player/PlayerConnection.java b/src/main/java/net/minestom/server/network/player/PlayerConnection.java index 6a9c41acb..2c4b3717d 100644 --- a/src/main/java/net/minestom/server/network/player/PlayerConnection.java +++ b/src/main/java/net/minestom/server/network/player/PlayerConnection.java @@ -1,16 +1,18 @@ package net.minestom.server.network.player; -import io.netty.buffer.ByteBuf; import lombok.Getter; import net.minestom.server.MinecraftServer; import net.minestom.server.chat.ChatColor; import net.minestom.server.chat.ColoredText; import net.minestom.server.entity.Player; +import net.minestom.server.listener.manager.PacketListenerManager; +import net.minestom.server.network.ConnectionManager; import net.minestom.server.network.ConnectionState; import net.minestom.server.network.packet.server.ServerPacket; import net.minestom.server.network.packet.server.login.LoginDisconnectPacket; import net.minestom.server.network.packet.server.play.DisconnectPacket; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.net.SocketAddress; import java.util.concurrent.atomic.AtomicInteger; @@ -21,6 +23,8 @@ import java.util.concurrent.atomic.AtomicInteger; */ public abstract class PlayerConnection { + protected static final PacketListenerManager PACKET_LISTENER_MANAGER = MinecraftServer.getPacketListenerManager(); + private Player player; private ConnectionState connectionState; private boolean online; @@ -68,33 +72,19 @@ public abstract class PlayerConnection { } } - /** - * Sends a raw {@link ByteBuf} to the client. - * - * @param buffer The buffer to send. - * @param copy Should be true unless your only using the ByteBuf once. - */ - public abstract void sendPacket(@NotNull ByteBuf buffer, boolean copy); - - /** - * Writes a raw {@link ByteBuf} to the client. - * - * @param buffer The buffer to send. - * @param copy Should be true unless your only using the ByteBuf once. - */ - public abstract void writePacket(@NotNull ByteBuf buffer, boolean copy); - /** * Serializes the packet and send it to the client. + *

+ * Also responsible for executing {@link ConnectionManager#getSendPacketConsumers()} consumers. * * @param serverPacket the packet to send + * @see #shouldSendPacket(ServerPacket) */ public abstract void sendPacket(@NotNull ServerPacket serverPacket); - /** - * Flush all waiting packets. - */ - public abstract void flush(); + protected boolean shouldSendPacket(@NotNull ServerPacket serverPacket) { + return player == null || PACKET_LISTENER_MANAGER.processServerPacket(serverPacket, player); + } /** * Gets the remote address of the client. @@ -112,8 +102,9 @@ public abstract class PlayerConnection { /** * Gets the player linked to this connection. * - * @return the player + * @return the player, can be null if not initialized yet */ + @Nullable public Player getPlayer() { return player; } diff --git a/src/main/java/net/minestom/server/scoreboard/Sidebar.java b/src/main/java/net/minestom/server/scoreboard/Sidebar.java index 22bba6dbb..c2575382b 100644 --- a/src/main/java/net/minestom/server/scoreboard/Sidebar.java +++ b/src/main/java/net/minestom/server/scoreboard/Sidebar.java @@ -401,13 +401,13 @@ public class Sidebar implements Scoreboard { TeamsPacket teamsPacket = new TeamsPacket(); teamsPacket.teamName = teamName; teamsPacket.action = TeamsPacket.Action.CREATE_TEAM; - teamsPacket.teamDisplayName = teamDisplayName.toString(); + teamsPacket.teamDisplayName = teamDisplayName; teamsPacket.friendlyFlags = friendlyFlags; teamsPacket.nameTagVisibility = nameTagVisibility; teamsPacket.collisionRule = collisionRule; teamsPacket.teamColor = teamColor; - teamsPacket.teamPrefix = prefix.toString(); - teamsPacket.teamSuffix = suffix.toString(); + teamsPacket.teamPrefix = prefix; + teamsPacket.teamSuffix = suffix; teamsPacket.entities = new String[]{entityName}; return teamsPacket; } @@ -434,13 +434,13 @@ public class Sidebar implements Scoreboard { TeamsPacket teamsPacket = new TeamsPacket(); teamsPacket.teamName = teamName; teamsPacket.action = TeamsPacket.Action.UPDATE_TEAM_INFO; - teamsPacket.teamDisplayName = teamDisplayName.toString(); + teamsPacket.teamDisplayName = teamDisplayName; teamsPacket.friendlyFlags = friendlyFlags; teamsPacket.nameTagVisibility = nameTagVisibility; teamsPacket.collisionRule = collisionRule; teamsPacket.teamColor = teamColor; - teamsPacket.teamPrefix = prefix.toString(); - teamsPacket.teamSuffix = suffix.toString(); + teamsPacket.teamPrefix = prefix; + teamsPacket.teamSuffix = suffix; return teamsPacket; } diff --git a/src/main/java/net/minestom/server/scoreboard/Team.java b/src/main/java/net/minestom/server/scoreboard/Team.java index 809dd2e70..1d63bbf90 100644 --- a/src/main/java/net/minestom/server/scoreboard/Team.java +++ b/src/main/java/net/minestom/server/scoreboard/Team.java @@ -1,12 +1,11 @@ package net.minestom.server.scoreboard; -import io.netty.buffer.ByteBuf; import net.minestom.server.MinecraftServer; import net.minestom.server.chat.ChatColor; import net.minestom.server.chat.ColoredText; import net.minestom.server.entity.LivingEntity; import net.minestom.server.entity.Player; -import net.minestom.server.network.PacketWriterUtils; +import net.minestom.server.network.ConnectionManager; import net.minestom.server.network.packet.server.play.TeamsPacket; import net.minestom.server.network.packet.server.play.TeamsPacket.CollisionRule; import net.minestom.server.network.packet.server.play.TeamsPacket.NameTagVisibility; @@ -21,18 +20,12 @@ import java.util.concurrent.CopyOnWriteArraySet; */ public class Team { + private static final ConnectionManager CONNECTION_MANAGER = MinecraftServer.getConnectionManager(); + /** * A collection of all registered entities who are on the team */ private final Set members; - /** - * Creation packet for the team to create - */ - private final TeamsPacket teamsCreationPacket; - /** - * A byte buf to destroy the team - */ - private final ByteBuf teamsDestroyPacket; /** * The registry name of the team @@ -94,22 +87,6 @@ public class Team { this.entities = new String[0]; this.members = new CopyOnWriteArraySet<>(); - - // Initializes creation packet - this.teamsCreationPacket = new TeamsPacket(); - this.teamsCreationPacket.teamName = teamName; - this.teamsCreationPacket.action = TeamsPacket.Action.CREATE_TEAM; - this.teamsCreationPacket.teamDisplayName = this.teamDisplayName.toString(); - this.teamsCreationPacket.friendlyFlags = this.friendlyFlags; - this.teamsCreationPacket.nameTagVisibility = this.nameTagVisibility; - this.teamsCreationPacket.collisionRule = this.collisionRule; - this.teamsCreationPacket.teamColor = this.teamColor.getId(); - this.teamsCreationPacket.teamPrefix = this.prefix.toString(); - this.teamsCreationPacket.teamSuffix = this.suffix.toString(); - this.teamsCreationPacket.entities = this.entities; - - // Directly write packet since it will not change - this.teamsDestroyPacket = PacketUtils.writePacket(this.createTeamDestructionPacket()); } /** @@ -124,7 +101,6 @@ public class Team { System.arraycopy(this.entities, 0, entitiesCache, 0, this.entities.length); entitiesCache[this.entities.length] = member; this.entities = entitiesCache; - this.teamsCreationPacket.entities = this.entities; // Adds a new member to the team this.members.add(member); @@ -134,8 +110,9 @@ public class Team { addPlayerPacket.teamName = this.teamName; addPlayerPacket.action = TeamsPacket.Action.ADD_PLAYERS_TEAM; addPlayerPacket.entities = new String[]{member}; + // Sends to all online players the add player packet - PacketWriterUtils.writeAndSend(MinecraftServer.getConnectionManager().getOnlinePlayers(), addPlayerPacket); + PacketUtils.sendGroupedPacket(CONNECTION_MANAGER.getOnlinePlayers(), addPlayerPacket); } /** @@ -150,7 +127,7 @@ public class Team { removePlayerPacket.action = TeamsPacket.Action.REMOVE_PLAYERS_TEAM; removePlayerPacket.entities = new String[]{member}; // Sends to all online player teh remove player packet - PacketWriterUtils.writeAndSend(MinecraftServer.getConnectionManager().getOnlinePlayers(), removePlayerPacket); + PacketUtils.sendGroupedPacket(CONNECTION_MANAGER.getOnlinePlayers(), removePlayerPacket); // Removes the player from the this.members.remove(member); @@ -161,7 +138,6 @@ public class Team { entitiesCache[count++] = teamMember; } this.entities = entitiesCache; - this.teamsCreationPacket.entities = this.entities; } /** @@ -173,7 +149,6 @@ public class Team { */ public void setTeamDisplayName(ColoredText teamDisplayName) { this.teamDisplayName = teamDisplayName; - this.teamsCreationPacket.teamDisplayName = teamDisplayName.toString(); } /** @@ -195,7 +170,6 @@ public class Team { */ public void setNameTagVisibility(NameTagVisibility visibility) { this.nameTagVisibility = visibility; - this.teamsCreationPacket.nameTagVisibility = visibility; } /** @@ -217,7 +191,6 @@ public class Team { */ public void setCollisionRule(CollisionRule rule) { this.collisionRule = rule; - this.teamsCreationPacket.collisionRule = rule; } /** @@ -239,7 +212,6 @@ public class Team { */ public void setTeamColor(ChatColor color) { this.teamColor = color; - this.teamsCreationPacket.teamColor = color.getId(); } /** @@ -261,7 +233,6 @@ public class Team { */ public void setPrefix(ColoredText prefix) { this.prefix = prefix; - this.teamsCreationPacket.teamPrefix = prefix.toString(); } /** @@ -283,7 +254,6 @@ public class Team { */ public void setSuffix(ColoredText suffix) { this.suffix = suffix; - this.teamsCreationPacket.teamSuffix = suffix.toString(); } /** @@ -305,7 +275,6 @@ public class Team { */ public void setFriendlyFlags(byte flag) { this.friendlyFlags = flag; - this.teamsCreationPacket.friendlyFlags = flag; } /** @@ -328,16 +297,24 @@ public class Team { } /** - * Gets the creation packet to add a team. + * Creates the creation packet to add a team. * * @return the packet to add the team */ - public TeamsPacket getTeamsCreationPacket() { - return teamsCreationPacket; - } + public TeamsPacket createTeamsCreationPacket() { + TeamsPacket teamsCreationPacket = new TeamsPacket(); + teamsCreationPacket.teamName = teamName; + teamsCreationPacket.action = TeamsPacket.Action.CREATE_TEAM; + teamsCreationPacket.teamDisplayName = this.teamDisplayName; + teamsCreationPacket.friendlyFlags = this.friendlyFlags; + teamsCreationPacket.nameTagVisibility = this.nameTagVisibility; + teamsCreationPacket.collisionRule = this.collisionRule; + teamsCreationPacket.teamColor = this.teamColor.getId(); + teamsCreationPacket.teamPrefix = this.prefix; + teamsCreationPacket.teamSuffix = this.suffix; + teamsCreationPacket.entities = this.entities; - public ByteBuf getTeamsDestroyPacket() { - return teamsDestroyPacket; + return teamsCreationPacket; } /** @@ -435,16 +412,14 @@ public class Team { final TeamsPacket updatePacket = new TeamsPacket(); updatePacket.teamName = this.teamName; updatePacket.action = TeamsPacket.Action.UPDATE_TEAM_INFO; - updatePacket.teamDisplayName = this.teamDisplayName.toString(); + updatePacket.teamDisplayName = this.teamDisplayName; updatePacket.friendlyFlags = this.friendlyFlags; updatePacket.nameTagVisibility = this.nameTagVisibility; updatePacket.collisionRule = this.collisionRule; updatePacket.teamColor = this.teamColor.getId(); - updatePacket.teamPrefix = this.prefix.toString(); - updatePacket.teamSuffix = this.suffix.toString(); - ByteBuf buffer = PacketUtils.writePacket(updatePacket); - for (Player onlinePlayer : MinecraftServer.getConnectionManager().getOnlinePlayers()) { - onlinePlayer.getPlayerConnection().sendPacket(buffer, true); - } + updatePacket.teamPrefix = this.prefix; + updatePacket.teamSuffix = this.suffix; + + PacketUtils.sendGroupedPacket(MinecraftServer.getConnectionManager().getOnlinePlayers(), updatePacket); } } diff --git a/src/main/java/net/minestom/server/scoreboard/TeamManager.java b/src/main/java/net/minestom/server/scoreboard/TeamManager.java index 238b3c8fb..aab968ee8 100644 --- a/src/main/java/net/minestom/server/scoreboard/TeamManager.java +++ b/src/main/java/net/minestom/server/scoreboard/TeamManager.java @@ -1,14 +1,14 @@ package net.minestom.server.scoreboard; -import io.netty.buffer.ByteBuf; import net.minestom.server.MinecraftServer; import net.minestom.server.chat.ChatColor; import net.minestom.server.chat.ColoredText; import net.minestom.server.entity.LivingEntity; import net.minestom.server.entity.Player; -import net.minestom.server.network.PacketWriterUtils; -import net.minestom.server.network.packet.server.ServerPacket; +import net.minestom.server.network.ConnectionManager; +import net.minestom.server.utils.PacketUtils; import net.minestom.server.utils.UniqueIdUtils; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; @@ -20,6 +20,8 @@ import java.util.concurrent.CopyOnWriteArraySet; */ public final class TeamManager { + private static final ConnectionManager CONNECTION_MANAGER = MinecraftServer.getConnectionManager(); + /** * Represents all registered teams */ @@ -37,9 +39,10 @@ public final class TeamManager { * * @param team The team to be registered */ - protected void registerNewTeam(Team team) { + protected void registerNewTeam(@NotNull Team team) { this.teams.add(team); - this.broadcastPacket(team.getTeamsCreationPacket()); + + PacketUtils.sendGroupedPacket(MinecraftServer.getConnectionManager().getOnlinePlayers(), team.createTeamsCreationPacket()); } /** @@ -48,7 +51,7 @@ public final class TeamManager { * @param registryName The registry name of team * @return {@code true} if the team was deleted, otherwise {@code false} */ - public boolean deleteTeam(String registryName) { + public boolean deleteTeam(@NotNull String registryName) { Team team = this.getTeam(registryName); if (team == null) return false; return this.deleteTeam(team); @@ -60,9 +63,9 @@ public final class TeamManager { * @param team The team to be deleted * @return {@code true} if the team was deleted, otherwise {@code false} */ - public boolean deleteTeam(Team team) { + public boolean deleteTeam(@NotNull Team team) { // Sends to all online players a team destroy packet - this.broadcastBuffer(team.getTeamsDestroyPacket()); + PacketUtils.sendGroupedPacket(CONNECTION_MANAGER.getOnlinePlayers(), team.createTeamDestructionPacket()); return this.teams.remove(team); } @@ -72,7 +75,7 @@ public final class TeamManager { * @param name The registry name of the team * @return the team builder */ - public TeamBuilder createBuilder(String name) { + public TeamBuilder createBuilder(@NotNull String name) { return new TeamBuilder(name, this); } @@ -82,7 +85,7 @@ public final class TeamManager { * @param name The registry name * @return the created {@link Team} */ - public Team createTeam(String name) { + public Team createTeam(@NotNull String name) { return this.createBuilder(name).build(); } @@ -193,24 +196,4 @@ public final class TeamManager { public Set getTeams() { return this.teams; } - - /** - * Broadcasts to all online {@link Player}'s a {@link ServerPacket} - * - * @param packet The packet to broadcast - */ - private void broadcastPacket(ServerPacket packet) { - PacketWriterUtils.writeAndSend(MinecraftServer.getConnectionManager().getOnlinePlayers(), packet); - } - - /** - * Broadcasts to all online {@link Player}'s a buffer - * - * @param buffer The buffer to broadcast - */ - private void broadcastBuffer(ByteBuf buffer) { - for (Player onlinePlayer : MinecraftServer.getConnectionManager().getOnlinePlayers()) { - onlinePlayer.getPlayerConnection().sendPacket(buffer, true); - } - } } diff --git a/src/main/java/net/minestom/server/utils/PacketUtils.java b/src/main/java/net/minestom/server/utils/PacketUtils.java index d526127cd..d0ebab32e 100644 --- a/src/main/java/net/minestom/server/utils/PacketUtils.java +++ b/src/main/java/net/minestom/server/utils/PacketUtils.java @@ -2,10 +2,13 @@ package net.minestom.server.utils; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; +import net.minestom.server.entity.Player; import net.minestom.server.network.packet.server.ServerPacket; import net.minestom.server.utils.binary.BinaryWriter; import org.jetbrains.annotations.NotNull; +import java.util.Collection; + /** * Class used to write packets. */ @@ -15,6 +18,12 @@ public final class PacketUtils { } + public static void sendGroupedPacket(Collection players, ServerPacket packet) { + for (Player player : players) { + player.getPlayerConnection().sendPacket(packet); + } + } + /** * Writes a {@link ServerPacket} into a {@link ByteBuf}. * diff --git a/src/test/java/demo/PlayerInit.java b/src/test/java/demo/PlayerInit.java index 2939f1699..7b2d28aa3 100644 --- a/src/test/java/demo/PlayerInit.java +++ b/src/test/java/demo/PlayerInit.java @@ -83,6 +83,12 @@ public class PlayerInit { packetController.setCancel(false); }); + connectionManager.onPacketSend((player, packetController, packet) -> { + // Listen to all sent packet + System.out.println("PACKET: " + packet.getClass().getSimpleName()); + packetController.setCancel(false); + }); + connectionManager.addPlayerInitialization(player -> { player.addEventCallback(EntityAttackEvent.class, event -> {