From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: MrHua269 Date: Fri, 1 May 2026 21:47:48 +0800 Subject: [PATCH] Pufferfish: Reduce projectile chunk loading A part of Pufferfish(https://github.com/Pufferfish-gg/Pufferfish) Co-authored-by: Paul Sauve Original patch: https://github.com/pufferfish-gg/Pufferfish/blob/ver/1.21/pufferfish-server/minecraft-patches/features/0006-Reduce-projectile-chunk-loading.patch Original license(GPL-3.0): https://github.com/pufferfish-gg/Pufferfish/blob/ver/1.21/PATCH-LICENSE diff --git a/io/papermc/paper/threadedregions/RegionizedWorldData.java b/io/papermc/paper/threadedregions/RegionizedWorldData.java index 5a72d922af1af3a4e2314b8fa441787e7875ed77..1d393b97d09083eee5e21e00be5223741b5b7819 100644 --- a/io/papermc/paper/threadedregions/RegionizedWorldData.java +++ b/io/papermc/paper/threadedregions/RegionizedWorldData.java @@ -408,6 +408,10 @@ public final class RegionizedWorldData { private RegionizedServer.WorldLevelData tickData; + // Shiroha start - Pufferfish - Reduce projectile chunk loading + public long pufferfish$loadedThisTick = 0L; + public long pufferfish$loadedTick = 0L; + // Shiroha end // connections public final List connections = new ArrayList<>(); diff --git a/net/minecraft/world/entity/projectile/Projectile.java b/net/minecraft/world/entity/projectile/Projectile.java index 721e3b083846fd363a31311196bc4c681969215c..cc3aebbd42a876fcc982a9bf1c3dc1bd11f3a4e0 100644 --- a/net/minecraft/world/entity/projectile/Projectile.java +++ b/net/minecraft/world/entity/projectile/Projectile.java @@ -58,6 +58,38 @@ public abstract class Projectile extends Entity implements TraceableEntity { this.setOwner(EntityReference.of(owner)); } + // Pufferfish start + private int loadedLifetime = 0; + @Override + public void setPos(double x, double y, double z) { + var currRegionData = io.papermc.paper.threadedregions.TickRegionScheduler.getCurrentRegionizedWorldData(); + // we might run this on a chunk system worker(chunk gen), so skip this check if no world data was fetched + if (currRegionData == null || currRegionData.world != this.level()) { + return; + } + long currentTick = currRegionData.getRedstoneGameTime(); + if (currRegionData.pufferfish$loadedTick != currentTick) { + currRegionData.pufferfish$loadedTick = currentTick; + currRegionData.pufferfish$loadedThisTick = 0L; + } + int previousX = Mth.floor(this.getX()) >> 4, previousZ = Mth.floor(this.getZ()) >> 4; + int newX = Mth.floor(x) >> 4, newZ = Mth.floor(z) >> 4; + if (previousX != newX || previousZ != newZ) { + boolean isLoaded = ((net.minecraft.server.level.ServerChunkCache) this.level().getChunkSource()).getChunkAtIfLoadedImmediately(newX, newZ) != null; + if (!isLoaded) { + if (currRegionData.pufferfish$loadedThisTick > io.nanachiyo0721.shiroha.config.modules.optimizations.ProjectileChunkReduceConfig.maxProjectileLoadsPerTick) { + if (++this.loadedLifetime > io.nanachiyo0721.shiroha.config.modules.optimizations.ProjectileChunkReduceConfig.maxProjectileLoadsPerProjectile) { + this.discard(); + } + return; + } + currRegionData.pufferfish$loadedThisTick++; + } + } + super.setPos(x, y, z); + } + // Pufferfish end + // Folia start - region threading // In general, this is an entire mess. At the time of writing, there are fifty usages of getOwner. // Usage of this function is to avoid concurrency issues, even if it sacrifices behavior.