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 0000000000..a5b9ac7649 --- /dev/null +++ b/paper-api/src/main/java/io/papermc/paper/event/world/WorldDifficultyChangeEvent.java @@ -0,0 +1,59 @@ +package io.papermc.paper.event.world; + +import io.papermc.paper.command.brigadier.CommandSourceStack; +import org.bukkit.Difficulty; +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; + +/** + * 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 { + + private static final HandlerList HANDLER_LIST = new HandlerList(); + + 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; + this.difficulty = difficulty; + } + + /** + * Gets the command source associated with this event. + * + * @return {@code null} if the difficulty was changed via api, otherwise the {@link CommandSourceStack}. + */ + public @Nullable CommandSourceStack getCommandSource() { + return commandSource; + } + + /** + * Gets the new difficulty of the world. + * + * @return the new difficulty. + */ + public Difficulty getDifficulty() { + return difficulty; + } + + @Override + public HandlerList getHandlers() { + return HANDLER_LIST; + } + + public static HandlerList getHandlerList() { + return HANDLER_LIST; + } +} diff --git a/paper-server/patches/features/0016-Moonrise-optimisation-patches.patch b/paper-server/patches/features/0016-Moonrise-optimisation-patches.patch index 501821d302..1bdd7e14ee 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 Component.translatable("commands.difficulty.success", difficulty.getDisplayName()), true); return 0; } 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 68351e4760..aa0a61d7f3 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -113,6 +113,7 @@ import org.bukkit.craftbukkit.metadata.BlockMetadataStore; 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; @@ -1310,12 +1311,12 @@ public class CraftWorld extends CraftRegionAccessor implements World { @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(), CraftDifficulty.toMinecraft(difficulty), null, true); } @Override public Difficulty getDifficulty() { - return Difficulty.getByValue(this.getHandle().getDifficulty().ordinal()); + 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 0000000000..f8f4d7955c --- /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; + }; + } +}