2026-07-09 00:03:09 +08:00
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <mrhua269@gmail.com>
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
2026-07-26 22:29:41 +08:00
index df9a8fba86b61d2d2f82e40e0f317cab84faa2ff..7cbf93b183eaeb156467044ccdb2923e6d944438 100644
2026-07-09 00:03:09 +08:00
--- 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);
}
2026-07-14 11:32:51 +08:00
+ // Shiroha start - Add portal rate limiter
2026-07-09 00:03:09 +08:00
+ into.portalRateThrottler.mergeWith(from.portalRateThrottler);
+ from.portalRateThrottler.destroy();
2026-07-14 11:32:51 +08:00
+ // Shiroha end
2026-07-09 00:03:09 +08:00
}
@Override
@@ -322,6 +326,12 @@ public final class RegionizedWorldData {
into.chunkHoldersToBroadcast.add(chunkHolder);
}
}
2026-07-14 11:32:51 +08:00
+ // Shiroha start - Add portal rate limiter
2026-07-09 00:03:09 +08:00
+ for (var worldData : dataSet) {
+ from.portalRateThrottler.splitInto(worldData.portalRateThrottler);
+ }
+ from.portalRateThrottler.destroy();
2026-07-14 11:32:51 +08:00
+ // Shiroha end
2026-07-09 00:03:09 +08:00
}
};
@@ -343,6 +353,35 @@ public final class RegionizedWorldData {
return this.isHandlingTick;
}
2026-07-14 11:32:51 +08:00
+ // Shiroha start - Add portal rate limiter
2026-07-14 12:22:17 +08:00
+ 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();
2026-07-09 00:03:09 +08:00
+
+ private int computePortalRateCap() {
+ // expression mode is disabled
+ if (this.portalRateCapExpression == null) {
2026-07-14 12:22:17 +08:00
+ return io.nanachiyo0721.shiroha.config.modules.function.PortalRateLimiterConfig.maxPortalTeleportsPerTick;
2026-07-09 00:03:09 +08:00
+ }
+
+ final int tickingEntityCount = this.entityTickList.size();
+ final int tickingChunkCount = this.tickingChunks.size();
+ final int playerCount = this.localPlayers.size();
+
2026-07-14 12:22:17 +08:00
+ return io.nanachiyo0721.shiroha.config.modules.function.PortalRateLimiterConfig.computeExpression(
2026-07-09 00:03:09 +08:00
+ this.portalRateCapExpression,
+ tickingEntityCount,
+ tickingChunkCount,
+ playerCount
+ );
+ }
+ public boolean isPortalTeleportationOutOfRate() {
2026-07-14 12:22:17 +08:00
+ if (!io.nanachiyo0721.shiroha.config.modules.function.PortalRateLimiterConfig.enabled) {
2026-07-09 00:03:09 +08:00
+ return false;
+ }
+
+ return this.portalRateThrottler.isOutOfRate(this.computePortalRateCap());
+ }
2026-07-14 11:32:51 +08:00
+ // Shiroha end
2026-07-09 00:03:09 +08:00
// entities
// this is copy on write to allow packet processing to iterate safely
private final CopyOnWriteArrayList<ServerPlayer> localPlayers = new CopyOnWriteArrayList<>();
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
2026-07-18 19:48:30 +08:00
index 6025675b7004c9700ddc26638761f76d64ecc026..5be3e493f1638cc0befe5530c58ea15467a3a7ac 100644
2026-07-09 00:03:09 +08:00
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
2026-07-18 19:48:30 +08:00
@@ -1932,6 +1932,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
2026-07-09 00:03:09 +08:00
//net.minecraft.world.level.block.entity.HopperBlockEntity.skipHopperEvents = level.paperConfig().hopper.disableMoveEvent || org.bukkit.event.inventory.InventoryMoveItemEvent.getHandlerList().getRegisteredListeners().length == 0; // Paper - Perf: Optimize Hoppers // Folia - region threading
profiler.push(() -> level + " " + level.dimension().identifier());
profiler.push("tick");
2026-07-14 11:32:51 +08:00
+ // Shiroha start - Add portal rate limiter
2026-07-09 00:03:09 +08:00
+ regionizedWorldData.portalRateThrottler.begin();
2026-07-14 11:32:51 +08:00
+ // Shiroha end
2026-07-09 00:03:09 +08:00
try {
foliaProfiler.startTimer(level.tickTimerId); try { // Folia - profiler
2026-07-18 19:48:30 +08:00
@@ -1946,6 +1949,9 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
2026-07-09 00:03:09 +08:00
profiler.pop();
profiler.pop();
regionizedWorldData.explosionDensityCache.clear(); // Paper - Optimize explosions // Folia - region threading
2026-07-14 11:32:51 +08:00
+ // Shiroha start - Add portal rate limiter
2026-07-09 00:03:09 +08:00
+ regionizedWorldData.portalRateThrottler.done();
2026-07-14 11:32:51 +08:00
+ // Shiroha end
2026-07-09 00:03:09 +08:00
}
//this.isIteratingOverLevels = false; // Paper - Throw exception on world create while being ticked // Folia - region threading
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
2026-07-18 19:48:30 +08:00
index 5668f80c2ac1fcf2ac0e1e5378c789d7fce655f3..ecb1b98723e78e9d2f3ce182be8f78f8f32a52da 100644
2026-07-09 00:03:09 +08:00
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
2026-07-18 19:48:30 +08:00
@@ -1536,8 +1536,15 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
2026-07-09 00:03:09 +08:00
// removed from region while ticking
return;
}
2026-07-14 11:32:51 +08:00
+ // Shiroha start - Add portal rate limiter
2026-07-09 00:03:09 +08:00
+ var worldData = entity.level().getCurrentWorldData();
+ if (entity.portalProcess != null && worldData.isPortalTeleportationOutOfRate()) {
+ return;
+ }
2026-07-14 11:32:51 +08:00
+ // Shiroha end
2026-07-09 00:03:09 +08:00
if (entity.handlePortal()) {
// portalled
2026-07-14 11:32:51 +08:00
+ worldData.portalRateThrottler.increase(); // Shiroha - Add portal rate limiter
2026-07-09 00:03:09 +08:00
return;
}
}
2026-07-18 19:48:30 +08:00
@@ -1581,8 +1588,15 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet
2026-07-09 00:03:09 +08:00
// removed from region while ticking
return;
}
2026-07-14 11:32:51 +08:00
+ // Shiroha start - Add portal rate limiter
2026-07-09 00:03:09 +08:00
+ var worldData = entity.level().getCurrentWorldData();
+ if (entity.portalProcess != null && worldData.isPortalTeleportationOutOfRate()) {
+ return;
+ }
2026-07-14 11:32:51 +08:00
+ // Shiroha end
2026-07-09 00:03:09 +08:00
if (entity.handlePortal()) {
// portalled
2026-07-14 11:32:51 +08:00
+ worldData.portalRateThrottler.increase(); // Shiroha - Add portal rate limiter
2026-07-09 00:03:09 +08:00
return;
}
// Folia end - region threading