Optimize bandwidth + fix keep alive

This commit is contained in:
Felix Cravic 2020-05-29 02:11:41 +02:00
parent b00627f778
commit eb5659c235
8 changed files with 47 additions and 13 deletions

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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();

View File

@ -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;
}
}

View File

@ -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;
}
/**

View File

@ -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;

View File

@ -18,6 +18,8 @@ public class KeepAliveListener {
return;
}
player.refreshAnswerKeepAlive(true);
// Update latency
int latency = (int) (System.currentTimeMillis() - packet.id);
player.refreshLatency(latency);

View File

@ -26,8 +26,7 @@ public class PacketWriterUtils {
public static void writeAndSend(Collection<Player> players, ServerPacket serverPacket) {
batchesPool.execute(() -> {
int size = players.size();
if (size == 0)
if (players.isEmpty())
return;
ByteBuf buffer = PacketUtils.writePacket(serverPacket);