From d14ddc4fabd2189d5f63b49596539871032c74bc Mon Sep 17 00:00:00 2001 From: YoyoNow Date: Mon, 19 Oct 2026 07:18:29 +0000 Subject: [PATCH] Fix lag from PistonCalculator at high TPS Bundle piston order recalculations into one run every 200ms (wall clock, independent of TPS) instead of one full recalculation and entity rebuild per piston/place/break event. Tracked pistons that get moved are removed from the visualization instead of being moved along. Fixes #227 --- .../features/util/PistonCalculator.java | 55 ++++++++++--------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/util/PistonCalculator.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/util/PistonCalculator.java index 59044202..8b9b4a62 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/util/PistonCalculator.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/util/PistonCalculator.java @@ -94,41 +94,48 @@ public class PistonCalculator implements Listener { @EventHandler public void onBlockPistonExtend(BlockPistonExtendEvent event) { if (pistOrders.isEmpty()) return; - Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> { - movePistOrders(event.getDirection(), event.getBlocks()); - pistOrders.values().forEach(PistOrder::calculate); - }, 3); + removeMovedPistOrders(event.getBlocks()); + scheduleRecalculate(); } @EventHandler public void onBlockPistonRetract(BlockPistonRetractEvent event) { if (pistOrders.isEmpty()) return; - Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> { - movePistOrders(event.getDirection(), event.getBlocks()); - pistOrders.values().forEach(PistOrder::calculate); - }, 3); + removeMovedPistOrders(event.getBlocks()); + scheduleRecalculate(); } - private void movePistOrders(BlockFace direction, List blocks) { - Set orders = new HashSet<>(); + private void removeMovedPistOrders(List blocks) { blocks.forEach(block -> { - PistOrder pistOrder = pistOrders.get(block.getLocation()); - if (pistOrder == null) return; - pistOrders.remove(block.getLocation()); - pistOrder.piston = pistOrder.piston.getRelative(direction); - orders.add(pistOrder); - }); - orders.forEach(pistOrder -> { - pistOrders.put(pistOrder.piston.getLocation(), pistOrder); + PistOrder pistOrder = pistOrders.remove(block.getLocation()); + if (pistOrder != null) pistOrder.server.close(); }); } + private static final long RECALCULATE_INTERVAL_MS = 200; + private boolean recalculationScheduled = false; + private long lastRecalculation = 0; + + private void scheduleRecalculate() { + if (recalculationScheduled) return; + recalculationScheduled = true; + Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), this::recalculateIfDue, 1); + } + + private void recalculateIfDue() { + if (System.currentTimeMillis() - lastRecalculation < RECALCULATE_INTERVAL_MS) { + Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), this::recalculateIfDue, 1); + return; + } + recalculationScheduled = false; + lastRecalculation = System.currentTimeMillis(); + pistOrders.values().forEach(PistOrder::calculate); + } + @EventHandler public void onBlockPlace(BlockPlaceEvent event) { if (pistOrders.isEmpty()) return; - Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> { - pistOrders.values().forEach(PistOrder::calculate); - }, 1); + scheduleRecalculate(); } @EventHandler @@ -138,9 +145,7 @@ public class PistonCalculator implements Listener { PistOrder pistOrder = pistOrders.remove(event.getBlock().getLocation()); pistOrder.server.close(); } - Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> { - pistOrders.values().forEach(PistOrder::calculate); - }, 1); + scheduleRecalculate(); } @EventHandler @@ -166,7 +171,7 @@ public class PistonCalculator implements Listener { private final Map pistOrders = new HashMap<>(); private final class PistOrder { - private Block piston; + private final Block piston; private REntityServer server = new REntityServer(); private boolean pulling = false;