From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: MrHua269 Date: Thu, 9 Jul 2026 10:17:22 +0800 Subject: [PATCH] Add portal rate limiter diff --git a/io/papermc/paper/threadedregions/RegionizedWorldData.java b/io/papermc/paper/threadedregions/RegionizedWorldData.java index df9a8fba86b61d2d2f82e40e0f317cab84faa2ff..7cbf93b183eaeb156467044ccdb2923e6d944438 100644 --- a/io/papermc/paper/threadedregions/RegionizedWorldData.java +++ b/io/papermc/paper/threadedregions/RegionizedWorldData.java @@ -157,6 +157,10 @@ public final class RegionizedWorldData { for (final ChunkHolder chunkHolder : from.chunkHoldersToBroadcast) { into.chunkHoldersToBroadcast.add(chunkHolder); } + // Shiroha start - Add portal rate limiter + into.portalRateThrottler.mergeWith(from.portalRateThrottler); + from.portalRateThrottler.destroy(); + // Shiroha end } @Override @@ -322,6 +326,12 @@ public final class RegionizedWorldData { into.chunkHoldersToBroadcast.add(chunkHolder); } } + // Shiroha start - Add portal rate limiter + for (var worldData : dataSet) { + from.portalRateThrottler.splitInto(worldData.portalRateThrottler); + } + from.portalRateThrottler.destroy(); + // Shiroha end } }; @@ -343,6 +353,35 @@ public final class RegionizedWorldData { return this.isHandlingTick; } + // Shiroha start - Add portal rate limiter + public final io.nanachiyo0721.shiroha.utils.RateThrottler portalRateThrottler = new io.nanachiyo0721.shiroha.utils.RateThrottler(); + public final net.objecthunter.exp4j.Expression portalRateCapExpression = io.nanachiyo0721.shiroha.config.modules.function.PortalRateLimiterConfig.getExpressionIfConfigured(); + + private int computePortalRateCap() { + // expression mode is disabled + if (this.portalRateCapExpression == null) { + return io.nanachiyo0721.shiroha.config.modules.function.PortalRateLimiterConfig.maxPortalTeleportsPerTick; + } + + final int tickingEntityCount = this.entityTickList.size(); + final int tickingChunkCount = this.tickingChunks.size(); + final int playerCount = this.localPlayers.size(); + + return io.nanachiyo0721.shiroha.config.modules.function.PortalRateLimiterConfig.computeExpression( + this.portalRateCapExpression, + tickingEntityCount, + tickingChunkCount, + playerCount + ); + } + public boolean isPortalTeleportationOutOfRate() { + if (!io.nanachiyo0721.shiroha.config.modules.function.PortalRateLimiterConfig.enabled) { + return false; + } + + return this.portalRateThrottler.isOutOfRate(this.computePortalRateCap()); + } + // Shiroha end // entities // this is copy on write to allow packet processing to iterate safely private final CopyOnWriteArrayList localPlayers = new CopyOnWriteArrayList<>(); diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java index 3ecedf303384c172a5e2a19c9e6ac0c3a43cef74..ee7fce1e4e9b94b1f9c956c376fff0abee51b0ca 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java @@ -1933,6 +1933,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop level + " " + level.dimension().identifier()); profiler.push("tick"); + // Shiroha start - Add portal rate limiter + regionizedWorldData.portalRateThrottler.begin(); + // Shiroha end try { foliaProfiler.startTimer(level.tickTimerId); try { // Folia - profiler @@ -1947,6 +1950,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop