From 61a04c8ef87db8d0166bd1750e5c323ca0f033d6 Mon Sep 17 00:00:00 2001 From: david Date: Thu, 24 Apr 2025 16:55:10 +0200 Subject: [PATCH 01/13] call WorldDifficultyChangeEvent --- .../src/main/java/org/bukkit/craftbukkit/CraftWorld.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java index 4a405744061b..76ad9641b475 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -1288,7 +1288,7 @@ public void setAutoSave(boolean value) { @Override public void setDifficulty(Difficulty difficulty) { - this.getHandle().getServer().setDifficulty(this.getHandle(), net.minecraft.world.Difficulty.byId(difficulty.getValue()), true); // Paper - per level difficulty; don't skip other difficulty-changing logic + this.getHandle().getServer().setDifficulty(this.getHandle(), net.minecraft.world.Difficulty.byId(difficulty.getValue()), null, true); // Paper - per level difficulty; don't skip other difficulty-changing logic; WorldDifficultyChangeEvent } @Override From 73f2020855854d65ebecf6063ca633d663072614 Mon Sep 17 00:00:00 2001 From: david Date: Thu, 24 Apr 2025 16:29:41 +0200 Subject: [PATCH 02/13] add difficulty change event --- .../world/WorldDifficultyChangeEvent.java | 75 +++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 paper-api/src/main/java/io/papermc/paper/event/world/WorldDifficultyChangeEvent.java diff --git a/paper-api/src/main/java/io/papermc/paper/event/world/WorldDifficultyChangeEvent.java b/paper-api/src/main/java/io/papermc/paper/event/world/WorldDifficultyChangeEvent.java new file mode 100644 index 000000000000..24bb2e4c2673 --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/event/world/WorldDifficultyChangeEvent.java @@ -0,0 +1,75 @@ +package io.papermc.paper.event.world; + +import org.bukkit.Difficulty; +import org.bukkit.World; +import org.bukkit.command.CommandSender; +import org.bukkit.event.Cancellable; +import org.bukkit.event.HandlerList; +import org.bukkit.event.world.WorldEvent; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; + +/** + * Called when a world's difficulty is changed, either by command or by api. + */ +@NullMarked +public class WorldDifficultyChangeEvent extends WorldEvent implements Cancellable { + + private static final HandlerList HANDLER_LIST = new HandlerList(); + + private final @Nullable CommandSender commandSender; + private Difficulty difficulty; + private boolean cancelled; + + public WorldDifficultyChangeEvent(final World world, final @Nullable CommandSender commandSender, final Difficulty difficulty) { + super(world); + this.commandSender = commandSender; + this.difficulty = difficulty; + } + + /** + * Gets the command sender associated with this event. + * + * @return {@code null} if the difficulty was changed via api, otherwise the {@link CommandSender}. + */ + public @Nullable CommandSender getCommandSender() { + return commandSender; + } + + /** + * Gets the new difficulty of the world. + * + * @return the new difficulty. + */ + public Difficulty getDifficulty() { + return difficulty; + } + + /** + * Set the new difficulty of the world. + * + * @param difficulty the new difficulty. + */ + public void setDifficulty(final Difficulty difficulty) { + this.difficulty = difficulty; + } + + @Override + public boolean isCancelled() { + return this.cancelled; + } + + @Override + public void setCancelled(final boolean cancel) { + this.cancelled = cancel; + } + + @Override + public HandlerList getHandlers() { + return HANDLER_LIST; + } + + public static HandlerList getHandlerList() { + return HANDLER_LIST; + } +} From 2e39f47c0af5d6591aea97d38264b4eb40b4bc7a Mon Sep 17 00:00:00 2001 From: david Date: Thu, 24 Apr 2025 19:28:55 +0200 Subject: [PATCH 03/13] add file patches --- .../0015-Moonrise-optimisation-patches.patch | 10 +++---- ...er-desync-when-new-players-are-added.patch | 8 ++--- .../server/MinecraftServer.java.patch | 30 ++++++++++++++++--- .../commands/DifficultyCommand.java.patch | 2 +- 4 files changed, 36 insertions(+), 14 deletions(-) diff --git a/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch b/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch index 10729a44c7c4..6cdec382bfe4 100644 --- a/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch +++ b/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch @@ -23750,7 +23750,7 @@ index 58be6e1d1607a3af5e28f851718b82321f2feb25..9c9b601a3f903bebb0dd1bda0e247455 thread1 -> { DedicatedServer dedicatedServer1 = new DedicatedServer( diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 91df2a420eeab1bab508b95f0029fae7adb51c58..094ef7f54ad71795a2d8c2a8d03a32bef6ff2164 100644 +index 4e9edb13c61eb5f7c99c5f2ae0ae7a2718f31d9c..1d4b4c9a374605457bf80edb9e3bb8e949e91988 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java @@ -172,7 +172,7 @@ import net.minecraft.world.phys.Vec2; @@ -23942,7 +23942,7 @@ index 91df2a420eeab1bab508b95f0029fae7adb51c58..094ef7f54ad71795a2d8c2a8d03a32be return true; } else { boolean ret = false; // Paper - force execution of all worlds, do not just bias the first -@@ -2466,6 +2554,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop list = this.mountedOrDismounted(passengers).map(Entity::getUUID).toList(); diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java -index fe9b4484d683fe48f435a053c9c90557fdf80e7b..8afe96bfdc37e57129f1bb4af5b6d5cc22c11aee 100644 +index 085040aa98704f2874bcd95b751b0a81dcdb15ad..cd72273468f596b640bd2d10d846fbe8813846a6 100644 --- a/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java @@ -166,7 +166,7 @@ import net.minecraft.world.phys.shapes.VoxelShape; @@ -27565,7 +27565,7 @@ index fe9b4484d683fe48f435a053c9c90557fdf80e7b..8afe96bfdc37e57129f1bb4af5b6d5cc } diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java -index a8c73bdf8fb130eed8922cb537a35cda07e66da5..3e73c69c9db8cbded28a001b20d9989acb11c638 100644 +index a11591ea5e8aa1861d202db49ab200d814308c6d..31032beb40105b287e51206de2f68c9a070e8bdd 100644 --- a/net/minecraft/server/level/ServerPlayer.java +++ b/net/minecraft/server/level/ServerPlayer.java @@ -187,7 +187,7 @@ import net.minecraft.world.scores.Team; diff --git a/paper-server/patches/features/0016-Fix-entity-tracker-desync-when-new-players-are-added.patch b/paper-server/patches/features/0016-Fix-entity-tracker-desync-when-new-players-are-added.patch index 9e490b8a73af..4a6adb3c0a11 100644 --- a/paper-server/patches/features/0016-Fix-entity-tracker-desync-when-new-players-are-added.patch +++ b/paper-server/patches/features/0016-Fix-entity-tracker-desync-when-new-players-are-added.patch @@ -60,7 +60,7 @@ index 1463c31ba980ab0eb2174e3e891d1423a505e9dc..886340232b58afd59caa6df29e211589 } else if (this.seenBy.remove(player.connection)) { this.serverEntity.removePairing(player); diff --git a/net/minecraft/server/level/ServerEntity.java b/net/minecraft/server/level/ServerEntity.java -index 0005a1784ccaa00e5d6d67e7be98445150487982..257ecbcf7d463eefb951867a5426eaf24e356305 100644 +index a1ae77b70f69852d9e4332bf1cb3409c33b21de0..b118e91f1e0b5a8b8c0b2a4a32faabc5a34a5954 100644 --- a/net/minecraft/server/level/ServerEntity.java +++ b/net/minecraft/server/level/ServerEntity.java @@ -103,6 +103,13 @@ public class ServerEntity { @@ -77,7 +77,7 @@ index 0005a1784ccaa00e5d6d67e7be98445150487982..257ecbcf7d463eefb951867a5426eaf2 public void sendChanges() { // Paper start - optimise collisions if (((ca.spottedleaf.moonrise.patches.chunk_system.entity.ChunkSystemEntity)this.entity).moonrise$isHardColliding()) { -@@ -136,7 +143,7 @@ public class ServerEntity { +@@ -141,7 +148,7 @@ public class ServerEntity { this.sendDirtyEntityData(); } @@ -86,7 +86,7 @@ index 0005a1784ccaa00e5d6d67e7be98445150487982..257ecbcf7d463eefb951867a5426eaf2 byte b = Mth.packDegrees(this.entity.getYRot()); byte b1 = Mth.packDegrees(this.entity.getXRot()); boolean flag = Math.abs(b - this.lastSentYRot) >= 1 || Math.abs(b1 - this.lastSentXRot) >= 1; -@@ -171,7 +178,7 @@ public class ServerEntity { +@@ -176,7 +183,7 @@ public class ServerEntity { long l1 = this.positionCodec.encodeY(vec3); long l2 = this.positionCodec.encodeZ(vec3); boolean flag5 = l < -32768L || l > 32767L || l1 < -32768L || l1 > 32767L || l2 < -32768L || l2 > 32767L; @@ -95,7 +95,7 @@ index 0005a1784ccaa00e5d6d67e7be98445150487982..257ecbcf7d463eefb951867a5426eaf2 this.wasOnGround = this.entity.onGround(); this.teleportDelay = 0; packet = ClientboundEntityPositionSyncPacket.of(this.entity); -@@ -236,6 +243,7 @@ public class ServerEntity { +@@ -241,6 +248,7 @@ public class ServerEntity { } this.entity.hasImpulse = false; diff --git a/paper-server/patches/sources/net/minecraft/server/MinecraftServer.java.patch b/paper-server/patches/sources/net/minecraft/server/MinecraftServer.java.patch index f7c930147ac2..970589a8001e 100644 --- a/paper-server/patches/sources/net/minecraft/server/MinecraftServer.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/MinecraftServer.java.patch @@ -1101,7 +1101,7 @@ } public KeyPair getKeyPair() { -@@ -1243,11 +_,14 @@ +@@ -1243,11 +_,36 @@ } } @@ -1110,11 +1110,33 @@ - this.worldData.setDifficulty(this.worldData.isHardcore() ? Difficulty.HARD : difficulty); - this.updateMobSpawningFlags(); - this.getPlayerList().getPlayers().forEach(this::sendDifficultyUpdate); -+ // Paper start - per level difficulty -+ public void setDifficulty(ServerLevel level, Difficulty difficulty, boolean forced) { ++ // Paper start - per level difficulty, WorldDifficultyChangeEvent ++ private static org.bukkit.Difficulty toBukkit(Difficulty difficulty) { ++ return switch (difficulty) { ++ case EASY -> org.bukkit.Difficulty.EASY; ++ case HARD -> org.bukkit.Difficulty.HARD; ++ case NORMAL -> org.bukkit.Difficulty.NORMAL; ++ case PEACEFUL -> org.bukkit.Difficulty.PEACEFUL; ++ }; ++ } ++ ++ private static Difficulty fromBukkit(org.bukkit.Difficulty difficulty) { ++ return switch (difficulty) { ++ case EASY -> Difficulty.EASY; ++ case HARD -> Difficulty.HARD; ++ case NORMAL -> Difficulty.NORMAL; ++ case PEACEFUL -> Difficulty.PEACEFUL; ++ }; ++ } ++ ++ public void setDifficulty(ServerLevel level, Difficulty difficulty, @Nullable CommandSourceStack source, boolean forced) { + net.minecraft.world.level.storage.PrimaryLevelData worldData = level.serverLevelData; + if (forced || !worldData.isDifficultyLocked()) { -+ worldData.setDifficulty(worldData.isHardcore() ? Difficulty.HARD : difficulty); ++ io.papermc.paper.event.world.WorldDifficultyChangeEvent event = new io.papermc.paper.event.world.WorldDifficultyChangeEvent( ++ level.getWorld(), source != null ? source.getBukkitSender() : null, toBukkit(difficulty) ++ ); ++ if (!event.callEvent()) return; ++ worldData.setDifficulty(worldData.isHardcore() ? Difficulty.HARD : fromBukkit(event.getDifficulty())); + level.setSpawnSettings(worldData.getDifficulty() != Difficulty.PEACEFUL && ((net.minecraft.server.dedicated.DedicatedServer) this).settings.getProperties().spawnMonsters); + // this.getPlayerList().getPlayers().forEach(this::sendDifficultyUpdate); + // Paper end - per level difficulty diff --git a/paper-server/patches/sources/net/minecraft/server/commands/DifficultyCommand.java.patch b/paper-server/patches/sources/net/minecraft/server/commands/DifficultyCommand.java.patch index 5206cb78a7c8..bacdafe0105a 100644 --- a/paper-server/patches/sources/net/minecraft/server/commands/DifficultyCommand.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/commands/DifficultyCommand.java.patch @@ -9,7 +9,7 @@ throw ERROR_ALREADY_DIFFICULT.create(difficulty.getKey()); } else { - server.setDifficulty(difficulty, true); -+ server.setDifficulty(source.getLevel(), difficulty, true); // Paper - per level difficulty; don't skip other difficulty-changing logic (fix upstream's fix) ++ server.setDifficulty(source.getLevel(), difficulty, source, true); // Paper - per level difficulty; don't skip other difficulty-changing logic (fix upstream's fix); WorldDifficultyChangeEvent source.sendSuccess(() -> Component.translatable("commands.difficulty.success", difficulty.getDisplayName()), true); return 0; } From 42e6e6aa7b3c0af76ad1dcbb8c1f76ed177228e4 Mon Sep 17 00:00:00 2001 From: david Date: Thu, 24 Apr 2025 19:48:36 +0200 Subject: [PATCH 04/13] move utility methods to CraftWorld --- .../0015-Moonrise-optimisation-patches.patch | 4 ++-- .../server/MinecraftServer.java.patch | 24 +++---------------- .../org/bukkit/craftbukkit/CraftWorld.java | 22 +++++++++++++++-- 3 files changed, 25 insertions(+), 25 deletions(-) diff --git a/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch b/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch index 6cdec382bfe4..204a38027b2f 100644 --- a/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch +++ b/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch @@ -23750,7 +23750,7 @@ index 58be6e1d1607a3af5e28f851718b82321f2feb25..9c9b601a3f903bebb0dd1bda0e247455 thread1 -> { DedicatedServer dedicatedServer1 = new DedicatedServer( diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 4e9edb13c61eb5f7c99c5f2ae0ae7a2718f31d9c..1d4b4c9a374605457bf80edb9e3bb8e949e91988 100644 +index 02ac6e0a5831308a123492fbeaf43e3fa30d99c1..d5e2670ac13734f617f4667f4ff0756d2089a79b 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java @@ -172,7 +172,7 @@ import net.minecraft.world.phys.Vec2; @@ -23942,7 +23942,7 @@ index 4e9edb13c61eb5f7c99c5f2ae0ae7a2718f31d9c..1d4b4c9a374605457bf80edb9e3bb8e9 return true; } else { boolean ret = false; // Paper - force execution of all worlds, do not just bias the first -@@ -2488,6 +2576,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop org.bukkit.Difficulty.EASY; -+ case HARD -> org.bukkit.Difficulty.HARD; -+ case NORMAL -> org.bukkit.Difficulty.NORMAL; -+ case PEACEFUL -> org.bukkit.Difficulty.PEACEFUL; -+ }; -+ } -+ -+ private static Difficulty fromBukkit(org.bukkit.Difficulty difficulty) { -+ return switch (difficulty) { -+ case EASY -> Difficulty.EASY; -+ case HARD -> Difficulty.HARD; -+ case NORMAL -> Difficulty.NORMAL; -+ case PEACEFUL -> Difficulty.PEACEFUL; -+ }; -+ } -+ + public void setDifficulty(ServerLevel level, Difficulty difficulty, @Nullable CommandSourceStack source, boolean forced) { + net.minecraft.world.level.storage.PrimaryLevelData worldData = level.serverLevelData; + if (forced || !worldData.isDifficultyLocked()) { + io.papermc.paper.event.world.WorldDifficultyChangeEvent event = new io.papermc.paper.event.world.WorldDifficultyChangeEvent( -+ level.getWorld(), source != null ? source.getBukkitSender() : null, toBukkit(difficulty) ++ level.getWorld(), source != null ? source.getBukkitSender() : null, org.bukkit.craftbukkit.CraftWorld.toBukkit(difficulty) + ); + if (!event.callEvent()) return; -+ worldData.setDifficulty(worldData.isHardcore() ? Difficulty.HARD : fromBukkit(event.getDifficulty())); ++ worldData.setDifficulty(worldData.isHardcore() ? Difficulty.HARD : org.bukkit.craftbukkit.CraftWorld.toMinecraft(event.getDifficulty())); + level.setSpawnSettings(worldData.getDifficulty() != Difficulty.PEACEFUL && ((net.minecraft.server.dedicated.DedicatedServer) this).settings.getProperties().spawnMonsters); + // this.getPlayerList().getPlayers().forEach(this::sendDifficultyUpdate); + // Paper end - per level difficulty diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java index 76ad9641b475..a93dcf3986e8 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -1288,12 +1288,30 @@ public void setAutoSave(boolean value) { @Override public void setDifficulty(Difficulty difficulty) { - this.getHandle().getServer().setDifficulty(this.getHandle(), net.minecraft.world.Difficulty.byId(difficulty.getValue()), null, true); // Paper - per level difficulty; don't skip other difficulty-changing logic; WorldDifficultyChangeEvent + this.getHandle().getServer().setDifficulty(this.getHandle(), toMinecraft(difficulty), null, true); // Paper - per level difficulty; don't skip other difficulty-changing logic; WorldDifficultyChangeEvent } @Override public Difficulty getDifficulty() { - return Difficulty.getByValue(this.getHandle().getDifficulty().ordinal()); + return toBukkit(this.getHandle().getDifficulty()); + } + + public static org.bukkit.Difficulty toBukkit(net.minecraft.world.Difficulty difficulty) { + return switch (difficulty) { + case EASY -> org.bukkit.Difficulty.EASY; + case HARD -> org.bukkit.Difficulty.HARD; + case NORMAL -> org.bukkit.Difficulty.NORMAL; + case PEACEFUL -> org.bukkit.Difficulty.PEACEFUL; + }; + } + + public static net.minecraft.world.Difficulty toMinecraft(org.bukkit.Difficulty difficulty) { + return switch (difficulty) { + case EASY -> net.minecraft.world.Difficulty.EASY; + case HARD -> net.minecraft.world.Difficulty.HARD; + case NORMAL -> net.minecraft.world.Difficulty.NORMAL; + case PEACEFUL -> net.minecraft.world.Difficulty.PEACEFUL; + }; } @Override From d9e760734299ea3080785264dd4f1edbc875fa12 Mon Sep 17 00:00:00 2001 From: david Date: Thu, 24 Apr 2025 20:57:20 +0200 Subject: [PATCH 05/13] move difficulty utility methods to their own class --- .../server/MinecraftServer.java.patch | 4 ++-- .../org/bukkit/craftbukkit/CraftWorld.java | 23 +++--------------- .../craftbukkit/util/CraftDifficulty.java | 24 +++++++++++++++++++ 3 files changed, 29 insertions(+), 22 deletions(-) create mode 100644 paper-server/src/main/java/org/bukkit/craftbukkit/util/CraftDifficulty.java diff --git a/paper-server/patches/sources/net/minecraft/server/MinecraftServer.java.patch b/paper-server/patches/sources/net/minecraft/server/MinecraftServer.java.patch index 9aa4c204d492..590e984754ac 100644 --- a/paper-server/patches/sources/net/minecraft/server/MinecraftServer.java.patch +++ b/paper-server/patches/sources/net/minecraft/server/MinecraftServer.java.patch @@ -1115,10 +1115,10 @@ + net.minecraft.world.level.storage.PrimaryLevelData worldData = level.serverLevelData; + if (forced || !worldData.isDifficultyLocked()) { + io.papermc.paper.event.world.WorldDifficultyChangeEvent event = new io.papermc.paper.event.world.WorldDifficultyChangeEvent( -+ level.getWorld(), source != null ? source.getBukkitSender() : null, org.bukkit.craftbukkit.CraftWorld.toBukkit(difficulty) ++ level.getWorld(), source != null ? source.getBukkitSender() : null, org.bukkit.craftbukkit.util.CraftDifficulty.toBukkit(difficulty) + ); + if (!event.callEvent()) return; -+ worldData.setDifficulty(worldData.isHardcore() ? Difficulty.HARD : org.bukkit.craftbukkit.CraftWorld.toMinecraft(event.getDifficulty())); ++ worldData.setDifficulty(worldData.isHardcore() ? Difficulty.HARD : org.bukkit.craftbukkit.util.CraftDifficulty.toMinecraft(event.getDifficulty())); + level.setSpawnSettings(worldData.getDifficulty() != Difficulty.PEACEFUL && ((net.minecraft.server.dedicated.DedicatedServer) this).settings.getProperties().spawnMonsters); + // this.getPlayerList().getPlayers().forEach(this::sendDifficultyUpdate); + // Paper end - per level difficulty diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java index a93dcf3986e8..689ee5c8a623 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -107,6 +107,7 @@ import org.bukkit.craftbukkit.persistence.CraftPersistentDataContainer; import org.bukkit.craftbukkit.persistence.CraftPersistentDataTypeRegistry; import org.bukkit.craftbukkit.util.CraftBiomeSearchResult; +import org.bukkit.craftbukkit.util.CraftDifficulty; import org.bukkit.craftbukkit.util.CraftLocation; import org.bukkit.craftbukkit.util.CraftNamespacedKey; import org.bukkit.craftbukkit.util.CraftRayTraceResult; @@ -1288,30 +1289,12 @@ public void setAutoSave(boolean value) { @Override public void setDifficulty(Difficulty difficulty) { - this.getHandle().getServer().setDifficulty(this.getHandle(), toMinecraft(difficulty), null, true); // Paper - per level difficulty; don't skip other difficulty-changing logic; WorldDifficultyChangeEvent + this.getHandle().getServer().setDifficulty(this.getHandle(), CraftDifficulty.toMinecraft(difficulty), null, true); // Paper - per level difficulty; don't skip other difficulty-changing logic; WorldDifficultyChangeEvent } @Override public Difficulty getDifficulty() { - return toBukkit(this.getHandle().getDifficulty()); - } - - public static org.bukkit.Difficulty toBukkit(net.minecraft.world.Difficulty difficulty) { - return switch (difficulty) { - case EASY -> org.bukkit.Difficulty.EASY; - case HARD -> org.bukkit.Difficulty.HARD; - case NORMAL -> org.bukkit.Difficulty.NORMAL; - case PEACEFUL -> org.bukkit.Difficulty.PEACEFUL; - }; - } - - public static net.minecraft.world.Difficulty toMinecraft(org.bukkit.Difficulty difficulty) { - return switch (difficulty) { - case EASY -> net.minecraft.world.Difficulty.EASY; - case HARD -> net.minecraft.world.Difficulty.HARD; - case NORMAL -> net.minecraft.world.Difficulty.NORMAL; - case PEACEFUL -> net.minecraft.world.Difficulty.PEACEFUL; - }; + return CraftDifficulty.toBukkit(this.getHandle().getDifficulty()); } @Override diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/util/CraftDifficulty.java b/paper-server/src/main/java/org/bukkit/craftbukkit/util/CraftDifficulty.java new file mode 100644 index 000000000000..f8f4d7955ce2 --- /dev/null +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/util/CraftDifficulty.java @@ -0,0 +1,24 @@ +package org.bukkit.craftbukkit.util; + +import org.jspecify.annotations.NullMarked; + +@NullMarked +public final class CraftDifficulty { + public static org.bukkit.Difficulty toBukkit(net.minecraft.world.Difficulty difficulty) { + return switch (difficulty) { + case EASY -> org.bukkit.Difficulty.EASY; + case HARD -> org.bukkit.Difficulty.HARD; + case NORMAL -> org.bukkit.Difficulty.NORMAL; + case PEACEFUL -> org.bukkit.Difficulty.PEACEFUL; + }; + } + + public static net.minecraft.world.Difficulty toMinecraft(org.bukkit.Difficulty difficulty) { + return switch (difficulty) { + case EASY -> net.minecraft.world.Difficulty.EASY; + case HARD -> net.minecraft.world.Difficulty.HARD; + case NORMAL -> net.minecraft.world.Difficulty.NORMAL; + case PEACEFUL -> net.minecraft.world.Difficulty.PEACEFUL; + }; + } +} From 947814d2f3adc0baff5efe0681ffadeeb0162bef Mon Sep 17 00:00:00 2001 From: david Date: Thu, 24 Apr 2025 23:50:40 +0200 Subject: [PATCH 06/13] [ci skip] Removed comment in setDifficulty method --- .../src/main/java/org/bukkit/craftbukkit/CraftWorld.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java index 689ee5c8a623..bceafed440ab 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -1289,7 +1289,7 @@ public void setAutoSave(boolean value) { @Override public void setDifficulty(Difficulty difficulty) { - this.getHandle().getServer().setDifficulty(this.getHandle(), CraftDifficulty.toMinecraft(difficulty), null, true); // Paper - per level difficulty; don't skip other difficulty-changing logic; WorldDifficultyChangeEvent + this.getHandle().getServer().setDifficulty(this.getHandle(), CraftDifficulty.toMinecraft(difficulty), null, true); } @Override From e849caee81eeae0428e5dca0818244a28473604f Mon Sep 17 00:00:00 2001 From: david Date: Thu, 24 Apr 2025 23:50:58 +0200 Subject: [PATCH 07/13] [ci skip] Updated Javadocs for WorldDifficultyChangeEvent --- .../papermc/paper/event/world/WorldDifficultyChangeEvent.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/paper-api/src/main/java/io/papermc/paper/event/world/WorldDifficultyChangeEvent.java b/paper-api/src/main/java/io/papermc/paper/event/world/WorldDifficultyChangeEvent.java index 24bb2e4c2673..7253872b32ed 100644 --- a/paper-api/src/main/java/io/papermc/paper/event/world/WorldDifficultyChangeEvent.java +++ b/paper-api/src/main/java/io/papermc/paper/event/world/WorldDifficultyChangeEvent.java @@ -11,6 +11,9 @@ /** * Called when a world's difficulty is changed, either by command or by api. + *

+ * If the world is in {@link World#isHardcore() hardcore} + * the resulting difficulty will always be {@link Difficulty#HARD} */ @NullMarked public class WorldDifficultyChangeEvent extends WorldEvent implements Cancellable { From 0bc30b598aeed6ba2bfa53d3c0eda046c55eb76c Mon Sep 17 00:00:00 2001 From: david Date: Thu, 1 May 2025 11:32:59 +0200 Subject: [PATCH 08/13] rebase --- .../features/0015-Moonrise-optimisation-patches.patch | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch b/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch index 59c0dc568714..6286634d4b2b 100644 --- a/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch +++ b/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch @@ -23750,7 +23750,7 @@ index 58be6e1d1607a3af5e28f851718b82321f2feb25..9c9b601a3f903bebb0dd1bda0e247455 thread1 -> { DedicatedServer dedicatedServer1 = new DedicatedServer( diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 91df2a420eeab1bab508b95f0029fae7adb51c58..094ef7f54ad71795a2d8c2a8d03a32bef6ff2164 100644 +index 3ad26868b4ef2d126fed04f2b95aaf81807eb481..7b62633e1785f9f76b08429fb00c6cba033c8803 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java @@ -172,7 +172,7 @@ import net.minecraft.world.phys.Vec2; @@ -23942,7 +23942,7 @@ index 91df2a420eeab1bab508b95f0029fae7adb51c58..094ef7f54ad71795a2d8c2a8d03a32be return true; } else { boolean ret = false; // Paper - force execution of all worlds, do not just bias the first -@@ -2466,6 +2554,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop Date: Thu, 5 Jun 2025 14:31:06 +0200 Subject: [PATCH 09/13] rebase --- .../patches/features/0015-Moonrise-optimisation-patches.patch | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch b/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch index 49514101cf6c..642dcd3a92f6 100644 --- a/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch +++ b/paper-server/patches/features/0015-Moonrise-optimisation-patches.patch @@ -23754,7 +23754,7 @@ index 58be6e1d1607a3af5e28f851718b82321f2feb25..9c9b601a3f903bebb0dd1bda0e247455 thread1 -> { DedicatedServer dedicatedServer1 = new DedicatedServer( diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 91df2a420eeab1bab508b95f0029fae7adb51c58..094ef7f54ad71795a2d8c2a8d03a32bef6ff2164 100644 +index 3ad26868b4ef2d126fed04f2b95aaf81807eb481..7b62633e1785f9f76b08429fb00c6cba033c8803 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java @@ -172,7 +172,7 @@ import net.minecraft.world.phys.Vec2; @@ -23946,7 +23946,7 @@ index 91df2a420eeab1bab508b95f0029fae7adb51c58..094ef7f54ad71795a2d8c2a8d03a32be return true; } else { boolean ret = false; // Paper - force execution of all worlds, do not just bias the first -@@ -2466,6 +2554,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop Date: Thu, 17 Jul 2025 21:45:31 +0200 Subject: [PATCH 10/13] rebased --- .../features/0016-Moonrise-optimisation-patches.patch | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/paper-server/patches/features/0016-Moonrise-optimisation-patches.patch b/paper-server/patches/features/0016-Moonrise-optimisation-patches.patch index 4be82944c5f1..5e4ddb99e49c 100644 --- a/paper-server/patches/features/0016-Moonrise-optimisation-patches.patch +++ b/paper-server/patches/features/0016-Moonrise-optimisation-patches.patch @@ -23867,7 +23867,7 @@ index 46de98a6bbbae48c4837e1e588ba198a363d2dde..fd3553bdc1c3cdbf6aa3dc00e0a4987f thread1 -> { DedicatedServer dedicatedServer1 = new DedicatedServer( diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 3527c39f3f95832d52aeda6205bbbb7161ecaf66..dc47259e40089a4793d950d4c3dc5bcc51ff680f 100644 +index 359568f7e6dd4e22ee69b4922ddd0ba0aaaf765e..4e6d2eb5caf41af0b9f04d3cef1bb6fc78fc86e3 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java @@ -173,7 +173,7 @@ import net.minecraft.world.phys.Vec2; @@ -24059,7 +24059,7 @@ index 3527c39f3f95832d52aeda6205bbbb7161ecaf66..dc47259e40089a4793d950d4c3dc5bcc return true; } else { boolean ret = false; // Paper - force execution of all worlds, do not just bias the first -@@ -2479,6 +2567,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop Date: Sat, 26 Jul 2025 22:34:26 +0200 Subject: [PATCH 11/13] made difficulty final and changed command sender to command source stack --- .../world/WorldDifficultyChangeEvent.java | 41 +++++-------------- 1 file changed, 10 insertions(+), 31 deletions(-) diff --git a/paper-api/src/main/java/io/papermc/paper/event/world/WorldDifficultyChangeEvent.java b/paper-api/src/main/java/io/papermc/paper/event/world/WorldDifficultyChangeEvent.java index 7253872b32ed..9de897f46f46 100644 --- a/paper-api/src/main/java/io/papermc/paper/event/world/WorldDifficultyChangeEvent.java +++ b/paper-api/src/main/java/io/papermc/paper/event/world/WorldDifficultyChangeEvent.java @@ -1,9 +1,8 @@ package io.papermc.paper.event.world; +import io.papermc.paper.command.brigadier.CommandSourceStack; import org.bukkit.Difficulty; import org.bukkit.World; -import org.bukkit.command.CommandSender; -import org.bukkit.event.Cancellable; import org.bukkit.event.HandlerList; import org.bukkit.event.world.WorldEvent; import org.jspecify.annotations.NullMarked; @@ -16,27 +15,26 @@ * the resulting difficulty will always be {@link Difficulty#HARD} */ @NullMarked -public class WorldDifficultyChangeEvent extends WorldEvent implements Cancellable { +public class WorldDifficultyChangeEvent extends WorldEvent { private static final HandlerList HANDLER_LIST = new HandlerList(); - private final @Nullable CommandSender commandSender; - private Difficulty difficulty; - private boolean cancelled; + private final @Nullable CommandSourceStack commandSource; + private final Difficulty difficulty; - public WorldDifficultyChangeEvent(final World world, final @Nullable CommandSender commandSender, final Difficulty difficulty) { + public WorldDifficultyChangeEvent(final World world, final @Nullable CommandSourceStack commandSource, final Difficulty difficulty) { super(world); - this.commandSender = commandSender; + this.commandSource = commandSource; this.difficulty = difficulty; } /** - * Gets the command sender associated with this event. + * Gets the command source associated with this event. * - * @return {@code null} if the difficulty was changed via api, otherwise the {@link CommandSender}. + * @return {@code null} if the difficulty was changed via api, otherwise the {@link CommandSourceStack}. */ - public @Nullable CommandSender getCommandSender() { - return commandSender; + public @Nullable CommandSourceStack getCommandSource() { + return commandSource; } /** @@ -48,25 +46,6 @@ public Difficulty getDifficulty() { return difficulty; } - /** - * Set the new difficulty of the world. - * - * @param difficulty the new difficulty. - */ - public void setDifficulty(final Difficulty difficulty) { - this.difficulty = difficulty; - } - - @Override - public boolean isCancelled() { - return this.cancelled; - } - - @Override - public void setCancelled(final boolean cancel) { - this.cancelled = cancel; - } - @Override public HandlerList getHandlers() { return HANDLER_LIST; From ee8b1a225e9ca6e07330407a21082e94d827e5e1 Mon Sep 17 00:00:00 2001 From: david Date: Sat, 26 Jul 2025 22:34:34 +0200 Subject: [PATCH 12/13] made event non-cancellable --- .../features/0016-Moonrise-optimisation-patches.patch | 6 +++--- .../net/minecraft/server/MinecraftServer.java.patch | 11 +++++------ 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/paper-server/patches/features/0016-Moonrise-optimisation-patches.patch b/paper-server/patches/features/0016-Moonrise-optimisation-patches.patch index 501821d302a9..1bdd7e14eec0 100644 --- a/paper-server/patches/features/0016-Moonrise-optimisation-patches.patch +++ b/paper-server/patches/features/0016-Moonrise-optimisation-patches.patch @@ -23867,7 +23867,7 @@ index 46de98a6bbbae48c4837e1e588ba198a363d2dde..fd3553bdc1c3cdbf6aa3dc00e0a4987f thread1 -> { DedicatedServer dedicatedServer1 = new DedicatedServer( diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java -index 3527c39f3f95832d52aeda6205bbbb7161ecaf66..dc47259e40089a4793d950d4c3dc5bcc51ff680f 100644 +index f1346c2dc8fcf24a1ed945dbc57775daaa683b72..3b2b9d959e704abf87fd074418b47ff741a2a65e 100644 --- a/net/minecraft/server/MinecraftServer.java +++ b/net/minecraft/server/MinecraftServer.java @@ -173,7 +173,7 @@ import net.minecraft.world.phys.Vec2; @@ -24059,7 +24059,7 @@ index 3527c39f3f95832d52aeda6205bbbb7161ecaf66..dc47259e40089a4793d950d4c3dc5bcc return true; } else { boolean ret = false; // Paper - force execution of all worlds, do not just bias the first -@@ -2479,6 +2567,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop Date: Sat, 26 Jul 2025 23:05:21 +0200 Subject: [PATCH 13/13] mark constructor as internal --- .../papermc/paper/event/world/WorldDifficultyChangeEvent.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/paper-api/src/main/java/io/papermc/paper/event/world/WorldDifficultyChangeEvent.java b/paper-api/src/main/java/io/papermc/paper/event/world/WorldDifficultyChangeEvent.java index 9de897f46f46..a5b9ac7649c6 100644 --- a/paper-api/src/main/java/io/papermc/paper/event/world/WorldDifficultyChangeEvent.java +++ b/paper-api/src/main/java/io/papermc/paper/event/world/WorldDifficultyChangeEvent.java @@ -5,6 +5,7 @@ import org.bukkit.World; import org.bukkit.event.HandlerList; import org.bukkit.event.world.WorldEvent; +import org.jetbrains.annotations.ApiStatus; import org.jspecify.annotations.NullMarked; import org.jspecify.annotations.Nullable; @@ -22,6 +23,7 @@ public class WorldDifficultyChangeEvent extends WorldEvent { private final @Nullable CommandSourceStack commandSource; private final Difficulty difficulty; + @ApiStatus.Internal public WorldDifficultyChangeEvent(final World world, final @Nullable CommandSourceStack commandSource, final Difficulty difficulty) { super(world); this.commandSource = commandSource;