From 57555b8c6afc87542b26559e40381b4f0ba508bd Mon Sep 17 00:00:00 2001 From: Jake Potrebic Date: Sun, 9 Oct 2022 13:19:35 -0700 Subject: [PATCH] Add missing structure set seed configs (#8030) --- .../0810-Add-config-for-stronghold-seed.patch | 47 ----- ...d-missing-structure-set-seed-configs.patch | 197 ++++++++++++++++++ 2 files changed, 197 insertions(+), 47 deletions(-) delete mode 100644 patches/server/0810-Add-config-for-stronghold-seed.patch create mode 100644 patches/server/0810-Add-missing-structure-set-seed-configs.patch diff --git a/patches/server/0810-Add-config-for-stronghold-seed.patch b/patches/server/0810-Add-config-for-stronghold-seed.patch deleted file mode 100644 index d052da6c1..000000000 --- a/patches/server/0810-Add-config-for-stronghold-seed.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Jake Potrebic -Date: Thu, 13 Jan 2022 23:05:53 -0800 -Subject: [PATCH] Add config for stronghold seed - - -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 cc79ca7ee770408ec59b1f6a3f4ec58e23bd2619..cb64b46eb874bb7ce22cdbf9e9629c929a05fb61 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java -+++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java -@@ -236,7 +236,13 @@ public abstract class ChunkGenerator { - HolderSet holderset = concentricringsstructureplacement.preferredBiomes(); - RandomSource randomsource = RandomSource.create(); - -+ // Paper start -+ if (this.conf.strongholdSeed != null && this.structureSets.getResourceKey(holder).orElse(null) == net.minecraft.world.level.levelgen.structure.BuiltinStructureSets.STRONGHOLDS) { -+ randomsource.setSeed(this.conf.strongholdSeed); -+ } else { - randomsource.setSeed(this instanceof FlatLevelSource ? 0L : randomstate.legacyLevelSeed()); -+ } -+ // Paper end - double d0 = randomsource.nextDouble() * 3.141592653589793D * 2.0D; - int l = 0; - int i1 = 0; -diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java -index cf96f9fdc4ae561f01d44503b9851c60140e4ea7..bbf15fbb889670e57bd86377590a1b3abe80b96d 100644 ---- a/src/main/java/org/spigotmc/SpigotWorldConfig.java -+++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java -@@ -366,6 +366,7 @@ public class SpigotWorldConfig - public int mansionSeed; - public int fossilSeed; - public int portalSeed; -+ public Long strongholdSeed; // Paper - private void initWorldGenSeeds() - { - this.villageSeed = this.getInt( "seed-village", 10387312 ); -@@ -383,6 +384,10 @@ public class SpigotWorldConfig - this.mansionSeed = this.getInt( "seed-mansion", 10387319 ); - this.fossilSeed = this.getInt( "seed-fossil", 14357921 ); - this.portalSeed = this.getInt( "seed-portal", 34222645 ); -+ // Paper start -+ final String strongholdSeedString = this.getString("seed-stronghold", "default"); -+ this.strongholdSeed = org.apache.commons.lang3.math.NumberUtils.isParsable(strongholdSeedString) ? Long.parseLong(strongholdSeedString) : null; -+ // Paper end - this.log( "Custom Map Seeds: Village: " + this.villageSeed + " Desert: " + this.desertSeed + " Igloo: " + this.iglooSeed + " Jungle: " + this.jungleSeed + " Swamp: " + this.swampSeed + " Monument: " + this.monumentSeed - + " Ocean: " + this.oceanSeed + " Shipwreck: " + this.shipwreckSeed + " End City: " + this.endCitySeed + " Slime: " + this.slimeSeed + " Nether: " + this.netherSeed + " Mansion: " + this.mansionSeed + " Fossil: " + this.fossilSeed + " Portal: " + this.portalSeed ); - } diff --git a/patches/server/0810-Add-missing-structure-set-seed-configs.patch b/patches/server/0810-Add-missing-structure-set-seed-configs.patch new file mode 100644 index 000000000..4053a482e --- /dev/null +++ b/patches/server/0810-Add-missing-structure-set-seed-configs.patch @@ -0,0 +1,197 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jake Potrebic +Date: Thu, 13 Jan 2022 23:05:53 -0800 +Subject: [PATCH] Add missing structure set seed configs + +The 4 missing structure set seed configs are strongholds, mineshafts, +buried treasure, and ancient cities. + +Strongholds use a ring placement scheme which isn't random so they +utilize the world seed by default, this adds a config to override it +for just generating the ring positions. + +Mineshafts and Buried Treasure structure sets are special cases +where the "salt" that can be defined for them via datapacks has 0 +effect because the difference between the spacing and separation is 1 +which is used as the upper bound in the random with salt. So the random +always returns the same int (0) so the salt has no effect. This adds +seeds/salts to the frequency reducer which has a similar effect. + +Co-authored-by: William Blake Galbreath + +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 cc79ca7ee770408ec59b1f6a3f4ec58e23bd2619..52264a583e79cc6adb9967aebac7f6b3ac129017 100644 +--- a/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java ++++ b/src/main/java/net/minecraft/world/level/chunk/ChunkGenerator.java +@@ -133,7 +133,7 @@ public abstract class ChunkGenerator { + // Spigot start + private Stream possibleStructureSetsSpigot() { + return this.possibleStructureSets().map(Holder::value).map((structureset) -> { +- if (structureset.placement() instanceof RandomSpreadStructurePlacement randomConfig) { ++ if (structureset.placement() instanceof RandomSpreadStructurePlacement randomConfig && this.structureSets.getKey(structureset).getNamespace().equals(net.minecraft.resources.ResourceLocation.DEFAULT_NAMESPACE)) { // Paper - check namespace cause datapacks could add structure sets with the same path + String name = this.structureSets.getKey(structureset).getPath(); + int seed = randomConfig.salt; + +@@ -180,6 +180,11 @@ public abstract class ChunkGenerator { + case "villages": + seed = conf.villageSeed; + break; ++ // Paper start ++ case "ancient_cities": ++ seed = conf.ancientCitySeed; ++ break; ++ // Paper end + } + + structureset = new StructureSet(structureset.structures(), new RandomSpreadStructurePlacement(randomConfig.locateOffset, randomConfig.frequencyReductionMethod, randomConfig.frequency, seed, randomConfig.exclusionZone, randomConfig.spacing(), randomConfig.separation(), randomConfig.spreadType())); +@@ -236,7 +241,13 @@ public abstract class ChunkGenerator { + HolderSet holderset = concentricringsstructureplacement.preferredBiomes(); + RandomSource randomsource = RandomSource.create(); + ++ // Paper start ++ if (this.conf.strongholdSeed != null && this.structureSets.getResourceKey(holder).orElse(null) == net.minecraft.world.level.levelgen.structure.BuiltinStructureSets.STRONGHOLDS) { ++ randomsource.setSeed(this.conf.strongholdSeed); ++ } else { + randomsource.setSeed(this instanceof FlatLevelSource ? 0L : randomstate.legacyLevelSeed()); ++ } ++ // Paper end + double d0 = randomsource.nextDouble() * 3.141592653589793D * 2.0D; + int l = 0; + int i1 = 0; +@@ -677,7 +688,7 @@ public abstract class ChunkGenerator { + + for (int i1 = chunkX - chunkRange; i1 <= chunkX + chunkRange; ++i1) { + for (int j1 = chunkZ - chunkRange; j1 <= chunkZ + chunkRange; ++j1) { +- if (structureplacement.isStructureChunk(this, noiseConfig, seed, i1, j1)) { ++ if (structureplacement.isStructureChunk(this, noiseConfig, seed, i1, j1, structureSet.unwrapKey().map(ResourceKey::location).orElse(null))) { // Paper + return true; + } + } +@@ -764,7 +775,7 @@ public abstract class ChunkGenerator { + } + } + +- if (structureplacement.isStructureChunk(this, noiseConfig, seed, chunkcoordintpair.x, chunkcoordintpair.z)) { ++ if (structureplacement.isStructureChunk(this, noiseConfig, seed, chunkcoordintpair.x, chunkcoordintpair.z, this.structureSets.getResourceKey(holder).map(ResourceKey::location).orElse(null))) { // Paper + if (list.size() == 1) { + this.tryGenerateStructure((StructureSet.StructureSelectionEntry) list.get(0), structureAccessor, registryManager, noiseConfig, structureTemplateManager, seed, chunk, chunkcoordintpair, sectionposition); + } else { +diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/placement/StructurePlacement.java b/src/main/java/net/minecraft/world/level/levelgen/structure/placement/StructurePlacement.java +index 2fd1284c7f0d8e2cf35d03072089256d990b06eb..8ef0e9fa126cd96289bab48eaa06c2a1fbe4281e 100644 +--- a/src/main/java/net/minecraft/world/level/levelgen/structure/placement/StructurePlacement.java ++++ b/src/main/java/net/minecraft/world/level/levelgen/structure/placement/StructurePlacement.java +@@ -59,10 +59,22 @@ public abstract class StructurePlacement { + return this.exclusionZone; + } + ++ @Deprecated @io.papermc.paper.annotation.DoNotUse // Paper + public boolean isStructureChunk(ChunkGenerator chunkGenerator, RandomState noiseConfig, long seed, int chunkX, int chunkZ) { ++ // Paper start - add missing structure set configs ++ return this.isStructureChunk(chunkGenerator, noiseConfig, seed, chunkX, chunkZ, null); ++ } ++ public boolean isStructureChunk(ChunkGenerator chunkGenerator, RandomState noiseConfig, long seed, int chunkX, int chunkZ, @org.jetbrains.annotations.Nullable net.minecraft.resources.ResourceLocation structureSetKey) { ++ Integer saltOverride = null; ++ if (net.minecraft.world.level.levelgen.structure.BuiltinStructureSets.MINESHAFTS.location().equals(structureSetKey)) { ++ saltOverride = chunkGenerator.conf.mineshaftSeed; ++ } else if (net.minecraft.world.level.levelgen.structure.BuiltinStructureSets.BURIED_TREASURES.location().equals(structureSetKey)) { ++ saltOverride = chunkGenerator.conf.buriedTreasureSeed; ++ } ++ // Paper end + if (!this.isPlacementChunk(chunkGenerator, noiseConfig, seed, chunkX, chunkZ)) { + return false; +- } else if (this.frequency < 1.0F && !this.frequencyReductionMethod.shouldGenerate(seed, this.salt, chunkX, chunkZ, this.frequency)) { ++ } else if (this.frequency < 1.0F && !this.frequencyReductionMethod.shouldGenerate(seed, this.salt, chunkX, chunkZ, this.frequency, saltOverride)) { // Paper + return false; + } else { + return !this.exclusionZone.isPresent() || !this.exclusionZone.get().isPlacementForbidden(chunkGenerator, noiseConfig, seed, chunkX, chunkZ); +@@ -77,25 +89,31 @@ public abstract class StructurePlacement { + + public abstract StructurePlacementType type(); + +- private static boolean probabilityReducer(long seed, int salt, int chunkX, int chunkZ, float frequency) { ++ private static boolean probabilityReducer(long seed, int salt, int chunkX, int chunkZ, float frequency, @org.jetbrains.annotations.Nullable Integer saltOverride) { // Paper - ignore here + WorldgenRandom worldgenRandom = new WorldgenRandom(new LegacyRandomSource(0L)); + worldgenRandom.setLargeFeatureWithSalt(seed, salt, chunkX, chunkZ); + return worldgenRandom.nextFloat() < frequency; + } + +- private static boolean legacyProbabilityReducerWithDouble(long seed, int salt, int chunkX, int chunkZ, float frequency) { ++ private static boolean legacyProbabilityReducerWithDouble(long seed, int salt, int chunkX, int chunkZ, float frequency, @org.jetbrains.annotations.Nullable Integer saltOverride) { // Paper + WorldgenRandom worldgenRandom = new WorldgenRandom(new LegacyRandomSource(0L)); ++ if (saltOverride == null) { // Paper + worldgenRandom.setLargeFeatureSeed(seed, chunkX, chunkZ); ++ // Paper start ++ } else { ++ worldgenRandom.setLargeFeatureWithSalt(seed, chunkX, chunkZ, saltOverride); ++ } ++ // Paper end + return worldgenRandom.nextDouble() < (double)frequency; + } + +- private static boolean legacyArbitrarySaltProbabilityReducer(long seed, int salt, int chunkX, int chunkZ, float frequency) { ++ private static boolean legacyArbitrarySaltProbabilityReducer(long seed, int salt, int chunkX, int chunkZ, float frequency, @org.jetbrains.annotations.Nullable Integer saltOverride) { // Paper + WorldgenRandom worldgenRandom = new WorldgenRandom(new LegacyRandomSource(0L)); +- worldgenRandom.setLargeFeatureWithSalt(seed, chunkX, chunkZ, 10387320); ++ worldgenRandom.setLargeFeatureWithSalt(seed, chunkX, chunkZ, saltOverride != null ? saltOverride : 10387320); // Paper + return worldgenRandom.nextFloat() < frequency; + } + +- private static boolean legacyPillagerOutpostReducer(long seed, int salt, int chunkX, int chunkZ, float frequency) { ++ private static boolean legacyPillagerOutpostReducer(long seed, int salt, int chunkX, int chunkZ, float frequency, @org.jetbrains.annotations.Nullable Integer saltOverride) { // Paper - ignore here + int i = chunkX >> 4; + int j = chunkZ >> 4; + WorldgenRandom worldgenRandom = new WorldgenRandom(new LegacyRandomSource(0L)); +@@ -118,7 +136,7 @@ public abstract class StructurePlacement { + + @FunctionalInterface + public interface FrequencyReducer { +- boolean shouldGenerate(long seed, int salt, int chunkX, int chunkZ, float chance); ++ boolean shouldGenerate(long seed, int salt, int chunkX, int chunkZ, float chance, @org.jetbrains.annotations.Nullable Integer saltOverride); // Paper + } + + public static enum FrequencyReductionMethod implements StringRepresentable { +@@ -136,8 +154,8 @@ public abstract class StructurePlacement { + this.reducer = generationPredicate; + } + +- public boolean shouldGenerate(long seed, int salt, int chunkX, int chunkZ, float chance) { +- return this.reducer.shouldGenerate(seed, salt, chunkX, chunkZ, chance); ++ public boolean shouldGenerate(long seed, int salt, int chunkX, int chunkZ, float chance, @org.jetbrains.annotations.Nullable Integer saltOverride) { // Paper ++ return this.reducer.shouldGenerate(seed, salt, chunkX, chunkZ, chance, saltOverride); // Paper + } + + @Override +diff --git a/src/main/java/org/spigotmc/SpigotWorldConfig.java b/src/main/java/org/spigotmc/SpigotWorldConfig.java +index cf96f9fdc4ae561f01d44503b9851c60140e4ea7..46ef3400605cc420bd88f13838df7d1f1106235e 100644 +--- a/src/main/java/org/spigotmc/SpigotWorldConfig.java ++++ b/src/main/java/org/spigotmc/SpigotWorldConfig.java +@@ -366,6 +366,16 @@ public class SpigotWorldConfig + public int mansionSeed; + public int fossilSeed; + public int portalSeed; ++ // Paper start - add missing structure set configs ++ public int ancientCitySeed; ++ public int buriedTreasureSeed; ++ public Integer mineshaftSeed; ++ public Long strongholdSeed; ++ private N getSeed(String path, java.util.function.Function toNumberFunc) { ++ final String value = this.getString(path, "default"); ++ return org.apache.commons.lang3.math.NumberUtils.isParsable(value) ? toNumberFunc.apply(value) : null; ++ } ++ // Paper end + private void initWorldGenSeeds() + { + this.villageSeed = this.getInt( "seed-village", 10387312 ); +@@ -383,6 +393,12 @@ public class SpigotWorldConfig + this.mansionSeed = this.getInt( "seed-mansion", 10387319 ); + this.fossilSeed = this.getInt( "seed-fossil", 14357921 ); + this.portalSeed = this.getInt( "seed-portal", 34222645 ); ++ // Paper start - add missing structure set configs ++ this.ancientCitySeed = this.getInt("seed-ancientcity", 20083232); ++ this.buriedTreasureSeed = this.getInt("seed-buriedtreasure", 10387320); // StructurePlacement#HIGHLY_ARBITRARY_RANDOM_SALT ++ this.mineshaftSeed = this.getSeed("seed-mineshaft", Integer::parseInt); ++ this.strongholdSeed = this.getSeed("seed-stronghold", Long::parseLong); ++ // Paper end + this.log( "Custom Map Seeds: Village: " + this.villageSeed + " Desert: " + this.desertSeed + " Igloo: " + this.iglooSeed + " Jungle: " + this.jungleSeed + " Swamp: " + this.swampSeed + " Monument: " + this.monumentSeed + + " Ocean: " + this.oceanSeed + " Shipwreck: " + this.shipwreckSeed + " End City: " + this.endCitySeed + " Slime: " + this.slimeSeed + " Nether: " + this.netherSeed + " Mansion: " + this.mansionSeed + " Fossil: " + this.fossilSeed + " Portal: " + this.portalSeed ); + }