From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Aikar <aikar@aikar.co>
Date: Mon, 17 Sep 2018 23:05:31 -0400
Subject: [PATCH] Support Overriding World Seeds

Allows you to add to paper.yml

seed-overrides:
  world_name: some seed value

This will ignore every where a seed is set/created/loaded and force
a world to use the specified seed.

This seed will end up being saved to the world data file, so it is
a permanent change in that it won't go back if you remove it from paper.yml

diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
index 214b577b326bc794fa3721deb6171228dd4f25e6..559e6b42ba5bf0ea92cccbabd2ef1d4c27b03064 100644
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
@@ -11,6 +11,7 @@ import java.lang.reflect.Modifier;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.TimeUnit;
 import java.util.logging.Level;
 import java.util.regex.Pattern;
@@ -19,6 +20,7 @@ import com.google.common.collect.Lists;
 import net.minecraft.server.MinecraftServer;
 import org.bukkit.Bukkit;
 import org.bukkit.command.Command;
+import org.bukkit.configuration.ConfigurationSection;
 import org.bukkit.configuration.InvalidConfigurationException;
 import org.bukkit.configuration.file.YamlConfiguration;
 import co.aikar.timings.Timings;
@@ -310,4 +312,23 @@ public class PaperConfig {
         }
         tabSpamLimit = getInt("settings.spam-limiter.tab-spam-limit", tabSpamLimit);
     }
+
+    public static Map<String, Long> seedOverride = new java.util.HashMap<>();
+    private static void worldSeedOverrides() {
+        ConfigurationSection seeds = config.getConfigurationSection("seed-overrides");
+        if (seeds != null) {
+            TimingsManager.hiddenConfigs.add("seed-overrides");
+            for (String key : seeds.getKeys(false)) {
+                String seedString = seeds.getString(key);
+                long seed;
+                try {
+                    seed = Long.parseLong(seedString);
+                } catch (Exception e) {
+                    seed = (long) seedString.hashCode();
+                }
+                log("Seed Override: " + key + " => " + seed);
+                seedOverride.put(key, seed);
+            }
+        }
+    }
 }
diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java
index 056cbdeec8a1c17de44d59f16b77a995c82a3abb..ec4ce59c5e29b68d96856a9086fe2ba1bdbb1df1 100644
--- a/src/main/java/net/minecraft/server/MinecraftServer.java
+++ b/src/main/java/net/minecraft/server/MinecraftServer.java
@@ -378,7 +378,7 @@ public abstract class MinecraftServer extends IAsyncTaskHandlerReentrant<TickTas
             this.convertWorld(name); // Run conversion now
 
             org.bukkit.generator.ChunkGenerator gen = this.server.getGenerator(name);
-            WorldSettings worldsettings = new WorldSettings(i, this.getGamemode(), this.getGenerateStructures(), this.isHardcore(), worldtype);
+            WorldSettings worldsettings = new WorldSettings(com.destroystokyo.paper.PaperConfig.seedOverride.getOrDefault(name, i), this.getGamemode(), this.getGenerateStructures(), this.isHardcore(), worldtype); // Paper
             worldsettings.setGeneratorSettings(jsonelement);
 
             if (j == 0) {
diff --git a/src/main/java/net/minecraft/server/WorldData.java b/src/main/java/net/minecraft/server/WorldData.java
index 561b6d94696eebc255279f45d2ca6b88b2490f78..95518e54d1fd7ada51df1cdc3562affccd48bfcb 100644
--- a/src/main/java/net/minecraft/server/WorldData.java
+++ b/src/main/java/net/minecraft/server/WorldData.java
@@ -127,7 +127,7 @@ public class WorldData {
             this.d = nbttagcompound2.getBoolean("Snapshot");
         }
 
-        this.e = nbttagcompound.getLong("RandomSeed");
+        this.e = com.destroystokyo.paper.PaperConfig.seedOverride.getOrDefault(nbttagcompound.getString("LevelName"), nbttagcompound.getLong("RandomSeed")); // Paper
         if (nbttagcompound.hasKeyOfType("generatorName", 8)) {
             String s = nbttagcompound.getString("generatorName");
 
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index d15a857b30511bda9bbeddf651b4633e4bea473d..011d0927da7a2a67dcd6d75e3af07d38f30acf81 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -1016,7 +1016,7 @@ public final class CraftServer implements Server {
         WorldSettings worldSettings;
         // See MinecraftServer.a(String, String, long, WorldType, JsonElement)
         if (worlddata == null) {
-            worldSettings = new WorldSettings(creator.seed(), EnumGamemode.getById(getDefaultGameMode().getValue()), generateStructures, hardcore, type);
+            worldSettings = new WorldSettings(com.destroystokyo.paper.PaperConfig.seedOverride.getOrDefault(name, creator.seed()), EnumGamemode.getById(getDefaultGameMode().getValue()), generateStructures, hardcore, type); // Paper
             JsonElement parsedSettings = new JsonParser().parse(creator.generatorSettings());
             if (parsedSettings.isJsonObject()) {
                 worldSettings.setGeneratorSettings(parsedSettings.getAsJsonObject());
