added population data
This commit is contained in:
@@ -1,11 +1,9 @@
|
||||
package kaptainwutax.seedcracker;
|
||||
|
||||
import kaptainwutax.seedcracker.cracker.BiomeData;
|
||||
import kaptainwutax.seedcracker.cracker.PillarData;
|
||||
import kaptainwutax.seedcracker.cracker.StructureData;
|
||||
import kaptainwutax.seedcracker.cracker.TimeMachine;
|
||||
import kaptainwutax.seedcracker.cracker.*;
|
||||
import kaptainwutax.seedcracker.render.RenderQueue;
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.biome.layer.BiomeLayerSampler;
|
||||
import net.minecraft.world.biome.layer.BiomeLayers;
|
||||
import net.minecraft.world.biome.source.BiomeSourceType;
|
||||
@@ -16,6 +14,8 @@ import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class SeedCracker implements ModInitializer {
|
||||
|
||||
@@ -28,6 +28,7 @@ public class SeedCracker implements ModInitializer {
|
||||
|
||||
private TimeMachine timeMachine = new TimeMachine();
|
||||
private List<StructureData> structureCache = new ArrayList<>();
|
||||
private List<PopulationData> populationCache = new ArrayList<>();
|
||||
private List<BiomeData> biomeCache = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
@@ -74,7 +75,7 @@ public class SeedCracker implements ModInitializer {
|
||||
added = true;
|
||||
}
|
||||
|
||||
if(this.structureSeeds == null && this.pillarSeeds != null && this.structureCache.size() >= 5) {
|
||||
if(this.structureSeeds == null && this.pillarSeeds != null && this.structureCache.size() >= 3) {
|
||||
this.structureSeeds = new ArrayList<>();
|
||||
LOG.warn("Looking for structure seeds with " + this.structureCache.size() + " structure features.");
|
||||
|
||||
@@ -89,6 +90,7 @@ public class SeedCracker implements ModInitializer {
|
||||
}
|
||||
|
||||
this.structureCache.clear();
|
||||
this.onPopulationData(null);
|
||||
this.onBiomeData(null);
|
||||
} else if(this.structureSeeds != null && structureData != null) {
|
||||
this.structureSeeds.removeIf(structureSeed -> {
|
||||
@@ -103,6 +105,48 @@ public class SeedCracker implements ModInitializer {
|
||||
return added;
|
||||
}
|
||||
|
||||
public synchronized boolean onPopulationData(PopulationData populationData) {
|
||||
boolean added = false;
|
||||
|
||||
if(populationData != null && !this.populationCache.contains(populationData)) {
|
||||
this.populationCache.add(populationData);
|
||||
added = true;
|
||||
}
|
||||
|
||||
if(this.worldSeeds == null && this.structureSeeds != null && this.populationCache.size() >= 4) {
|
||||
this.worldSeeds = new ArrayList<>();
|
||||
LOG.warn("Looking for world seeds with " + this.populationCache.size() + " decorators.");
|
||||
|
||||
for(int i = 0; i < this.structureSeeds.size(); i++) {
|
||||
SeedCracker.LOG.warn("Progress " + (i * 100.0f) / this.structureSeeds.size() + "%...");
|
||||
|
||||
long structureSeed = this.structureSeeds.get(i);
|
||||
|
||||
for(long j = 0; j < (1L << 16); j++) {
|
||||
long worldSeed = (j << 48) | structureSeed;
|
||||
boolean goodSeed = true;
|
||||
|
||||
for(PopulationData data: this.populationCache) {
|
||||
if(!data.test(worldSeed)) {
|
||||
goodSeed = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(goodSeed) {
|
||||
this.worldSeeds.add(worldSeed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOG.warn("Finished search with " + this.worldSeeds + (this.worldSeeds.size() == 1 ? " seed." : " seeds."));
|
||||
} else if(this.worldSeeds != null && populationData != null) {
|
||||
this.worldSeeds.removeIf(worldSeed -> !populationData.test(worldSeed));
|
||||
}
|
||||
|
||||
return added;
|
||||
}
|
||||
|
||||
public synchronized boolean onBiomeData(BiomeData biomeData) {
|
||||
boolean added = false;
|
||||
|
||||
@@ -126,7 +170,7 @@ public class SeedCracker implements ModInitializer {
|
||||
BiomeLayerSampler sampler = BiomeLayers.build(worldSeed, LevelGeneratorType.DEFAULT,
|
||||
BiomeSourceType.VANILLA_LAYERED.getConfig().getGeneratorSettings())[1];
|
||||
|
||||
for (BiomeData data : this.biomeCache) {
|
||||
for(BiomeData data : this.biomeCache) {
|
||||
if (!data.test(worldSeed, sampler)) {
|
||||
goodSeed = false;
|
||||
break;
|
||||
@@ -150,148 +194,33 @@ public class SeedCracker implements ModInitializer {
|
||||
BiomeSourceType.VANILLA_LAYERED.getConfig().getGeneratorSettings())[1];
|
||||
return !biomeData.test(worldSeed, sampler);
|
||||
});
|
||||
} else if(this.worldSeeds != null) {
|
||||
this.worldSeeds.removeIf(worldSeed -> {
|
||||
for(BiomeData data: this.biomeCache) {
|
||||
BiomeLayerSampler sampler = BiomeLayers.build(worldSeed, LevelGeneratorType.DEFAULT,
|
||||
BiomeSourceType.VANILLA_LAYERED.getConfig().getGeneratorSettings())[1];
|
||||
if(!biomeData.test(worldSeed, sampler))return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
return added;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
/*
|
||||
//91,94,82,85,88,79,97,76,100,103
|
||||
SeedCracker cracker = new SeedCracker();
|
||||
List<Integer> heights = new ArrayList<>();
|
||||
heights.add(91);
|
||||
heights.add(94);
|
||||
heights.add(82);
|
||||
heights.add(85);
|
||||
heights.add(88);
|
||||
heights.add(79);
|
||||
heights.add(97);
|
||||
heights.add(76);
|
||||
heights.add(100);
|
||||
heights.add(103);
|
||||
Random rand = new Random(1234L);
|
||||
|
||||
List<StructureData> structureDataList = new ArrayList<>();
|
||||
structureDataList.add(new StructureData(new ChunkPos(-37, -95), StructureData.END_CITY));
|
||||
structureDataList.add(new StructureData(new ChunkPos(-57,-116), StructureData.END_CITY));
|
||||
structureDataList.add(new StructureData(new ChunkPos(-18, 204), StructureData.OCEAN_MONUMENT));
|
||||
structureDataList.add(new StructureData(new ChunkPos(-44, 109), StructureData.OCEAN_MONUMENT));
|
||||
structureDataList.add(new StructureData(new ChunkPos(14, -158), StructureData.DESERT_PYRAMID));
|
||||
|
||||
cracker.getSpikeSeeds(heights).forEach(seed -> {
|
||||
System.out.println("Found pillar seed: [" + seed + "].");
|
||||
|
||||
structureDataList.forEach(s -> {
|
||||
System.out.println("Structure data: [" + s.getSalt() + ", " + s.getOffsetX() + ", " + s.getOffsetZ() + "].");
|
||||
});
|
||||
|
||||
cracker.getStructureSeeds(seed, structureDataList).forEach(seed1 -> {
|
||||
System.out.println("Found structure seed: [" + seed1 + "].");
|
||||
|
||||
for(long i = 0; i < (1L << 16); i++) {
|
||||
long worldSeed = (i << 48) | seed1;
|
||||
BiomeLayerSampler[] biomeLayerSamplers = BiomeLayers.build(worldSeed, LevelGeneratorType.DEFAULT, BiomeSourceType.VANILLA_LAYERED.getConfig().getGeneratorSettings());
|
||||
//System.out.println(worldSeed + ", " + biomeLayerSamplers[0].sample(0, 0));
|
||||
}
|
||||
});
|
||||
});*/
|
||||
IntStream.range(0, 8).mapToObj((int_1x) -> {
|
||||
int int_2 = rand.nextInt(16);
|
||||
int int_3 = rand.nextInt(256);
|
||||
int int_4 = rand.nextInt(16);
|
||||
System.out.println("Created " + int_2 + ", " + int_3 + ", " + int_4);
|
||||
return new BlockPos(int_2, int_3, int_4);
|
||||
}).forEach(pos -> {
|
||||
System.out.println("Populating " + pos);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
public List<Integer> getSpikeHeights(long worldSeed) {
|
||||
Random rand = new Random(worldSeed);
|
||||
long pillarSeed = rand.nextLong() & 65535L;
|
||||
|
||||
List<Integer> indices = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
indices.add(i);
|
||||
}
|
||||
|
||||
Collections.shuffle(indices, new Random(pillarSeed));
|
||||
|
||||
List<Integer> heights = new ArrayList<>();
|
||||
|
||||
for (Integer index: indices) {
|
||||
heights.add(76 + index * 3);
|
||||
}
|
||||
|
||||
return heights;
|
||||
}
|
||||
|
||||
|
||||
protected ChunkPos getStart(ChunkGenerator<?> chunkGenerator_1, Random rand, int chunkX, int chunkZ) {
|
||||
int templeDistance = 32;
|
||||
int templeSeparation = 8;
|
||||
|
||||
chunkX = chunkX < 0 ? chunkX - templeDistance + 1 : chunkX;
|
||||
chunkZ = chunkZ < 0 ? chunkZ - templeDistance + 1 : chunkZ;
|
||||
|
||||
//Pick out in which region the chunk is.
|
||||
int regionX = chunkX / templeDistance;
|
||||
int regionZ = chunkZ / templeDistance;
|
||||
|
||||
((ChunkRandom)rand).setStructureSeed(chunkGenerator_1.getSeed(), regionX, regionZ, this.getSeedModifier());
|
||||
|
||||
//Convert it back to a chunk pos.
|
||||
regionX *= templeDistance;
|
||||
regionZ *= templeDistance;
|
||||
|
||||
//Add a random chunk offset.
|
||||
regionX += rand.nextInt(templeDistance - templeSeparation);
|
||||
regionZ += rand.nextInt(templeDistance - templeSeparation);
|
||||
|
||||
return new ChunkPos(regionX, regionZ);
|
||||
}
|
||||
|
||||
public void getTempleCalls(ChunkPos chunkPos) {
|
||||
int templeDistance = 32;
|
||||
|
||||
int chunkX = chunkPos.x;
|
||||
int chunkZ = chunkPos.z;
|
||||
|
||||
chunkX = chunkX < 0 ? chunkX - templeDistance + 1 : chunkX;
|
||||
chunkZ = chunkZ < 0 ? chunkZ - templeDistance + 1 : chunkZ;
|
||||
|
||||
//Pick out in which region the chunk is.
|
||||
int regionX = (chunkX / templeDistance) * templeDistance;
|
||||
int regionZ = (chunkZ / templeDistance) * templeDistance;
|
||||
|
||||
int offsetX = chunkPos.x - regionX;
|
||||
int offsetZ = chunkPos.z - regionZ;
|
||||
}
|
||||
|
||||
public boolean shouldStartAt(ChunkGenerator<?> chunkGen, Random random_1, int chunkX, int chunkZ) {
|
||||
ChunkPos startPosition = this.getStart(chunkGen, random_1, chunkX, chunkZ);
|
||||
|
||||
if(chunkX == startPosition.x && chunkZ == startPosition.z) {
|
||||
Biome biome = chunkGen.getBiomeSource().getBiome(new BlockPos(chunkX * 16 + 9, 0, chunkZ * 16 + 9));
|
||||
|
||||
if(chunkGen.hasStructure(biome, this)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public long setStructureSeed(long worldSeed, int regionX, int regionZ, int salt) {
|
||||
long seed = (long)regionX * 341873128712L + (long)regionZ * 132897987541L + worldSeed + (long)salt;
|
||||
seed = (seed ^ Rand.JAVA_LCG.multiplier) & (Rand.JAVA_LCG.modulo - 1);
|
||||
return seed;
|
||||
}
|
||||
|
||||
public void getStart(long worldSeed, int regionX, int regionZ, int salt) {
|
||||
long seed = this.setStructureSeed(worldSeed, regionX, regionZ, salt);
|
||||
int nextIntSeed = (int)(Rand.JAVA_LCG.nextSeed(seed) >>> (48 - 31));
|
||||
int chunkX = nextIntSeed % 24;
|
||||
nextIntSeed = (int)(Rand.JAVA_LCG.nextSeed(Rand.JAVA_LCG.nextSeed(seed)) >>> (48 - 31));
|
||||
int chunkZ = nextIntSeed % 24;
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package kaptainwutax.seedcracker.cracker;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.gen.ChunkRandom;
|
||||
import net.minecraft.world.gen.GenerationStep;
|
||||
import net.minecraft.world.gen.decorator.Decorator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class DungeonData extends PopulationData {
|
||||
|
||||
public static final Feature DUNGEON = new Feature(GenerationStep.Feature.UNDERGROUND_STRUCTURES, Decorator.DUNGEONS) {};
|
||||
public static final Integer COBBLESTONE_CALL = 0;
|
||||
public static final Integer MOSSY_COBBLESTONE_CALL = 1;
|
||||
|
||||
private List<BlockPos> starts;
|
||||
private final List<List<Integer>> floorCallsList;
|
||||
|
||||
public DungeonData(ChunkPos chunkPos, Biome biome, List<BlockPos> starts, List<List<Integer>> floorCallsList) {
|
||||
super(chunkPos, DUNGEON, biome);
|
||||
this.starts = starts;
|
||||
this.floorCallsList = floorCallsList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(ChunkRandom chunkRandom) {
|
||||
List<Integer> idsToCheck = new ArrayList<>();
|
||||
|
||||
for(int i = 0; i < 8; i++) {
|
||||
BlockPos pos = new BlockPos(chunkRandom.nextInt(16), chunkRandom.nextInt(256), chunkRandom.nextInt(16));
|
||||
int a = this.starts.indexOf(pos);
|
||||
if(a != -1)idsToCheck.add(a);
|
||||
|
||||
//We assume the dungeon failed, skip 2 calls.
|
||||
chunkRandom.nextBoolean();
|
||||
chunkRandom.nextBoolean();
|
||||
}
|
||||
|
||||
if(idsToCheck.size() != this.starts.size())return false;
|
||||
|
||||
//TODO: Implement floor calls.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package kaptainwutax.seedcracker.cracker;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.gen.ChunkRandom;
|
||||
import net.minecraft.world.gen.GenerationStep;
|
||||
import net.minecraft.world.gen.decorator.ConfiguredDecorator;
|
||||
import net.minecraft.world.gen.decorator.Decorator;
|
||||
import net.minecraft.world.gen.feature.ConfiguredFeature;
|
||||
import net.minecraft.world.gen.feature.DecoratedFeatureConfig;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public abstract class PopulationData {
|
||||
|
||||
private final ChunkPos chunkPos;
|
||||
private final Feature feature;
|
||||
private final Biome biome;
|
||||
|
||||
public PopulationData(ChunkPos chunkPos, Feature feature, Biome biome) {
|
||||
this.chunkPos = chunkPos;
|
||||
this.feature = feature;
|
||||
this.biome = biome;
|
||||
}
|
||||
|
||||
public final boolean test(long worldSeed) {
|
||||
ChunkRandom chunkRandom = this.feature.buildRand(worldSeed, this.biome, this.chunkPos);
|
||||
return this.test(chunkRandom);
|
||||
}
|
||||
|
||||
public abstract boolean test(ChunkRandom chunkRandom);
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if(obj == this)return true;
|
||||
|
||||
if(obj instanceof PopulationData) {
|
||||
PopulationData populationData = ((PopulationData)obj);
|
||||
return populationData.chunkPos.equals(this.chunkPos) && populationData.feature == this.feature;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public abstract static class Feature {
|
||||
private GenerationStep.Feature genStep;
|
||||
private Decorator decorator;
|
||||
|
||||
public Feature(GenerationStep.Feature genStep, Decorator decorator) {
|
||||
this.genStep = genStep;
|
||||
this.decorator = decorator;
|
||||
}
|
||||
|
||||
public ChunkRandom buildRand(long worldSeed, Biome biome, ChunkPos chunkPos) {
|
||||
List<ConfiguredFeature<?>> features = biome.getFeaturesForStep(this.genStep);
|
||||
|
||||
for(int i = 0; i < features.size(); i++) {
|
||||
ConfiguredFeature<?> feature = features.get(i);
|
||||
if(!(feature.config instanceof DecoratedFeatureConfig))continue;
|
||||
ConfiguredDecorator<?> currentDecorator = ((DecoratedFeatureConfig)feature.config).decorator;
|
||||
|
||||
if(currentDecorator.decorator == this.decorator) {
|
||||
BlockPos pos = new BlockPos(chunkPos.getStartX(), 0, chunkPos.getStartZ());
|
||||
ChunkRandom chunkRandom = new ChunkRandom();
|
||||
long populationSeed = chunkRandom.setSeed(worldSeed, pos.getX(), pos.getZ());
|
||||
chunkRandom.setFeatureSeed(populationSeed, i, this.genStep.ordinal());
|
||||
return chunkRandom;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -28,7 +28,7 @@ public class DungeonFeature extends DecorationFeature {
|
||||
|
||||
for(int xo = -dungeonSize.getX(); xo <= dungeonSize.getX(); xo++) {
|
||||
for(int zo = -dungeonSize.getZ(); zo <= dungeonSize.getZ(); zo++) {
|
||||
Block block = this.world.getBlockState(pos.add(xo, -1, zo)).getBlock();
|
||||
Block block = this.world.getBlockState(this.pos.add(xo, -1, zo)).getBlock();
|
||||
|
||||
if(block == Blocks.MOSSY_COBBLESTONE) {
|
||||
floorCalls.add(MOSSY_COBBLESTONE_CALL);
|
||||
|
||||
Reference in New Issue
Block a user