aboutsummaryrefslogtreecommitdiffhomepage
path: root/patches/server/0802-Configurable-feature-seeds.patch
blob: 4a81ec7cafd83b090cc42bf765c811aa1cae98f3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Nassim Jahnke <jahnke.nassim@gmail.com>
Date: Tue, 31 Aug 2021 17:05:27 +0200
Subject: [PATCH] Configurable feature seeds

Co-authored-by: Thonk <30448663+ExcessiveAmountsOfZombies@users.noreply.github.com>

diff --git a/src/main/java/co/aikar/timings/TimingsExport.java b/src/main/java/co/aikar/timings/TimingsExport.java
index ee53453440177537fc653ea156785d7591498614..5e3b7fb2e0b7608610555cd23e7ad25a05883181 100644
--- a/src/main/java/co/aikar/timings/TimingsExport.java
+++ b/src/main/java/co/aikar/timings/TimingsExport.java
@@ -273,7 +273,7 @@ public class TimingsExport extends Thread {
         JSONObject object = new JSONObject();
         for (String key : config.getKeys(false)) {
             String fullKey = (parentKey != null ? parentKey + "." + key : key);
-            if (fullKey.equals("database") || fullKey.equals("settings.bungeecord-addresses") || TimingsManager.hiddenConfigs.contains(fullKey) || key.startsWith("seed-") || key.equals("worldeditregentempworld")) {
+            if (fullKey.equals("database") || fullKey.equals("settings.bungeecord-addresses") || TimingsManager.hiddenConfigs.contains(fullKey) || key.startsWith("seed-") || key.equals("worldeditregentempworld") || key.equals("feature-seeds")) {
                 continue;
             }
             final Object val = config.get(key);
diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
index ea67eb1099e6ec34426d80c95e9999f4aa8793b9..8150330bc55a010c7d0f96421586226631eb72f7 100644
--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
+++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java
@@ -946,6 +946,55 @@ public class PaperWorldConfig {
         return table;
     }
 
+    public it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap<net.minecraft.resources.ResourceLocation> featureSeeds = new it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap<>();
+    private void featureSeeds() {
+        featureSeeds.defaultReturnValue(-1);
+        final boolean randomise = getBoolean("feature-seeds.generate-random-seeds-for-all", false);
+        final ConfigurationSection defaultSection = config.getConfigurationSection("world-settings.default.feature-seeds");
+        final ConfigurationSection section = config.getConfigurationSection("world-settings." + worldName + ".feature-seeds");
+        final net.minecraft.core.Registry<net.minecraft.world.level.levelgen.feature.ConfiguredFeature<?, ?>> registry
+            = net.minecraft.server.MinecraftServer.getServer().registryAccess().registryOrThrow(net.minecraft.core.Registry.CONFIGURED_FEATURE_REGISTRY);
+        if (section != null) {
+            loadFeatureSeeds(section, registry);
+        }
+
+        // Also use default set seeds if not already set per world
+        loadFeatureSeeds(defaultSection, registry);
+
+        if (randomise) {
+            final Map<String, Object> randomisedSeeds = new HashMap<>();
+            final java.util.Random random = new java.security.SecureRandom();
+            for (final net.minecraft.resources.ResourceLocation resourceLocation : registry.keySet()) {
+                if (featureSeeds.containsKey(resourceLocation)) {
+                    continue;
+                }
+
+                final long seed = random.nextLong();
+                randomisedSeeds.put("world-settings." + worldName + ".feature-seeds." + resourceLocation.getPath(), seed);
+                featureSeeds.put(resourceLocation, seed);
+            }
+            if (!randomisedSeeds.isEmpty()) {
+                config.addDefaults(randomisedSeeds);
+            }
+        }
+    }
+
+    private void loadFeatureSeeds(final ConfigurationSection section, final net.minecraft.core.Registry<net.minecraft.world.level.levelgen.feature.ConfiguredFeature<?, ?>> registry) {
+        for (final String key : section.getKeys(false)) {
+            if (!(section.get(key) instanceof Number)) {
+                continue;
+            }
+
+            final net.minecraft.resources.ResourceLocation location = new net.minecraft.resources.ResourceLocation(key);
+            if (!registry.containsKey(location)) {
+                logError("Invalid feature resource location: " + location);
+                continue;
+            }
+
+            featureSeeds.putIfAbsent(location, section.getLong(key));
+        }
+    }
+
     public int getBehaviorTickRate(String typeName, String entityType, int def) {
         return getIntOrDefault(behaviorTickRates, typeName, entityType, def);
     }
diff --git a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
index e2b7da265e9616ac47e6be72cc6e6d2c75cfec44..e4591c0b3c8547cc6f4e2a0891fc378ee4334d9e 100644
--- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java
@@ -277,7 +277,7 @@ public abstract class ChunkGenerator implements BiomeManager.NoiseBiomeSource {
             int j = list.size();
 
             try {
-                Registry<PlacedFeature> iregistry = generatoraccessseed.registryAccess().registryOrThrow(Registry.PLACED_FEATURE_REGISTRY);
+                Registry<PlacedFeature> iregistry = generatoraccessseed.registryAccess().registryOrThrow(Registry.PLACED_FEATURE_REGISTRY); // Paper - diff on change
                 Registry<StructureFeature<?>> iregistry1 = generatoraccessseed.registryAccess().registryOrThrow(Registry.STRUCTURE_FEATURE_REGISTRY);
                 int k = Math.max(GenerationStep.Decoration.values().length, j);
 
@@ -351,7 +351,15 @@ public abstract class ChunkGenerator implements BiomeManager.NoiseBiomeSource {
                                 return (String) optional.orElseGet(placedfeature::toString);
                             };
 
-                            seededrandom.setFeatureSeed(i, l1, l);
+                            // Paper start - change populationSeed used in random
+                            long featurePopulationSeed = i;
+                            final net.minecraft.resources.ResourceLocation location = iregistry.getKey(placedfeature);
+                            final long configFeatureSeed = generatoraccessseed.getMinecraftWorld().paperConfig.featureSeeds.getLong(location);
+                            if (configFeatureSeed != -1) {
+                                featurePopulationSeed = seededrandom.setDecorationSeed(configFeatureSeed, blockposition.getX(), blockposition.getZ()); // See seededrandom.setDecorationSeed from above
+                            }
+                            seededrandom.setFeatureSeed(featurePopulationSeed, l1, l);
+                            // Paper end
 
                             try {
                                 generatoraccessseed.setCurrentlyGenerating(supplier1);