added population data

This commit is contained in:
Unknown
2019-11-27 07:17:57 -05:00
parent 8a959ad72a
commit de1487cbbf
4 changed files with 197 additions and 142 deletions
@@ -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);