diff --git a/gradle.properties b/gradle.properties index d15a6926b..0201a0288 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ group = org.purpurmc.purpur mcVersion = 26.1.2 apiVersion = 26.1.2 channel=EXPERIMENTAL -paperCommit = 948acae8c27eba00e17a676533772721aec2e3f8 +paperCommit = 7799bf28ae9ba1cbf3b9a23f10f79df5c8e832bc org.gradle.configuration-cache = true org.gradle.caching = true diff --git a/purpur-api/paper-patches/files/src/main/java/org/bukkit/World.java.patch b/purpur-api/paper-patches/files/src/main/java/org/bukkit/World.java.patch index 2cfee824f..039f98091 100644 --- a/purpur-api/paper-patches/files/src/main/java/org/bukkit/World.java.patch +++ b/purpur-api/paper-patches/files/src/main/java/org/bukkit/World.java.patch @@ -1,6 +1,6 @@ --- a/src/main/java/org/bukkit/World.java +++ b/src/main/java/org/bukkit/World.java -@@ -4469,6 +_,100 @@ +@@ -4537,6 +_,100 @@ @Nullable public DragonBattle getEnderDragonBattle(); diff --git a/purpur-server/minecraft-patches/features/0001-Ridables.patch b/purpur-server/minecraft-patches/features/0001-Ridables.patch index 3300ba532..dfde21136 100644 --- a/purpur-server/minecraft-patches/features/0001-Ridables.patch +++ b/purpur-server/minecraft-patches/features/0001-Ridables.patch @@ -18,10 +18,10 @@ index 64a82b414afd093c010878c150592c681665b735..1db70e2397137158c3df9603ea90743e public boolean isClientAuthoritative() { return false; diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 9589fc0621021f900ed62f929b7da69705c91573..0279b1d6456ec271b1fc706a9fb5608de179c383 100644 +index 33915dbc64062bbe8d0d9df6dbdb60660c1ad9c6..07d3c51b80c251da74aba87bdbf9ac74650b83e5 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java -@@ -1862,6 +1862,7 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0; // Paper - BlockPhysicsEvent level.hasEntityMoveEvent = io.papermc.paper.event.entity.EntityMoveEvent.getHandlerList().getRegisteredListeners().length > 0; // Paper - Add EntityMoveEvent @@ -30,10 +30,10 @@ index 9589fc0621021f900ed62f929b7da69705c91573..0279b1d6456ec271b1fc706a9fb5608d 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 profiler.push(() -> level + " " + level.dimension().identifier()); diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java -index 3710e3ff7a65058dd4799459400a5be6bcf19cb8..7898b28dc2ccca20800d989334b625e8a95c935c 100644 +index aa1282fbd44533cbc563fff74d8a1c309f1a9cc0..1072da2fa0138d42769749cc98c6ec0f97fd6f09 100644 --- a/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java -@@ -235,6 +235,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet +@@ -236,6 +236,7 @@ public class ServerLevel extends Level implements WorldGenLevel, ServerEntityGet public boolean hasPhysicsEvent = true; // Paper - BlockPhysicsEvent public boolean hasEntityMoveEvent; // Paper - Add EntityMoveEvent private final alternate.current.wire.WireHandler wireHandler = new alternate.current.wire.WireHandler(this); // Paper - optimize redstone (Alternate Current) @@ -62,10 +62,10 @@ index 3e8a8509c0574e732c8054cc2b86f74dd47d29d4..1bd1bb805060604fbe4dca6d71a863bb private void updatePlayerAttributes() { diff --git a/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -index ae965a1c6663ea9dd9588f010cd7831b51357fb0..8ec1aa8fdd2745d2269d73a9cfbb5f489408b91d 100644 +index abf5fc6b4beed0e3148c319cfa626be9f25d6b09..0069b240b1be6b80a979bfa9784fb4fd634e7440 100644 --- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java -@@ -3008,6 +3008,8 @@ public class ServerGamePacketListenerImpl +@@ -3000,6 +3000,8 @@ public class ServerGamePacketListenerImpl ServerGamePacketListenerImpl.this.cserver.getPluginManager().callEvent(event); final boolean resendData = event.isCancelled() || !ServerGamePacketListenerImpl.this.player.getItemInHand(hand).is(itemType); @@ -75,7 +75,7 @@ index ae965a1c6663ea9dd9588f010cd7831b51357fb0..8ec1aa8fdd2745d2269d73a9cfbb5f48 if (itemType == Items.WATER_BUCKET && target instanceof net.minecraft.world.entity.animal.Bucketable && target instanceof LivingEntity && resendData) { target.resendPossiblyDesyncedEntityData(ServerGamePacketListenerImpl.this.player); // Paper - The entire mob gets deleted, so resend it diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java -index dd99157af3e234b0c2b3a74e964583dea2e5ba36..1ff07b2d360e42a073a6ff0f2a188f320f8376b3 100644 +index 1922a09d57f7f91ef2dec814918fd9da4a9189cd..49c5c8ab8f3333d4d6a96643e7018905a533b645 100644 --- a/net/minecraft/world/entity/Entity.java +++ b/net/minecraft/world/entity/Entity.java @@ -3396,6 +3396,13 @@ public abstract class Entity @@ -107,7 +107,7 @@ index dd99157af3e234b0c2b3a74e964583dea2e5ba36..1ff07b2d360e42a073a6ff0f2a188f32 if (this.passengers.size() == 1 && this.passengers.get(0) == passenger) { this.passengers = ImmutableList.of(); } else { -@@ -5418,4 +5433,44 @@ public abstract class Entity +@@ -5417,4 +5432,44 @@ public abstract class Entity return ((ServerLevel) this.level()).isPositionEntityTicking(this.blockPosition()); } // Paper end - Expose entity id counter @@ -1814,7 +1814,7 @@ index 3d4bfeae2fddb9ace26e7dea8870704d8309862b..ed8fa3aa3d0bb3c83f46a902dfe60394 profiler.pop(); profiler.push("tadpoleActivityUpdate"); diff --git a/net/minecraft/world/entity/animal/goat/Goat.java b/net/minecraft/world/entity/animal/goat/Goat.java -index 6c637f9fb552bc287cdddf976b472bae3915b7b4..d4353bb9ba2168b81726bfaa406175e7f2af601a 100644 +index 3cb1e55e5400c4ab78fd10fc76db38e8d0dac1a0..3116825b324091b0fd769c7293c5514d88cc3cb5 100644 --- a/net/minecraft/world/entity/animal/goat/Goat.java +++ b/net/minecraft/world/entity/animal/goat/Goat.java @@ -100,6 +100,23 @@ public class Goat extends Animal { @@ -2027,7 +2027,7 @@ index 0993ec37f58cbc6b201ebc9aeb39aee438bd1cf9..6875e40687bbde6aba25da7d3145eccd } diff --git a/net/minecraft/world/entity/animal/happyghast/HappyGhast.java b/net/minecraft/world/entity/animal/happyghast/HappyGhast.java -index 413df81578393382a2e6a3aac370d5545d32bd11..f1da6beccfd658d8209dbc3e52f570a476f1c95b 100644 +index a7a9deaf637c2e994940ee8fdad7e5e09464dabe..d7f7bafb7c7854ce6bf64bbbab022fdb85a2e9d7 100644 --- a/net/minecraft/world/entity/animal/happyghast/HappyGhast.java +++ b/net/minecraft/world/entity/animal/happyghast/HappyGhast.java @@ -134,6 +134,13 @@ public class HappyGhast extends Animal { diff --git a/purpur-server/minecraft-patches/features/0003-Barrels-and-enderchests-6-rows.patch b/purpur-server/minecraft-patches/features/0003-Barrels-and-enderchests-6-rows.patch index d2c0d15a2..50577b741 100644 --- a/purpur-server/minecraft-patches/features/0003-Barrels-and-enderchests-6-rows.patch +++ b/purpur-server/minecraft-patches/features/0003-Barrels-and-enderchests-6-rows.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Barrels and enderchests 6 rows diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java -index 962dcadc6615128c2ac28e198955aedec09c9317..1d7a67ce5c33119c4ae794f61a5639a92a9e9dd1 100644 +index 7c0382f7cb42f448e947001542b7f40f11b018e9..341021c3952b89b6e234ce777aa37856eea58ff8 100644 --- a/net/minecraft/server/players/PlayerList.java +++ b/net/minecraft/server/players/PlayerList.java -@@ -889,6 +889,27 @@ public abstract class PlayerList { +@@ -888,6 +888,27 @@ public abstract class PlayerList { player.getBukkitEntity().recalculatePermissions(); // CraftBukkit this.server.getCommands().sendCommands(player); } // Paper - Add sendOpLevel API diff --git a/purpur-server/minecraft-patches/features/0020-Setting-to-reintroduce-end-void-rings.patch b/purpur-server/minecraft-patches/features/0020-Setting-to-reintroduce-end-void-rings.patch index 4cee4e49d..83c124d6d 100644 --- a/purpur-server/minecraft-patches/features/0020-Setting-to-reintroduce-end-void-rings.patch +++ b/purpur-server/minecraft-patches/features/0020-Setting-to-reintroduce-end-void-rings.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Setting to reintroduce end void rings diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 0279b1d6456ec271b1fc706a9fb5608de179c383..a653755f70f5f37b60bdd71f0ef51632cfc00186 100644 +index 07d3c51b80c251da74aba87bdbf9ac74650b83e5..761acf1c9cae98fc8d7699685824f561352a8f66 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java -@@ -1351,6 +1351,15 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop 0L) { final long difference = ticksBehind - catchup; -@@ -1965,7 +_,7 @@ +@@ -1983,7 +_,7 @@ } public String getServerModName() { diff --git a/purpur-server/minecraft-patches/sources/net/minecraft/server/level/ServerLevel.java.patch b/purpur-server/minecraft-patches/sources/net/minecraft/server/level/ServerLevel.java.patch index aec5b71bc..936d898d7 100644 --- a/purpur-server/minecraft-patches/sources/net/minecraft/server/level/ServerLevel.java.patch +++ b/purpur-server/minecraft-patches/sources/net/minecraft/server/level/ServerLevel.java.patch @@ -9,7 +9,7 @@ private final LevelDebugSynchronizers debugSynchronizers = new LevelDebugSynchronizers(this); // CraftBukkit start -@@ -642,8 +_,25 @@ +@@ -643,8 +_,25 @@ // CraftBukkit end this.tickTime = tickTime; this.server = server; @@ -35,8 +35,8 @@ + // Purpur end - Allow toggling special MobSpawners per world ChunkGenerator generator = levelStem.generator(); // CraftBukkit start - if (loadedWorldData.pdc() != null) { -@@ -731,6 +_,7 @@ + // Paper start - per-world time +@@ -738,6 +_,7 @@ this.chunkDataController = new ca.spottedleaf.moonrise.patches.chunk_system.io.datacontroller.ChunkDataController((ServerLevel)(Object)this, this.chunkTaskScheduler); // Paper end - rewrite chunk system this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit @@ -44,16 +44,16 @@ } // Paper start -@@ -787,7 +_,7 @@ +@@ -794,7 +_,7 @@ } int percentage = this.getGameRules().get(GameRules.PLAYERS_SLEEPING_PERCENTAGE); - if (this.sleepStatus.areEnoughSleeping(percentage) && this.sleepStatus.areEnoughDeepSleeping(percentage, this.players)) { + if (this.purpurConfig.playersSkipNight && this.sleepStatus.areEnoughSleeping(percentage) && this.sleepStatus.areEnoughDeepSleeping(percentage, this.players)) { // Purpur - Config for skipping night Optional> defaultClock = this.dimensionType().defaultClock(); - org.bukkit.event.world.TimeSkipEvent event = null; // Paper - time skip event + org.bukkit.event.world.ClockTimeSkipEvent event = null; // Paper - per-world time if (this.getGameRules().get(GameRules.ADVANCE_TIME) && defaultClock.isPresent()) { -@@ -1026,9 +_,18 @@ +@@ -1036,9 +_,18 @@ && this.random.nextDouble() < difficulty.getEffectiveDifficulty() * this.paperConfig().entities.spawning.skeletonHorseThunderSpawnChance.or(0.01) // Paper - Configurable spawn chances for skeleton horses && !this.getBlockState(pos.below()).is(BlockTags.LIGHTNING_RODS); if (isTrap) { @@ -73,7 +73,7 @@ horse.setAge(0); horse.setPos(pos.getX(), pos.getY(), pos.getZ()); this.addFreshEntity(horse, org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason.LIGHTNING); // CraftBukkit -@@ -1063,9 +_,35 @@ +@@ -1073,9 +_,35 @@ if (state.is(Blocks.SNOW)) { int currentLayers = state.getValue(SnowLayerBlock.LAYERS); if (currentLayers < Math.min(maxHeight, 8)) { @@ -109,7 +109,7 @@ } } else { org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this, topPos, Blocks.SNOW.defaultBlockState(), Block.UPDATE_ALL, null); // CraftBukkit -@@ -1086,7 +_,7 @@ +@@ -1096,7 +_,7 @@ p -> p.is(PoiTypes.LIGHTNING_ROD), lightningRodPos -> lightningRodPos.getY() == this.getHeight(Heightmap.Types.WORLD_SURFACE, lightningRodPos.getX(), lightningRodPos.getZ()) - 1, center, @@ -118,7 +118,7 @@ PoiManager.Occupancy.ANY ); return nearbyLightningRod.map(blockPos -> blockPos.above(1)); -@@ -1134,8 +_,26 @@ +@@ -1144,8 +_,26 @@ int percentage = this.getGameRules().get(GameRules.PLAYERS_SLEEPING_PERCENTAGE); Component message; if (this.sleepStatus.areEnoughSleeping(percentage)) { @@ -145,7 +145,7 @@ message = Component.translatable("sleep.players_sleeping", this.sleepStatus.amountSleeping(), this.sleepStatus.sleepersNeeded(percentage)); } -@@ -1301,6 +_,7 @@ +@@ -1311,6 +_,7 @@ public void resetWeatherCycle() { WeatherData weatherData = this.getWeatherData(); // CraftBukkit start @@ -153,7 +153,7 @@ weatherData.setRaining(false, org.bukkit.event.weather.WeatherChangeEvent.Cause.SLEEP); // Paper - Add cause to Weather/ThunderChangeEvents // If we stop due to everyone sleeping we should reset the weather duration to some other random value. // Not that everyone ever manages to get the whole server to sleep at the same time.... -@@ -1308,6 +_,7 @@ +@@ -1318,6 +_,7 @@ weatherData.setRainTime(0); } // CraftBukkit end @@ -161,7 +161,7 @@ weatherData.setThundering(false, org.bukkit.event.weather.ThunderChangeEvent.Cause.SLEEP); // Paper - Add cause to Weather/ThunderChangeEvents // CraftBukkit start // If we stop due to everyone sleeping we should reset the weather duration to some other random value. -@@ -1979,7 +_,7 @@ +@@ -1989,7 +_,7 @@ Explosion.BlockInteraction blockInteraction = switch (interactionType) { case NONE -> Explosion.BlockInteraction.KEEP; case BLOCK -> this.getDestroyType(GameRules.BLOCK_EXPLOSION_DROP_DECAY); @@ -170,7 +170,7 @@ ? this.getDestroyType(GameRules.MOB_EXPLOSION_DROP_DECAY) : Explosion.BlockInteraction.KEEP; case TNT -> this.getDestroyType(GameRules.TNT_EXPLOSION_DROP_DECAY); -@@ -2909,7 +_,7 @@ +@@ -2919,7 +_,7 @@ // Spigot start if (entity.getBukkitEntity() instanceof org.bukkit.inventory.InventoryHolder && (!(entity instanceof ServerPlayer) || entity.getRemovalReason() != Entity.RemovalReason.KILLED)) { // SPIGOT-6876: closeInventory clears death message // Paper start - Fix merchant inventory not closing on entity removal 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 index 84f652be9..47ec3ea15 100644 --- 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 @@ -13,7 +13,7 @@ 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 +_,10 @@ +@@ -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 @@ -24,7 +24,7 @@ // Paper start - retain certain values public @Nullable String playerBrand; public final java.util.Set pluginMessagerChannels; -@@ -105,6 +_,18 @@ +@@ -104,6 +_,18 @@ // Paper start - improve keepalives long now = System.nanoTime(); io.papermc.paper.util.KeepAlive.PendingKeepAlive pending = this.keepAlive.pendingKeepAlives.peek(); @@ -43,7 +43,7 @@ if (pending != null && pending.challengeId() == packet.getId()) { this.keepAlive.pendingKeepAlives.remove(pending); -@@ -179,6 +_,12 @@ +@@ -172,6 +_,12 @@ return; } @@ -56,17 +56,17 @@ if (identifier.equals(MINECRAFT_BRAND)) { this.playerBrand = new net.minecraft.network.FriendlyByteBuf(io.netty.buffer.Unpooled.wrappedBuffer(data)).readUtf(256); } -@@ -264,6 +_,23 @@ +@@ -257,6 +_,23 @@ Profiler.get().push("keepAlive"); long now = Util.getMillis(); // Paper start - improve keepalives + // Purpur start - Alternative Keepalive Handling + if (org.purpurmc.purpur.PurpurConfig.useAlternateKeepAlive) { -+ if (this.checkIfClosed(now) && !this.processedDisconnect) { ++ if (this.checkIfClosed(now)) { + long currTime = System.nanoTime(); + if ((currTime - this.keepAlive.lastKeepAliveTx) >= java.util.concurrent.TimeUnit.SECONDS.toNanos(1L)) { // 1 second + this.keepAlive.lastKeepAliveTx = currTime; -+ if (this.keepAlivePending && !this.processedDisconnect && keepAlives.size() * 1000L >= KEEPALIVE_LIMIT) { ++ if (this.keepAlivePending && keepAlives.size() * 1000L >= KEEPALIVE_LIMIT) { + this.disconnect(TIMEOUT_DISCONNECTION_MESSAGE, io.papermc.paper.connection.DisconnectionReason.TIMEOUT); + } else if (this.checkIfClosed(now)) { + this.keepAlivePending = true; @@ -77,6 +77,6 @@ + } + } else + // Purpur end - Alternative Keepalive Handling - if (this.checkIfClosed(now) && !this.processedDisconnect) { + if (this.checkIfClosed(now)) { long currTime = System.nanoTime(); diff --git a/purpur-server/minecraft-patches/sources/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch b/purpur-server/minecraft-patches/sources/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch index 9b7da1418..fdce417b3 100644 --- a/purpur-server/minecraft-patches/sources/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch +++ b/purpur-server/minecraft-patches/sources/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch @@ -20,8 +20,8 @@ + @Override public void tick() { - if (this.isDisconnected()) return; // Paper -@@ -372,6 +_,12 @@ + if (this.ackBlockChangesUpTo > -1) { +@@ -371,6 +_,12 @@ && this.server.playerIdleTimeout() > 0 && Util.getMillis() - this.player.getLastActionTime() > TimeUnit.MINUTES.toMillis(this.server.playerIdleTimeout()) && !this.player.wonGame) { @@ -34,7 +34,7 @@ this.disconnect(Component.translatable("multiplayer.disconnect.idling"), org.bukkit.event.player.PlayerKickEvent.Cause.IDLING); // Paper - kick event cause } } -@@ -693,6 +_,8 @@ +@@ -692,6 +_,8 @@ this.lastYaw = to.getYaw(); this.lastPitch = to.getPitch(); @@ -43,7 +43,7 @@ Location oldTo = to.clone(); PlayerMoveEvent event = new PlayerMoveEvent(player, from, to); this.cserver.getPluginManager().callEvent(event); -@@ -772,6 +_,7 @@ +@@ -771,6 +_,7 @@ PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level()); if (packet.getId() == this.awaitingTeleport) { if (this.awaitingPositionFromClient == null) { @@ -51,7 +51,7 @@ this.disconnect(Component.translatable("multiplayer.disconnect.invalid_player_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PLAYER_MOVEMENT); // Paper - kick event cause return; } -@@ -1340,6 +_,10 @@ +@@ -1339,6 +_,10 @@ final int maxBookPageSize = pageMax.intValue(); final double multiplier = Math.clamp(io.papermc.paper.configuration.GlobalConfiguration.get().itemValidation.bookSize.totalMultiplier, 0.3D, 1D); long byteAllowed = maxBookPageSize; @@ -62,7 +62,7 @@ for (final String page : pageList) { final int byteLength = page.getBytes(java.nio.charset.StandardCharsets.UTF_8).length; byteTotal += byteLength; -@@ -1364,7 +_,8 @@ +@@ -1363,7 +_,8 @@ } if (byteTotal > byteAllowed) { @@ -72,7 +72,7 @@ this.disconnectAsync(Component.literal("Book too large!"), org.bukkit.event.player.PlayerKickEvent.Cause.ILLEGAL_ACTION); // Paper - kick event cause // Paper - add proper async disconnect return; } -@@ -1383,31 +_,45 @@ +@@ -1382,31 +_,45 @@ Optional title = packet.title(); title.ifPresent(contents::add); contents.addAll(packet.pages()); @@ -122,7 +122,7 @@ writtenBook.set( DataComponents.WRITTEN_BOOK_CONTENT, new WrittenBookContent(this.filterableFromOutgoing(title), this.player.getPlainTextName(), 0, pages, true) ); -@@ -1420,6 +_,16 @@ +@@ -1419,6 +_,16 @@ return this.player.isTextFilteringEnabled() ? Filterable.passThrough(text.filteredOrEmpty()) : Filterable.from(text); } @@ -139,7 +139,7 @@ @Override public void handleEntityTagQuery(final ServerboundEntityTagQueryPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level()); -@@ -1459,7 +_,15 @@ +@@ -1458,7 +_,15 @@ @Override public void handleMovePlayer(final ServerboundMovePlayerPacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level()); @@ -156,7 +156,7 @@ this.disconnect(Component.translatable("multiplayer.disconnect.invalid_player_movement"), org.bukkit.event.player.PlayerKickEvent.Cause.INVALID_PLAYER_MOVEMENT); // Paper - kick event cause } else { ServerLevel level = this.player.level(); -@@ -1644,7 +_,7 @@ +@@ -1643,7 +_,7 @@ movedWrongly = true; if (event.getLogWarning()) // Paper end @@ -165,7 +165,7 @@ } // Paper } -@@ -1709,6 +_,8 @@ +@@ -1708,6 +_,8 @@ this.lastYaw = to.getYaw(); this.lastPitch = to.getPitch(); @@ -174,7 +174,7 @@ Location oldTo = to.clone(); PlayerMoveEvent event = new PlayerMoveEvent(player, from, to); this.cserver.getPluginManager().callEvent(event); -@@ -1764,6 +_,13 @@ +@@ -1763,6 +_,13 @@ this.player.tryResetCurrentImpulseContext(); } @@ -188,7 +188,7 @@ this.player.checkMovementStatistics(this.player.getX() - startX, this.player.getY() - startY, this.player.getZ() - startZ); this.lastGoodX = this.player.getX(); this.lastGoodY = this.player.getY(); -@@ -1784,6 +_,17 @@ +@@ -1783,6 +_,17 @@ } } @@ -206,7 +206,7 @@ private boolean shouldCheckPlayerMovement(final boolean isFallFlying) { if (this.isSingleplayerOwner()) { return false; -@@ -2228,6 +_,7 @@ +@@ -2227,6 +_,7 @@ boolean cancelled; if (hitResult == null || hitResult.getType() != HitResult.Type.BLOCK) { @@ -214,7 +214,7 @@ org.bukkit.event.player.PlayerInteractEvent event = CraftEventFactory.callPlayerInteractEvent(this.player, Action.RIGHT_CLICK_AIR, itemStack, hand); cancelled = event.useItemInHand() == Event.Result.DENY; } else { -@@ -2869,6 +_,7 @@ +@@ -2861,6 +_,7 @@ ItemStack mainHandItem = this.player.getMainHandItem(); if (this.player.isWithinAttackRange(mainHandItem, targetBounds, io.papermc.paper.configuration.GlobalConfiguration.get().misc.clientInteractionLeniencyDistance.or(3.0))) { // Paper - configurable lenience if (!mainHandItem.has(DataComponents.PIERCING_WEAPON)) { @@ -222,12 +222,12 @@ if (target instanceof ItemEntity || target instanceof ExperienceOrb || target == this.player -@@ -3650,7 +_,7 @@ +@@ -3642,7 +_,7 @@ @Override public void handleChangeGameMode(final ServerboundChangeGameModePacket packet) { PacketUtils.ensureRunningOnSameThread(packet, this, this.player.level()); -- if (!GameModeCommand.PERMISSION_CHECK.check(this.player.permissions())) { -+ if (!GameModeCommand.PERMISSION_CHECK.check(this.player.permissions()) && !player.getBukkitEntity().hasPermission("purpur.debug.f3n")) { // Purpur - Add permission for F3+N debug +- if (!GameModeCommand.PERMISSION_CHECK.check(this.player.permissions()) && !this.player.getBukkitEntity().hasPermission("minecraft.command.gamemode")) { // Paper - add permission check ++ if (!GameModeCommand.PERMISSION_CHECK.check(this.player.permissions()) && !this.player.getBukkitEntity().hasPermission("minecraft.command.gamemode") && !player.getBukkitEntity().hasPermission("purpur.debug.f3n")) { // Paper - add permission check // Purpur - Add permission for F3+N debug LOGGER.warn( "Player {} tried to change game mode to {} without required permissions", this.player.getGameProfile().name(), diff --git a/purpur-server/minecraft-patches/sources/net/minecraft/server/network/ServerLoginPacketListenerImpl.java.patch b/purpur-server/minecraft-patches/sources/net/minecraft/server/network/ServerLoginPacketListenerImpl.java.patch index eeac5045e..e49f416b7 100644 --- a/purpur-server/minecraft-patches/sources/net/minecraft/server/network/ServerLoginPacketListenerImpl.java.patch +++ b/purpur-server/minecraft-patches/sources/net/minecraft/server/network/ServerLoginPacketListenerImpl.java.patch @@ -1,6 +1,6 @@ --- a/net/minecraft/server/network/ServerLoginPacketListenerImpl.java +++ b/net/minecraft/server/network/ServerLoginPacketListenerImpl.java -@@ -282,7 +_,7 @@ +@@ -290,7 +_,7 @@ ServerLoginPacketListenerImpl.LOGGER.warn("Failed to verify username but will let them in anyway!"); ServerLoginPacketListenerImpl.this.startClientVerification(ServerLoginPacketListenerImpl.this.createOfflineProfile(name)); // Spigot } else { diff --git a/purpur-server/minecraft-patches/sources/net/minecraft/server/players/PlayerList.java.patch b/purpur-server/minecraft-patches/sources/net/minecraft/server/players/PlayerList.java.patch index 6c01a51bd..c8d3b39b1 100644 --- a/purpur-server/minecraft-patches/sources/net/minecraft/server/players/PlayerList.java.patch +++ b/purpur-server/minecraft-patches/sources/net/minecraft/server/players/PlayerList.java.patch @@ -16,7 +16,7 @@ ServerLevel level = player.level(); player.awardStat(Stats.LEAVE_GAME); // CraftBukkit start - Quitting must be before we do final save of data, in case plugins need to modify it -@@ -772,6 +_,20 @@ +@@ -771,6 +_,20 @@ } } @@ -37,7 +37,7 @@ public void broadcastAll(final Packet packet, final ResourceKey dimension) { for (ServerPlayer player : this.players) { if (player.level().dimension() == dimension) { -@@ -865,6 +_,7 @@ +@@ -864,6 +_,7 @@ case ADMINS -> EntityEvent.PERMISSION_LEVEL_ADMINS; case OWNERS -> EntityEvent.PERMISSION_LEVEL_OWNERS; }; @@ -45,7 +45,7 @@ player.connection.send(new ClientboundEntityEventPacket(player, eventId)); } -@@ -876,7 +_,7 @@ +@@ -875,7 +_,7 @@ // Paper start - whitelist verify event / login event public LoginResult canBypassFullServerLogin(final NameAndId nameAndId, final LoginResult currentResult) { diff --git a/purpur-server/minecraft-patches/sources/net/minecraft/world/clock/ServerClockManager.java.patch b/purpur-server/minecraft-patches/sources/net/minecraft/world/clock/ServerClockManager.java.patch index 215f1d018..17784c292 100644 --- a/purpur-server/minecraft-patches/sources/net/minecraft/world/clock/ServerClockManager.java.patch +++ b/purpur-server/minecraft-patches/sources/net/minecraft/world/clock/ServerClockManager.java.patch @@ -1,20 +1,17 @@ --- a/net/minecraft/world/clock/ServerClockManager.java +++ b/net/minecraft/world/clock/ServerClockManager.java -@@ -122,7 +_,7 @@ - ServerClockManager.ClockInstance instance = this.getInstance(clock); - action.accept(instance); - Map, ClockNetworkState> updates = Map.of(clock, instance.packNetworkState(this.server)); -- this.server.getPlayerList().broadcastAll(new ClientboundSetTimePacket(this.getGameTime(), updates)); // TODO 26.1 per-player time -+ this.server.getPlayerList().broadcastAll(new ClientboundSetTimePacket(this.getGameTime(), updates)); // TODO 26.1 per-player time // Purpur - TODO: Configurable daylight cycle - this.setDirty(); - - for (ServerLevel level : this.server.getAllLevels()) { -@@ -151,7 +_,7 @@ - // Paper end +@@ -149,12 +_,12 @@ public ClientboundSetTimePacket createFullSyncPacket() { -- // TODO - snapshot: 26.1 per-player time -+ // TODO - snapshot: 26.1 per-player time // Purpur - TODO: Configurable daylight cycle - return new ClientboundSetTimePacket(this.getGameTime(), Util.mapValues(this.clocks, clock -> clock.packNetworkState(this.server))); + // Paper start - per-player time +- return this.createFullSyncPacket(null); ++ return this.createFullSyncPacket(null); // Purpur - TODO: Configurable daylight cycle } + public ClientboundSetTimePacket createFullSyncPacket(final net.minecraft.server.level.ServerPlayer player) { + final Map, ClockNetworkState> updates = new HashMap<>(this.clocks.size()); +- this.clocks.forEach((clock, instance) -> updates.put(clock, this.packNetworkState(clock, instance, player))); ++ this.clocks.forEach((clock, instance) -> updates.put(clock, this.packNetworkState(clock, instance, player))); // Purpur - TODO: Configurable daylight cycle + return new ClientboundSetTimePacket(this.getGameTime(), updates); + // Paper end - per-player time + } diff --git a/purpur-server/minecraft-patches/sources/net/minecraft/world/damagesource/CombatTracker.java.patch b/purpur-server/minecraft-patches/sources/net/minecraft/world/damagesource/CombatTracker.java.patch index 049de4313..5c43c62f7 100644 --- a/purpur-server/minecraft-patches/sources/net/minecraft/world/damagesource/CombatTracker.java.patch +++ b/purpur-server/minecraft-patches/sources/net/minecraft/world/damagesource/CombatTracker.java.patch @@ -1,6 +1,6 @@ --- a/net/minecraft/world/damagesource/CombatTracker.java +++ b/net/minecraft/world/damagesource/CombatTracker.java -@@ -66,7 +_,7 @@ +@@ -75,7 +_,7 @@ final Entity attackerEntity, final Component attackerName, final String messageWithItem, final String messageWithoutItem ) { ItemStack attackerItem = attackerEntity instanceof LivingEntity livingEntity ? livingEntity.getMainHandItem() : ItemStack.EMPTY; @@ -9,7 +9,7 @@ ? Component.translatable(messageWithItem, this.mob.getDisplayName(), attackerName, attackerItem.getDisplayName()) : Component.translatable(messageWithoutItem, this.mob.getDisplayName(), attackerName); } -@@ -109,6 +_,15 @@ +@@ -118,6 +_,15 @@ Component link = ComponentUtils.wrapInSquareBrackets(Component.translatable(deathMsg + ".link")).withStyle(INTENTIONAL_GAME_DESIGN_STYLE); return Component.translatable(deathMsg + ".message", this.mob.getDisplayName(), link); } else { diff --git a/purpur-server/minecraft-patches/sources/net/minecraft/world/entity/Entity.java.patch b/purpur-server/minecraft-patches/sources/net/minecraft/world/entity/Entity.java.patch index bcc91466c..af00a8519 100644 --- a/purpur-server/minecraft-patches/sources/net/minecraft/world/entity/Entity.java.patch +++ b/purpur-server/minecraft-patches/sources/net/minecraft/world/entity/Entity.java.patch @@ -137,7 +137,7 @@ } } } -@@ -4237,7 +_,7 @@ +@@ -4236,7 +_,7 @@ } public boolean canUsePortal(final boolean ignorePassenger) { @@ -146,7 +146,7 @@ } public boolean canTeleport(final Level from, final Level to) { -@@ -4787,6 +_,12 @@ +@@ -4786,6 +_,12 @@ return Mth.lerp(partial, this.yRotO, this.yRot); } @@ -159,7 +159,7 @@ public boolean touchingUnloadedChunk() { AABB box = this.getBoundingBox().inflate(1.0); int x0 = Mth.floor(box.minX); -@@ -5090,7 +_,7 @@ +@@ -5089,7 +_,7 @@ } public float maxUpStep() { diff --git a/purpur-server/minecraft-patches/sources/net/minecraft/world/entity/animal/goat/Goat.java.patch b/purpur-server/minecraft-patches/sources/net/minecraft/world/entity/animal/goat/Goat.java.patch index e89bce186..8661d8521 100644 --- a/purpur-server/minecraft-patches/sources/net/minecraft/world/entity/animal/goat/Goat.java.patch +++ b/purpur-server/minecraft-patches/sources/net/minecraft/world/entity/animal/goat/Goat.java.patch @@ -1,6 +1,6 @@ --- a/net/minecraft/world/entity/animal/goat/Goat.java +++ b/net/minecraft/world/entity/animal/goat/Goat.java -@@ -363,6 +_,7 @@ +@@ -362,6 +_,7 @@ // Paper start - Goat ram API public void ram(net.minecraft.world.entity.LivingEntity entity) { diff --git a/purpur-server/minecraft-patches/sources/net/minecraft/world/level/Level.java.patch b/purpur-server/minecraft-patches/sources/net/minecraft/world/level/Level.java.patch index f67f7e8b9..dc2f672c0 100644 --- a/purpur-server/minecraft-patches/sources/net/minecraft/world/level/Level.java.patch +++ b/purpur-server/minecraft-patches/sources/net/minecraft/world/level/Level.java.patch @@ -55,16 +55,16 @@ public CraftWorld getWorld() { return this.world; } -@@ -851,6 +_,8 @@ - // Paper end - getblock optimisations - cache world height/sections - this.spigotConfig = new org.spigotmc.SpigotWorldConfig(bukkitName, CraftNamespacedKey.fromMinecraft(dimension.identifier())); // Spigot +@@ -852,6 +_,8 @@ + final org.bukkit.NamespacedKey worldKey = CraftNamespacedKey.fromMinecraft(dimension.identifier()); // Paper + this.spigotConfig = new org.spigotmc.SpigotWorldConfig(bukkitName, worldKey); // Spigot this.paperConfig = paperWorldConfigCreator.apply(this.spigotConfig); // Paper - create paper world config -+ this.purpurConfig = new org.purpurmc.purpur.PurpurWorldConfig(bukkitName, environment, CraftNamespacedKey.fromMinecraft(dimension.identifier())); // Purpur - Purpur config files ++ this.purpurConfig = new org.purpurmc.purpur.PurpurWorldConfig(bukkitName, environment, worldKey); // Purpur - Purpur config files + this.playerBreedingCooldowns = this.getNewBreedingCooldownCache(); // Purpur - Add adjustable breeding cooldown to config this.generator = generator; - this.world = new CraftWorld((ServerLevel) this, generator, biomeProvider, environment); + this.world = new CraftWorld((ServerLevel) this, worldKey, biomeProvider, environment); -@@ -2193,4 +_,14 @@ +@@ -2194,4 +_,14 @@ return this.moonrise$getEntityLookup().getEntityCount(); // Paper - rewrite chunk system } // Paper end - allow patching this logic diff --git a/purpur-server/paper-patches/features/0002-Ridables.patch b/purpur-server/paper-patches/features/0002-Ridables.patch index 1cd13f034..59c16429a 100644 --- a/purpur-server/paper-patches/features/0002-Ridables.patch +++ b/purpur-server/paper-patches/features/0002-Ridables.patch @@ -36,10 +36,10 @@ index c5a866735d7d918ea58306ea2299a8b82be52f3f..d6ddbcff911ce4c97a20883af10d2b47 + // Purpur end - Ridables } diff --git a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -index 6d485bb4d91668070c28c3fe1dc2c4708760d924..631b8186f89e133936f9a55957fc3215e53184d1 100644 +index 7a42d1810f74a041318c8a3c53793106e872081f..6c4045b842a23caa2f3f1e52cb0130a97ffc2682 100644 --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java -@@ -649,6 +649,15 @@ public class CraftEventFactory { +@@ -652,6 +652,15 @@ public class CraftEventFactory { } craftServer.getPluginManager().callEvent(event); @@ -55,7 +55,7 @@ index 6d485bb4d91668070c28c3fe1dc2c4708760d924..631b8186f89e133936f9a55957fc3215 return event; } -@@ -1161,6 +1170,7 @@ public class CraftEventFactory { +@@ -1164,6 +1173,7 @@ public class CraftEventFactory { EntityDamageEvent event; if (damager != null) { event = new EntityDamageByEntityEvent(damager.getBukkitEntity(), damagee.getBukkitEntity(), cause, bukkitDamageSource, modifiers, modifierFunctions, critical); diff --git a/purpur-server/paper-patches/features/0004-API-for-any-mob-to-burn-daylight.patch b/purpur-server/paper-patches/features/0004-API-for-any-mob-to-burn-daylight.patch index 324d235f4..86fe58233 100644 --- a/purpur-server/paper-patches/features/0004-API-for-any-mob-to-burn-daylight.patch +++ b/purpur-server/paper-patches/features/0004-API-for-any-mob-to-burn-daylight.patch @@ -24,10 +24,10 @@ index d6ddbcff911ce4c97a20883af10d2b4752b63f55..7db0454a8c9251faa815500c307d116b Preconditions.checkArgument(entity != null, "Unknown entity"); diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -index 18709cf2d7d69dc8f4313eca0c0358f60f58b16b..fe9d7ecfec87a8914edb32561210ced95b599a7b 100644 +index ca447f1e2840d13217559dc1028dbea63fb05041..983146dc8b685fd0ce906ee8debc2e11df9d9fdc 100644 --- a/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java +++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftLivingEntity.java -@@ -1133,4 +1133,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { +@@ -1141,4 +1141,16 @@ public class CraftLivingEntity extends CraftEntity implements LivingEntity { manager.untrackWaypoint(getHandle()); manager.trackWaypoint(getHandle()); } diff --git a/purpur-server/paper-patches/features/0005-Setting-to-reintroduce-end-void-rings.patch b/purpur-server/paper-patches/features/0005-Setting-to-reintroduce-end-void-rings.patch index 0c780999d..ad122bb29 100644 --- a/purpur-server/paper-patches/features/0005-Setting-to-reintroduce-end-void-rings.patch +++ b/purpur-server/paper-patches/features/0005-Setting-to-reintroduce-end-void-rings.patch @@ -5,10 +5,10 @@ Subject: [PATCH] Setting to reintroduce end void rings diff --git a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java -index 569b46cce9d5207380a9391e969e3a6aa790717b..a0cf70f1ccbb78f058e8ac5fc95bcb5b03300cdc 100644 +index 232bc5e8b7cbb528b96f8048ba683705cddc436e..7d2b38ecf1478c9e53d033f41c4184864c8d32e4 100644 --- a/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java +++ b/src/main/java/io/papermc/paper/configuration/GlobalConfiguration.java -@@ -288,6 +288,7 @@ public class GlobalConfiguration extends ConfigurationPart { +@@ -292,6 +292,7 @@ public class GlobalConfiguration extends ConfigurationPart { } } @@ -16,19 +16,19 @@ index 569b46cce9d5207380a9391e969e3a6aa790717b..a0cf70f1ccbb78f058e8ac5fc95bcb5b public Misc misc; public class Misc extends ConfigurationPart { -@@ -334,6 +335,7 @@ public class GlobalConfiguration extends ConfigurationPart { +@@ -338,6 +339,7 @@ public class GlobalConfiguration extends ConfigurationPart { @Comment("Whether the nether dimension is enabled and will be loaded.") public boolean enableNether = true; @Comment("Keeps Paper's fix for MC-159283 enabled. Disable to use vanilla End ring terrain.") + @Setting(org.purpurmc.purpur.configuration.transformation.FarEndTerrainGenerationMigration.FIX_FAR_END_TERRAIN_GENERATION_KEY) // Purpur - Migrate Setting to reintroduce end void rings public boolean fixFarEndTerrainGeneration = true; - } - + @Comment("Fix for MC-301114. This removes the oldest combat entry when it hits the cap, to fix a memory leak on constant entity damage.") + public IntOr.Disabled maxTrackingCombatEntries = new IntOr.Disabled(OptionalInt.of(10240)); diff --git a/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java b/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java -index 1ab7f28e2ba386c68b9c70617c816b0b55fd796d..1446423550b6637aa955a1fa079f6c5d222093df 100644 +index aa5ff7fb46b068fcb27abfdcb81f10220c5d1e89..cb9b2b6878e8ca9e3baba341550a860176271013 100644 --- a/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java +++ b/src/main/java/io/papermc/paper/configuration/PaperConfigurations.java -@@ -293,6 +293,7 @@ public class PaperConfigurations extends Configurations