diff --git a/purpur-server/minecraft-patches/rejected/net/minecraft/world/level/levelgen/PhantomSpawner.java.patch b/purpur-server/minecraft-patches/rejected/net/minecraft/world/level/levelgen/PhantomSpawner.java.patch deleted file mode 100644 index 432d33639..000000000 --- a/purpur-server/minecraft-patches/rejected/net/minecraft/world/level/levelgen/PhantomSpawner.java.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001 -From: File -Date: Sun, 20 Apr 1997 05:37:42 -0800 -Subject: [PATCH] purpur File Patches - - -diff --git a/net/minecraft/world/level/levelgen/PhantomSpawner.java b/net/minecraft/world/level/levelgen/PhantomSpawner.java -index 135e8cc1b423d5a2a96ede693a306534ea45686b..84b4b68397be1766089783255845471077cc19f3 100644 ---- a/net/minecraft/world/level/levelgen/PhantomSpawner.java -+++ b/net/minecraft/world/level/levelgen/PhantomSpawner.java -@@ -38,13 +38,13 @@ public class PhantomSpawner implements CustomSpawner { - int spawnAttemptMaxSeconds = level.paperConfig().entities.behavior.phantomsSpawnAttemptMaxSeconds; - this.nextTick += (spawnAttemptMinSeconds + randomSource.nextInt(spawnAttemptMaxSeconds - spawnAttemptMinSeconds + 1)) * 20; - // Paper end - Ability to control player's insomnia and phantoms -- if (level.getSkyDarken() >= 5 || !level.dimensionType().hasSkyLight()) { -+ if (level.getSkyDarken() >= level.purpurConfig.phantomSpawnMinSkyDarkness || !level.dimensionType().hasSkyLight()) { // Purpur - Add phantom spawning options - for (ServerPlayer serverPlayer : level.players()) { - if (!serverPlayer.isSpectator() && (!level.paperConfig().entities.behavior.phantomsDoNotSpawnOnCreativePlayers || !serverPlayer.isCreative())) { // Paper - Add phantom creative and insomniac controls - BlockPos blockPos = serverPlayer.blockPosition(); -- if (!level.dimensionType().hasSkyLight() || blockPos.getY() >= level.getSeaLevel() && level.canSeeSky(blockPos)) { -+ if (!level.dimensionType().hasSkyLight() || (!level.purpurConfig.phantomSpawnOnlyAboveSeaLevel || blockPos.getY() >= level.getSeaLevel()) && (!level.purpurConfig.phantomSpawnOnlyWithVisibleSky || level.canSeeSky(blockPos))) { // Purpur - Add phantom spawning options - DifficultyInstance currentDifficultyAt = level.getCurrentDifficultyAt(blockPos); -- if (currentDifficultyAt.isHarderThan(randomSource.nextFloat() * 3.0F)) { -+ if (currentDifficultyAt.isHarderThan(randomSource.nextFloat() * (float) level.purpurConfig.phantomSpawnLocalDifficultyChance)) { // Purpur - Add phantom spawning options - ServerStatsCounter stats = serverPlayer.getStats(); - int i = Mth.clamp(stats.getValue(Stats.CUSTOM.get(Stats.TIME_SINCE_REST)), 1, Integer.MAX_VALUE); - int i1 = 24000; -@@ -56,7 +56,7 @@ public class PhantomSpawner implements CustomSpawner { - FluidState fluidState = level.getFluidState(blockPos1); - if (NaturalSpawner.isValidEmptySpawnBlock(level, blockPos1, blockState, fluidState, EntityType.PHANTOM)) { - SpawnGroupData spawnGroupData = null; -- int i2 = 1 + randomSource.nextInt(currentDifficultyAt.getDifficulty().getId() + 1); -+ int i2 = level.purpurConfig.phantomSpawnMinPerAttempt + randomSource.nextInt((level.purpurConfig.phantomSpawnMaxPerAttempt < 0 ? currentDifficultyAt.getDifficulty().getId() : level.purpurConfig.phantomSpawnMaxPerAttempt - level.purpurConfig.phantomSpawnMinPerAttempt) + 1); // Purpur - Add phantom spawning options - - for (int i3 = 0; i3 < i2; i3++) { - // Paper start - PhantomPreSpawnEvent diff --git a/purpur-server/minecraft-patches/rejected/io/papermc/paper/entity/activation/ActivationRange.java.patch b/purpur-server/minecraft-patches/sources/io/papermc/paper/entity/activation/ActivationRange.java.patch similarity index 67% rename from purpur-server/minecraft-patches/rejected/io/papermc/paper/entity/activation/ActivationRange.java.patch rename to purpur-server/minecraft-patches/sources/io/papermc/paper/entity/activation/ActivationRange.java.patch index f10bea231..70f8de868 100644 --- a/purpur-server/minecraft-patches/rejected/io/papermc/paper/entity/activation/ActivationRange.java.patch +++ b/purpur-server/minecraft-patches/sources/io/papermc/paper/entity/activation/ActivationRange.java.patch @@ -1,14 +1,6 @@ -From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001 -From: File -Date: Sun, 20 Apr 1997 05:37:42 -0800 -Subject: [PATCH] purpur File Patches - - -diff --git a/io/papermc/paper/entity/activation/ActivationRange.java b/io/papermc/paper/entity/activation/ActivationRange.java -index c18823746ab2edcab536cb1589b7720e3af07e0f..bc62da127a01b33ce8fc0f958bc232d6287d57ec 100644 --- a/io/papermc/paper/entity/activation/ActivationRange.java +++ b/io/papermc/paper/entity/activation/ActivationRange.java -@@ -147,6 +147,8 @@ public final class ActivationRange { +@@ -147,6 +_,8 @@ continue; } @@ -17,7 +9,7 @@ index c18823746ab2edcab536cb1589b7720e3af07e0f..bc62da127a01b33ce8fc0f958bc232d6 final int worldHeight = world.getHeight(); ActivationRange.maxBB = player.getBoundingBox().inflate(maxRange, worldHeight, maxRange); ActivationType.MISC.boundingBox = player.getBoundingBox().inflate(miscActivationRange, worldHeight, miscActivationRange); -@@ -288,6 +290,7 @@ public final class ActivationRange { +@@ -288,6 +_,7 @@ * @return */ public static boolean checkIfActive(final Entity entity) { diff --git a/purpur-server/minecraft-patches/sources/net/minecraft/server/network/ServerCommonPacketListenerImpl.java.patch b/purpur-server/minecraft-patches/sources/net/minecraft/server/network/ServerCommonPacketListenerImpl.java.patch new file mode 100644 index 000000000..baad4a312 --- /dev/null +++ b/purpur-server/minecraft-patches/sources/net/minecraft/server/network/ServerCommonPacketListenerImpl.java.patch @@ -0,0 +1,72 @@ +--- a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java ++++ b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java +@@ -44,6 +_,7 @@ + private long keepAliveChallenge; + private long closedListenerTime; + private boolean closed = false; ++ private it.unimi.dsi.fastutil.longs.LongList keepAlives = new it.unimi.dsi.fastutil.longs.LongArrayList(); // Purpur - Alternative Keepalive Handling + private int latency; + private volatile boolean suspendFlushingOnServerThread = false; + // CraftBukkit start +@@ -53,6 +_,10 @@ + public final java.util.Map packCallbacks = new java.util.concurrent.ConcurrentHashMap<>(); // Paper - adventure resource pack callbacks + private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit + protected static final net.minecraft.resources.Identifier MINECRAFT_BRAND = net.minecraft.resources.Identifier.withDefaultNamespace("brand"); // Paper - Brand support ++ // Purpur start - Purpur client support ++ protected static final net.minecraft.resources.Identifier PURPUR_CLIENT = net.minecraft.resources.Identifier.fromNamespaceAndPath("purpur", "client"); ++ public boolean purpurClient; ++ // Purpur end - Purpur client support + // Paper start - retain certain values + public @Nullable String playerBrand; + public final java.util.Set pluginMessagerChannels; +@@ -100,6 +_,16 @@ + + @Override + public void handleKeepAlive(final ServerboundKeepAlivePacket packet) { ++ // Purpur start - Alternative Keepalive Handling ++ if (org.purpurmc.purpur.PurpurConfig.useAlternateKeepAlive) { ++ if (this.keepAlivePending && !keepAlives.isEmpty() && keepAlives.contains(packet.getId())) { ++ int ping = (int) (Util.getMillis() - packet.getId()); ++ this.latency = (this.latency * 3 + ping) / 4; ++ this.keepAlivePending = false; ++ keepAlives.clear(); // we got a valid response, lets roll with it and forget the rest ++ } ++ } else ++ // Purpur end - Alternative Keepalive Handling + if (this.keepAlivePending && packet.getId() == this.keepAliveChallenge) { + int time = (int)(Util.getMillis() - this.keepAliveTime); + this.latency = (this.latency * 3 + time) / 4; +@@ -149,6 +_,12 @@ + return; + } + ++ // Purpur start - Purpur client support ++ if (identifier.equals(PURPUR_CLIENT)) { ++ this.purpurClient = true; ++ } ++ // Purpur end - Purpur client support ++ + if (identifier.equals(MINECRAFT_BRAND)) { + this.playerBrand = new net.minecraft.network.FriendlyByteBuf(io.netty.buffer.Unpooled.wrappedBuffer(data)).readUtf(256); + } +@@ -236,6 +_,20 @@ + // Paper start - give clients a longer time to respond to pings as per pre 1.12.2 timings + // This should effectively place the keepalive handling back to "as it was" before 1.12.2 + final long elapsedTime = now - this.keepAliveTime; ++ // Purpur start - Alternative Keepalive Handling ++ if (org.purpurmc.purpur.PurpurConfig.useAlternateKeepAlive) { ++ if (elapsedTime >= 1000L) { // 1 second ++ if (this.keepAlivePending && !this.processedDisconnect && keepAlives.size() * 1000L >= KEEPALIVE_LIMIT) { ++ this.disconnect(TIMEOUT_DISCONNECTION_MESSAGE, io.papermc.paper.connection.DisconnectionReason.TIMEOUT); // Paper - kick event cause ++ } else if (this.checkIfClosed(now)) { ++ this.keepAlivePending = true; ++ this.keepAliveTime = now; // hijack this field for 1 second intervals ++ this.keepAlives.add(now); // currentTime is ID ++ this.send(new ClientboundKeepAlivePacket(now)); ++ } ++ } ++ } else ++ // Purpur end - Alternative Keepalive Handling + if (!this.isSingleplayerOwner() && elapsedTime >= 15000L) { // use vanilla's 15000L between keep alive packets + if (this.keepAlivePending) { + if (!this.processedDisconnect && elapsedTime >= KEEPALIVE_LIMIT) { // check keepalive limit, don't fire if already disconnected diff --git a/purpur-server/minecraft-patches/rejected/net/minecraft/world/level/chunk/storage/RegionFileStorage.java.patch b/purpur-server/minecraft-patches/sources/net/minecraft/world/level/chunk/storage/RegionFileStorage.java.patch similarity index 68% rename from purpur-server/minecraft-patches/rejected/net/minecraft/world/level/chunk/storage/RegionFileStorage.java.patch rename to purpur-server/minecraft-patches/sources/net/minecraft/world/level/chunk/storage/RegionFileStorage.java.patch index e716154d3..836d87d64 100644 --- a/purpur-server/minecraft-patches/rejected/net/minecraft/world/level/chunk/storage/RegionFileStorage.java.patch +++ b/purpur-server/minecraft-patches/sources/net/minecraft/world/level/chunk/storage/RegionFileStorage.java.patch @@ -1,14 +1,6 @@ -From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001 -From: File -Date: Sun, 20 Apr 1997 05:37:42 -0800 -Subject: [PATCH] purpur File Patches - - -diff --git a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -index 1e9e061ec694ad64fc2724b83a66dfec7e069a43..e7e71018a4d328832fe44eef595e78265ee720ae 100644 --- a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java +++ b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java -@@ -309,7 +309,7 @@ public class RegionFileStorage implements AutoCloseable, ca.spottedleaf.moonrise +@@ -50,7 +_,7 @@ // Paper start private static void printOversizedLog(String msg, Path file, int x, int z) { diff --git a/purpur-server/minecraft-patches/sources/net/minecraft/world/level/levelgen/PhantomSpawner.java.patch b/purpur-server/minecraft-patches/sources/net/minecraft/world/level/levelgen/PhantomSpawner.java.patch new file mode 100644 index 000000000..454a21b0e --- /dev/null +++ b/purpur-server/minecraft-patches/sources/net/minecraft/world/level/levelgen/PhantomSpawner.java.patch @@ -0,0 +1,28 @@ +--- a/net/minecraft/world/level/levelgen/PhantomSpawner.java ++++ b/net/minecraft/world/level/levelgen/PhantomSpawner.java +@@ -38,13 +_,13 @@ + int spawnAttemptMaxSeconds = level.paperConfig().entities.behavior.phantomsSpawnAttemptMaxSeconds; + this.nextTick += (spawnAttemptMinSeconds + random.nextInt(spawnAttemptMaxSeconds - spawnAttemptMinSeconds + 1)) * 20; + // Paper end - Ability to control player's insomnia and phantoms +- if (level.getSkyDarken() >= 5 || !level.dimensionType().hasSkyLight()) { ++ if (level.getSkyDarken() >= level.purpurConfig.phantomSpawnMinSkyDarkness || !level.dimensionType().hasSkyLight()) { // Purpur - Add phantom spawning options + for (ServerPlayer player : level.players()) { + if (!player.isSpectator() && (!level.paperConfig().entities.behavior.phantomsDoNotSpawnOnCreativePlayers || !player.isCreative())) { // Paper - Add phantom creative and insomniac controls + BlockPos playerPos = player.blockPosition(); +- if (!level.dimensionType().hasSkyLight() || playerPos.getY() >= level.getSeaLevel() && level.canSeeSky(playerPos)) { ++ if (!level.dimensionType().hasSkyLight() || (!level.purpurConfig.phantomSpawnOnlyAboveSeaLevel || playerPos.getY() >= level.getSeaLevel()) && (!level.purpurConfig.phantomSpawnOnlyWithVisibleSky || level.canSeeSky(playerPos))) { // Purpur - Add phantom spawning options + DifficultyInstance difficulty = level.getCurrentDifficultyAt(playerPos); +- if (difficulty.isHarderThan(random.nextFloat() * 3.0F)) { ++ if (difficulty.isHarderThan(random.nextFloat() * (float) level.purpurConfig.phantomSpawnLocalDifficultyChance)) { // Purpur - Add phantom spawning options + ServerStatsCounter stats = player.getStats(); + int value = Mth.clamp(stats.getValue(Stats.CUSTOM.get(Stats.TIME_SINCE_REST)), 1, Integer.MAX_VALUE); + int dayLength = 24000; +@@ -56,7 +_,7 @@ + FluidState fluidState = level.getFluidState(spawnPos); + if (NaturalSpawner.isValidEmptySpawnBlock(level, spawnPos, blockState, fluidState, EntityType.PHANTOM)) { + SpawnGroupData groupData = null; +- int groupSize = 1 + random.nextInt(difficulty.getDifficulty().getId() + 1); ++ int groupSize = level.purpurConfig.phantomSpawnMinPerAttempt + random.nextInt((level.purpurConfig.phantomSpawnMaxPerAttempt < 0 ? difficulty.getDifficulty().getId() : level.purpurConfig.phantomSpawnMaxPerAttempt - level.purpurConfig.phantomSpawnMinPerAttempt) + 1); // Purpur - Add phantom spawning options + + for (int i = 0; i < groupSize; i++) { + // Paper start - PhantomPreSpawnEvent diff --git a/purpur-server/minecraft-patches/rejected/net/minecraft/server/network/ServerCommonPacketListenerImpl.java.patch b/purpur-server/minecraft-patches/unapplied-features/0022-Alternative-Keepalive-Handling-for-Improved-Keepaliv.patch similarity index 68% rename from purpur-server/minecraft-patches/rejected/net/minecraft/server/network/ServerCommonPacketListenerImpl.java.patch rename to purpur-server/minecraft-patches/unapplied-features/0022-Alternative-Keepalive-Handling-for-Improved-Keepaliv.patch index d48c1b440..7da737d57 100644 --- a/purpur-server/minecraft-patches/rejected/net/minecraft/server/network/ServerCommonPacketListenerImpl.java.patch +++ b/purpur-server/minecraft-patches/unapplied-features/0022-Alternative-Keepalive-Handling-for-Improved-Keepaliv.patch @@ -1,7 +1,8 @@ -From 56a0a83ddb1b7472dbc9762e2aca396605c62085 Mon Sep 17 00:00:00 2001 -From: File -Date: Sun, 20 Apr 1997 05:37:42 -0800 -Subject: [PATCH] purpur File Patches +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: granny +Date: Mon, 23 Mar 2026 17:48:11 -0700 +Subject: [PATCH] Alternative Keepalive Handling for Improved Keepalive Ping + System diff --git a/net/minecraft/server/network/ServerCommonPacketListenerImpl.java b/net/minecraft/server/network/ServerCommonPacketListenerImpl.java @@ -21,17 +22,6 @@ index b8a4b4cc02a2fc6b70f4b840796eed501aad6239..02c6733ce1de543dab3bf55814887903 private volatile int latency; // Paper - improve keepalives - make volatile private final io.papermc.paper.util.KeepAlive keepAlive; // Paper - improve keepalives private volatile boolean suspendFlushingOnServerThread = false; -@@ -54,6 +55,10 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack - public final java.util.Map packCallbacks = new java.util.concurrent.ConcurrentHashMap<>(); // Paper - adventure resource pack callbacks - private static final long KEEPALIVE_LIMIT = Long.getLong("paper.playerconnection.keepalive", 30) * 1000; // Paper - provide property to set keepalive limit - protected static final net.minecraft.resources.Identifier MINECRAFT_BRAND = net.minecraft.resources.Identifier.withDefaultNamespace("brand"); // Paper - Brand support -+ // Purpur start - Purpur client support -+ protected static final net.minecraft.resources.Identifier PURPUR_CLIENT = net.minecraft.resources.Identifier.fromNamespaceAndPath("purpur", "client"); -+ public boolean purpurClient; -+ // Purpur end - Purpur client support - // Paper start - retain certain values - public @Nullable String playerBrand; - public final java.util.Set pluginMessagerChannels; @@ -105,6 +110,18 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack // Paper start - improve keepalives long now = System.nanoTime(); @@ -51,19 +41,6 @@ index b8a4b4cc02a2fc6b70f4b840796eed501aad6239..02c6733ce1de543dab3bf55814887903 if (pending != null && pending.challengeId() == packet.getId()) { this.keepAlive.pendingKeepAlives.remove(pending); -@@ -179,6 +196,12 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack - return; - } - -+ // Purpur start - Purpur client support -+ if (identifier.equals(PURPUR_CLIENT)) { -+ this.purpurClient = true; -+ } -+ // Purpur end - Purpur client support -+ - if (identifier.equals(MINECRAFT_BRAND)) { - this.playerBrand = new net.minecraft.network.FriendlyByteBuf(io.netty.buffer.Unpooled.wrappedBuffer(data)).readUtf(256); - } @@ -264,6 +287,23 @@ public abstract class ServerCommonPacketListenerImpl implements ServerCommonPack Profiler.get().push("keepAlive"); long millis = Util.getMillis();