From eb5659c235e366e97b9b459035eba1140bdad53e Mon Sep 17 00:00:00 2001 From: Felix Cravic Date: Fri, 29 May 2020 02:11:41 +0200 Subject: [PATCH] Optimize bandwidth + fix keep alive --- .../net/minestom/server/UpdateManager.java | 12 +++++++++- .../net/minestom/server/entity/Entity.java | 2 ++ .../server/entity/EntityCreature.java | 3 +++ .../minestom/server/entity/ObjectEntity.java | 6 ++++- .../net/minestom/server/entity/Player.java | 23 +++++++++++++++---- .../minestom/server/inventory/Inventory.java | 9 ++++---- .../server/listener/KeepAliveListener.java | 2 ++ .../server/network/PacketWriterUtils.java | 3 +-- 8 files changed, 47 insertions(+), 13 deletions(-) diff --git a/src/main/java/net/minestom/server/UpdateManager.java b/src/main/java/net/minestom/server/UpdateManager.java index 1d39ce732..cd7c8a4e1 100644 --- a/src/main/java/net/minestom/server/UpdateManager.java +++ b/src/main/java/net/minestom/server/UpdateManager.java @@ -1,5 +1,7 @@ package net.minestom.server; +import net.kyori.text.TextComponent; +import net.kyori.text.format.TextColor; import net.minestom.server.entity.EntityManager; import net.minestom.server.entity.Player; import net.minestom.server.instance.InstanceManager; @@ -12,6 +14,9 @@ import java.util.concurrent.ExecutorService; public class UpdateManager { + private static final long KEEP_ALIVE_DELAY = 10_000; + private static final long KEEP_ALIVE_KICK = 30_000; + private ExecutorService mainUpdate = new MinestomThread(MinecraftServer.THREAD_COUNT_MAIN_UPDATE, MinecraftServer.THREAD_NAME_MAIN_UPDATE); private boolean stopRequested; @@ -33,9 +38,14 @@ public class UpdateManager { final long time = System.currentTimeMillis(); final KeepAlivePacket keepAlivePacket = new KeepAlivePacket(time); for (Player player : connectionManager.getOnlinePlayers()) { - if (time - player.getLastKeepAlive() > 10000) { + final long lastKeepAlive = time - player.getLastKeepAlive(); + if (lastKeepAlive > KEEP_ALIVE_DELAY && player.didAnswerKeepAlive()) { player.refreshKeepAlive(time); player.getPlayerConnection().sendPacket(keepAlivePacket); + } else if (lastKeepAlive >= KEEP_ALIVE_KICK) { + TextComponent textComponent = TextComponent.of("No Keep Alive answer") + .color(TextColor.RED); + player.kick(textComponent); } } diff --git a/src/main/java/net/minestom/server/entity/Entity.java b/src/main/java/net/minestom/server/entity/Entity.java index 0cd6b12ef..29499bd09 100644 --- a/src/main/java/net/minestom/server/entity/Entity.java +++ b/src/main/java/net/minestom/server/entity/Entity.java @@ -266,6 +266,8 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer { public boolean addViewer(Player player) { Check.notNull(player, "Viewer cannot be null"); boolean result = this.viewers.add(player); + if (!result) + return false; player.viewableEntities.add(this); return result; } diff --git a/src/main/java/net/minestom/server/entity/EntityCreature.java b/src/main/java/net/minestom/server/entity/EntityCreature.java index a072fc182..1842103fa 100644 --- a/src/main/java/net/minestom/server/entity/EntityCreature.java +++ b/src/main/java/net/minestom/server/entity/EntityCreature.java @@ -142,6 +142,9 @@ public abstract class EntityCreature extends LivingEntity { @Override public boolean addViewer(Player player) { boolean result = super.addViewer(player); + if (!result) + return false; + PlayerConnection playerConnection = player.getPlayerConnection(); EntityPacket entityPacket = new EntityPacket(); diff --git a/src/main/java/net/minestom/server/entity/ObjectEntity.java b/src/main/java/net/minestom/server/entity/ObjectEntity.java index 9ad11b812..f9d5543cb 100644 --- a/src/main/java/net/minestom/server/entity/ObjectEntity.java +++ b/src/main/java/net/minestom/server/entity/ObjectEntity.java @@ -30,6 +30,10 @@ public abstract class ObjectEntity extends Entity { @Override public boolean addViewer(Player player) { + boolean result = super.addViewer(player); + if (!result) + return false; + PlayerConnection playerConnection = player.getPlayerConnection(); SpawnEntityPacket spawnEntityPacket = new SpawnEntityPacket(); @@ -46,7 +50,7 @@ public abstract class ObjectEntity extends Entity { playerConnection.sendPacket(getPassengersPacket()); } - return super.addViewer(player); // Add player to viewers list + return result; } } diff --git a/src/main/java/net/minestom/server/entity/Player.java b/src/main/java/net/minestom/server/entity/Player.java index c1f979188..09d79770c 100644 --- a/src/main/java/net/minestom/server/entity/Player.java +++ b/src/main/java/net/minestom/server/entity/Player.java @@ -54,6 +54,7 @@ import java.util.function.Consumer; public class Player extends LivingEntity { private long lastKeepAlive; + private boolean answerKeepAlive; private String username; protected PlayerConnection playerConnection; @@ -144,6 +145,9 @@ public class Player extends LivingEntity { setCanPickupItem(true); // By default + // Allow the server to send the next keep alive packet + refreshAnswerKeepAlive(true); + this.gameMode = GameMode.SURVIVAL; this.dimension = Dimension.OVERWORLD; this.levelType = LevelType.DEFAULT; @@ -337,11 +341,10 @@ public class Player extends LivingEntity { // Tick event callEvent(PlayerTickEvent.class, playerTickEvent); - // Multiplayer sync - if (!getViewers().isEmpty()) { - final boolean positionChanged = position.getX() != lastX || position.getZ() != lastZ || position.getY() != lastY; - final boolean viewChanged = position.getYaw() != lastYaw || position.getPitch() != lastPitch; + final boolean positionChanged = position.getX() != lastX || position.getY() != lastY || position.getZ() != lastZ; + final boolean viewChanged = position.getYaw() != lastYaw || position.getPitch() != lastPitch; + if (!getViewers().isEmpty() && (positionChanged || viewChanged)) { ServerPacket updatePacket = null; ServerPacket optionalUpdatePacket = null; if (positionChanged && viewChanged) { @@ -483,6 +486,9 @@ public class Player extends LivingEntity { return false; boolean result = super.addViewer(player); + if (!result) + return false; + PlayerConnection viewerConnection = player.getPlayerConnection(); String property = "eyJ0aW1lc3RhbXAiOjE1NjU0ODMwODQwOTYsInByb2ZpbGVJZCI6ImFiNzBlY2I0MjM0NjRjMTRhNTJkN2EwOTE1MDdjMjRlIiwicHJvZmlsZU5hbWUiOiJUaGVNb2RlOTExIiwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2RkOTE2NzJiNTE0MmJhN2Y3MjA2ZTRjN2IwOTBkNzhlM2Y1ZDc2NDdiNWFmZDIyNjFhZDk4OGM0MWI2ZjcwYTEifX19"; SpawnPlayerPacket spawnPlayerPacket = new SpawnPlayerPacket(); @@ -1566,6 +1572,15 @@ public class Player extends LivingEntity { */ public void refreshKeepAlive(long lastKeepAlive) { this.lastKeepAlive = lastKeepAlive; + this.answerKeepAlive = false; + } + + public boolean didAnswerKeepAlive() { + return answerKeepAlive; + } + + public void refreshAnswerKeepAlive(boolean answerKeepAlive) { + this.answerKeepAlive = answerKeepAlive; } /** diff --git a/src/main/java/net/minestom/server/inventory/Inventory.java b/src/main/java/net/minestom/server/inventory/Inventory.java index 4d2f95f79..df2a23ed8 100644 --- a/src/main/java/net/minestom/server/inventory/Inventory.java +++ b/src/main/java/net/minestom/server/inventory/Inventory.java @@ -121,7 +121,7 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View * Refresh the inventory for all viewers */ public void update() { - PacketWriterUtils.writeAndSend(getViewers(), getWindowItemsPacket()); + PacketWriterUtils.writeAndSend(getViewers(), createWindowItemsPacket()); } /** @@ -134,7 +134,7 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View if (!getViewers().contains(player)) return; - PacketWriterUtils.writeAndSend(player, getWindowItemsPacket()); + PacketWriterUtils.writeAndSend(player, createWindowItemsPacket()); } @Override @@ -145,8 +145,7 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View @Override public boolean addViewer(Player player) { boolean result = this.viewers.add(player); - WindowItemsPacket windowItemsPacket = getWindowItemsPacket(); - player.getPlayerConnection().sendPacket(windowItemsPacket); + PacketWriterUtils.writeAndSend(player, createWindowItemsPacket()); return result; } @@ -174,7 +173,7 @@ public class Inventory implements InventoryModifier, InventoryClickHandler, View } } - private WindowItemsPacket getWindowItemsPacket() { + private WindowItemsPacket createWindowItemsPacket() { WindowItemsPacket windowItemsPacket = new WindowItemsPacket(); windowItemsPacket.windowId = getWindowId(); windowItemsPacket.count = (short) itemStacks.length; diff --git a/src/main/java/net/minestom/server/listener/KeepAliveListener.java b/src/main/java/net/minestom/server/listener/KeepAliveListener.java index 2c061b671..109e5b79f 100644 --- a/src/main/java/net/minestom/server/listener/KeepAliveListener.java +++ b/src/main/java/net/minestom/server/listener/KeepAliveListener.java @@ -18,6 +18,8 @@ public class KeepAliveListener { return; } + player.refreshAnswerKeepAlive(true); + // Update latency int latency = (int) (System.currentTimeMillis() - packet.id); player.refreshLatency(latency); diff --git a/src/main/java/net/minestom/server/network/PacketWriterUtils.java b/src/main/java/net/minestom/server/network/PacketWriterUtils.java index 31b9f00a5..9558c801d 100644 --- a/src/main/java/net/minestom/server/network/PacketWriterUtils.java +++ b/src/main/java/net/minestom/server/network/PacketWriterUtils.java @@ -26,8 +26,7 @@ public class PacketWriterUtils { public static void writeAndSend(Collection players, ServerPacket serverPacket) { batchesPool.execute(() -> { - int size = players.size(); - if (size == 0) + if (players.isEmpty()) return; ByteBuf buffer = PacketUtils.writePacket(serverPacket);