From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Nassim Jahnke 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 e5543b3a261f80bd9b0346d595a62b5458d9b229..45abadeb2568566b3646004d03e7ba8c1766c18a 100644 --- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java @@ -898,6 +898,55 @@ public class PaperWorldConfig { return table; } + public it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap 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> 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 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> 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..f8a2aa31e38f64f88a82d5a388b58f1962d5fda0 100644 --- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java +++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java @@ -278,7 +278,7 @@ public abstract class ChunkGenerator implements BiomeManager.NoiseBiomeSource { try { Registry iregistry = generatoraccessseed.registryAccess().registryOrThrow(Registry.PLACED_FEATURE_REGISTRY); - Registry> iregistry1 = generatoraccessseed.registryAccess().registryOrThrow(Registry.STRUCTURE_FEATURE_REGISTRY); + Registry> iregistry1 = generatoraccessseed.registryAccess().registryOrThrow(Registry.STRUCTURE_FEATURE_REGISTRY); // Paper - diff on change int k = Math.max(GenerationStep.Decoration.values().length, j); for (int l = 0; l < k; ++l) { @@ -292,7 +292,15 @@ public abstract class ChunkGenerator implements BiomeManager.NoiseBiomeSource { for (iterator = list1.iterator(); iterator.hasNext(); ++i1) { StructureFeature structuregenerator = (StructureFeature) iterator.next(); - seededrandom.setFeatureSeed(i, i1, l); + // Paper start - change populationSeed used in random + long featurePopulationSeed = i; + final net.minecraft.resources.ResourceLocation location = iregistry1.getKey(structuregenerator); + 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, i1, l);; + // Paper end Supplier supplier = () -> { // CraftBukkit - decompile error Optional optional = iregistry1.getResourceKey(structuregenerator).map(Object::toString);