From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Sun, 28 Jun 2020 03:59:10 -0400
Subject: [PATCH] Fix Per World Difficulty / Remembering Difficulty

Fixes per world difficulty with /difficulty command and also
makes it so that the server keeps the last difficulty used instead
of restoring the server.properties every single load.

diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index e477ccf2f17ffad0a3720f7ef7ccfe23b91bff3a..01394284fca2f56c1808e75f70a64c4cc2a196ea 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -1738,11 +1738,14 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
         }
     }
 
-    public void setDifficulty(Difficulty difficulty, boolean forceUpdate) {
-        if (forceUpdate || !this.worldData.isDifficultyLocked()) {
-            this.worldData.setDifficulty(this.worldData.isHardcore() ? Difficulty.HARD : difficulty);
-            this.updateMobSpawningFlags();
-            this.getPlayerList().getPlayers().forEach(this::sendDifficultyUpdate);
+    // Paper start - remember per level difficulty
+    public void setDifficulty(ServerLevel level, Difficulty difficulty, boolean forceUpdate) {
+        PrimaryLevelData worldData = level.serverLevelData;
+        if (forceUpdate || !worldData.isDifficultyLocked()) {
+            worldData.setDifficulty(worldData.isHardcore() ? Difficulty.HARD : difficulty);
+            level.setSpawnSettings(worldData.getDifficulty() != Difficulty.PEACEFUL && ((DedicatedServer) this).settings.getProperties().spawnMonsters, this.isSpawningAnimals());
+            // this.getPlayerList().getPlayers().forEach(this::sendDifficultyUpdate);
+            // Paper end
         }
     }
 
diff --git a/src/main/java/net/minecraft/server/commands/DifficultyCommand.java b/src/main/java/net/minecraft/server/commands/DifficultyCommand.java
index 33c859df0b669d0c3e97ccba29f17c1ba2166a27..9f03b738aea623fe409ca176397f48be055466da 100644
--- a/src/main/java/net/minecraft/server/commands/DifficultyCommand.java
+++ b/src/main/java/net/minecraft/server/commands/DifficultyCommand.java
@@ -35,10 +35,11 @@ public class DifficultyCommand {
 
     public static int setDifficulty(CommandSourceStack source, Difficulty difficulty) throws CommandSyntaxException {
         MinecraftServer minecraftServer = source.getServer();
-        if (minecraftServer.getWorldData().getDifficulty() == difficulty) {
+        net.minecraft.server.level.ServerLevel level = source.getLevel(); // Paper
+        if (level.serverLevelData.getDifficulty() == difficulty) { // Paper
             throw ERROR_ALREADY_DIFFICULT.create(difficulty.getKey());
         } else {
-            minecraftServer.setDifficulty(difficulty, true);
+            minecraftServer.setDifficulty(level, difficulty, true); // Paper - use world
             source.sendSuccess(new TranslatableComponent("commands.difficulty.success", difficulty.getDisplayName()), true);
             return 0;
         }
diff --git a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
index a335d48467d1730bfed25eb5fd9046e115f23ed0..0a930147663850dc2ea7ffe9ced5611d5bab7c6d 100644
--- a/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
+++ b/src/main/java/net/minecraft/server/dedicated/DedicatedServer.java
@@ -369,7 +369,7 @@ public class DedicatedServer extends MinecraftServer implements ServerInterface
 
     @Override
     public void forceDifficulty() {
-        this.setDifficulty(this.getProperties().difficulty, true);
+        //this.a(this.getDedicatedServerProperties().difficulty, true); // Paper - Don't overwrite level.dat's difficulty, keep current
     }
 
     @Override
diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
index 15b16f94736b250e1e4207498a42043901dd8f1b..ae3465cd5be426f3bddc3552b6aad6cad8c8ee25 100644
--- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
+++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java
@@ -3021,7 +3021,7 @@ public class ServerGamePacketListenerImpl implements ServerPlayerConnection, Ser
     public void handleChangeDifficulty(ServerboundChangeDifficultyPacket packet) {
         PacketUtils.ensureRunningOnSameThread(packet, this, this.player.getLevel());
         if (this.player.hasPermissions(2) || this.isSingleplayerOwner()) {
-            this.server.setDifficulty(packet.getDifficulty(), false);
+            //this.minecraftServer.a(packetplayindifficultychange.b(), false); // Paper - don't allow clients to change this
         }
     }
 
