diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 176c7e3cb..0a1c00f3d 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -13,10 +13,11 @@ jobs: steps: - uses: actions/checkout@v2 - - name: Set up JDK 11 - uses: actions/setup-java@v1 + - name: Set up JDK 16 + uses: actions/setup-java@v2 with: - java-version: 11 + distribution: 'adopt' + java-version: 16 - name: Grant execute permission for gradlew run: chmod +x gradlew - name: Setup gradle cache diff --git a/src/main/java/net/minestom/server/UpdateManager.java b/src/main/java/net/minestom/server/UpdateManager.java index afe43c11d..f337a0a1b 100644 --- a/src/main/java/net/minestom/server/UpdateManager.java +++ b/src/main/java/net/minestom/server/UpdateManager.java @@ -15,6 +15,7 @@ import org.jetbrains.annotations.NotNull; import java.util.List; import java.util.Queue; import java.util.concurrent.*; +import java.util.concurrent.locks.LockSupport; import java.util.function.Consumer; import java.util.function.LongConsumer; @@ -25,9 +26,6 @@ import java.util.function.LongConsumer; */ public final class UpdateManager { - private final ScheduledExecutorService updateExecutionService = Executors.newSingleThreadScheduledExecutor(r -> - new Thread(r, MinecraftServer.THREAD_NAME_TICK_SCHEDULER)); - private volatile boolean stopRequested; // TODO make configurable @@ -49,54 +47,52 @@ public final class UpdateManager { protected void start() { final ConnectionManager connectionManager = MinecraftServer.getConnectionManager(); - updateExecutionService.scheduleAtFixedRate(() -> { - try { - if (stopRequested) { - updateExecutionService.shutdown(); - return; + new Thread(() -> { + while (!stopRequested) { + try { + long currentTime = System.nanoTime(); + final long tickStart = System.currentTimeMillis(); + + // Tick start callbacks + doTickCallback(tickStartCallbacks, tickStart); + + // Waiting players update (newly connected clients waiting to get into the server) + connectionManager.updateWaitingPlayers(); + + // Keep Alive Handling + connectionManager.handleKeepAlive(tickStart); + + // Server tick (chunks/entities) + serverTick(tickStart); + + // the time that the tick took in nanoseconds + final long tickTime = System.nanoTime() - currentTime; + + // Tick end callbacks + doTickCallback(tickEndCallbacks, tickTime); + + // Monitoring + if (!tickMonitors.isEmpty()) { + final double acquisitionTimeMs = Acquirable.getAcquiringTime() / 1e6D; + final double tickTimeMs = tickTime / 1e6D; + final TickMonitor tickMonitor = new TickMonitor(tickTimeMs, acquisitionTimeMs); + this.tickMonitors.forEach(consumer -> consumer.accept(tickMonitor)); + Acquirable.resetAcquiringTime(); + } + + // Flush all waiting packets + AsyncUtils.runAsync(() -> connectionManager.getOnlinePlayers().parallelStream() + .filter(player -> player.getPlayerConnection() instanceof NettyPlayerConnection) + .map(player -> (NettyPlayerConnection) player.getPlayerConnection()) + .forEach(NettyPlayerConnection::flush)); + + // Disable thread until next tick + LockSupport.parkNanos((long) ((MinecraftServer.TICK_MS * 1e6) - tickTime)); + } catch (Exception e) { + MinecraftServer.getExceptionManager().handleException(e); } - - long currentTime = System.nanoTime(); - final long tickStart = System.currentTimeMillis(); - - // Tick start callbacks - doTickCallback(tickStartCallbacks, tickStart); - - // Waiting players update (newly connected clients waiting to get into the server) - connectionManager.updateWaitingPlayers(); - - // Keep Alive Handling - connectionManager.handleKeepAlive(tickStart); - - // Server tick (chunks/entities) - serverTick(tickStart); - - // the time that the tick took in nanoseconds - final long tickTime = System.nanoTime() - currentTime; - - // Tick end callbacks - doTickCallback(tickEndCallbacks, tickTime); - - // Monitoring - if (!tickMonitors.isEmpty()) { - final double acquisitionTimeMs = Acquirable.getAcquiringTime() / 1e6D; - final double tickTimeMs = tickTime / 1e6D; - final TickMonitor tickMonitor = new TickMonitor(tickTimeMs, acquisitionTimeMs); - this.tickMonitors.forEach(consumer -> consumer.accept(tickMonitor)); - - Acquirable.resetAcquiringTime(); - } - - // Flush all waiting packets - AsyncUtils.runAsync(() -> connectionManager.getOnlinePlayers().parallelStream() - .filter(player -> player.getPlayerConnection() instanceof NettyPlayerConnection) - .map(player -> (NettyPlayerConnection) player.getPlayerConnection()) - .forEach(NettyPlayerConnection::flush)); - - } catch (Exception e) { - MinecraftServer.getExceptionManager().handleException(e); } - }, 0, MinecraftServer.TICK_MS, TimeUnit.MILLISECONDS); + }, MinecraftServer.THREAD_NAME_TICK_SCHEDULER).start(); } /** diff --git a/src/main/java/net/minestom/server/network/packet/server/play/ExplosionPacket.java b/src/main/java/net/minestom/server/network/packet/server/play/ExplosionPacket.java index acd4fee22..8605e993c 100644 --- a/src/main/java/net/minestom/server/network/packet/server/play/ExplosionPacket.java +++ b/src/main/java/net/minestom/server/network/packet/server/play/ExplosionPacket.java @@ -36,7 +36,7 @@ public class ExplosionPacket implements ServerPacket { y = reader.readFloat(); z = reader.readFloat(); radius = reader.readFloat(); - int recordCount = reader.readInt() * 3; + int recordCount = reader.readVarInt() * 3; records = reader.readBytes(recordCount); playerMotionX = reader.readFloat(); playerMotionY = reader.readFloat(); diff --git a/src/main/java/net/minestom/server/network/packet/server/play/MapDataPacket.java b/src/main/java/net/minestom/server/network/packet/server/play/MapDataPacket.java index 5d1386e07..bd9d87295 100644 --- a/src/main/java/net/minestom/server/network/packet/server/play/MapDataPacket.java +++ b/src/main/java/net/minestom/server/network/packet/server/play/MapDataPacket.java @@ -73,11 +73,15 @@ public class MapDataPacket implements ComponentHoldingServerPacket { locked = reader.readBoolean(); trackingPosition = reader.readBoolean(); - int iconCount = reader.readVarInt(); - icons = new Icon[iconCount]; - for (int i = 0; i < iconCount; i++) { - icons[i] = new Icon(); - icons[i].read(reader); + if (trackingPosition) { + int iconCount = reader.readVarInt(); + icons = new Icon[iconCount]; + for (int i = 0; i < iconCount; i++) { + icons[i] = new Icon(); + icons[i].read(reader); + } + } else { + icons = new Icon[0]; } columns = reader.readByte();