Add WorldDifficultyChangeEvent (#12471)

This commit is contained in:
David
2025-07-26 23:38:16 +02:00
committed by GitHub
parent 57c13137e4
commit a57636189a
6 changed files with 96 additions and 9 deletions

View File

@@ -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.
* <p>
* 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;
}
}

View File

@@ -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<TickTa
@@ -2482,6 +2570,12 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
}
}
@@ -28333,7 +28333,7 @@ index b30f56fbc1fd17259a1d05dc9155fffcab292ca1..11fed81a4696ba18440e755c3b8a5ca3
this.generatingStep = generatingStep;
this.cache = cache;
diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java
index 774b597b34198d55bdec861e3ebabb36bac8e33e..d099b76082e59baf42de8e265eb2bc593c6e6f86 100644
index fdfbfd535469affe755379911b6fdda695866849..9547000b6e41fab39b00ca55ebd41825d222592e 100644
--- a/net/minecraft/server/players/PlayerList.java
+++ b/net/minecraft/server/players/PlayerList.java
@@ -1310,7 +1310,7 @@ public abstract class PlayerList {

View File

@@ -1112,7 +1112,7 @@
}
public KeyPair getKeyPair() {
@@ -1244,11 +_,14 @@
@@ -1244,11 +_,17 @@
}
}
@@ -1121,10 +1121,13 @@
- 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
+ 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()) {
+ new io.papermc.paper.event.world.WorldDifficultyChangeEvent(
+ level.getWorld(), source, org.bukkit.craftbukkit.util.CraftDifficulty.toBukkit(difficulty)
+ ).callEvent();
+ worldData.setDifficulty(worldData.isHardcore() ? Difficulty.HARD : difficulty);
+ level.setSpawnSettings(worldData.getDifficulty() != Difficulty.PEACEFUL && ((net.minecraft.server.dedicated.DedicatedServer) this).settings.getProperties().spawnMonsters);
+ // this.getPlayerList().getPlayers().forEach(this::sendDifficultyUpdate);

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
};
}
}