it all works

This commit is contained in:
Unknown
2019-11-13 07:22:55 -05:00
parent ed1da66d99
commit 85f9072b9a
14 changed files with 208 additions and 58 deletions
+1
View File
@@ -23,3 +23,4 @@ bin/
# fabric
run/
logs/
@@ -23,6 +23,7 @@ public class FinderQueue {
this.finderBuilders.add(DesertTempleFinder::create);
this.finderBuilders.add(JungleTempleFinder::create);
this.finderBuilders.add(EndPillarsFinder::create);
this.finderBuilders.add(BiomeFinder::create);
}
public static FinderQueue get() {
@@ -6,7 +6,6 @@ import kaptainwutax.seedcracker.cracker.StructureData;
import kaptainwutax.seedcracker.cracker.TimeMachine;
import kaptainwutax.seedcracker.render.RenderQueue;
import net.fabricmc.api.ModInitializer;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.biome.layer.BiomeLayerSampler;
import net.minecraft.world.biome.layer.BiomeLayers;
import net.minecraft.world.biome.source.BiomeSourceType;
@@ -21,8 +20,9 @@ import java.util.List;
public class SeedCracker implements ModInitializer {
public static final Logger LOG = LogManager.getLogger("Seed Cracker");
private static final SeedCracker INSTANCE = new SeedCracker();
public List<Long> worldSeeds = null;
public List<Long> worldSeeds = null;
public List<Long> structureSeeds = null;
public List<Integer> pillarSeeds = null;
@@ -35,7 +35,11 @@ public class SeedCracker implements ModInitializer {
RenderQueue.get().add("hand", FinderQueue.get()::renderFinders);
}
public void reset() {
public static SeedCracker get() {
return INSTANCE;
}
public void clear() {
this.worldSeeds = null;
this.structureSeeds = null;
this.pillarSeeds = null;
@@ -45,7 +49,16 @@ public class SeedCracker implements ModInitializer {
public void onPillarData(PillarData pillarData) {
if(this.pillarSeeds == null) {
LOG.warn("Looking for pillar seeds...");
this.pillarSeeds = pillarData.getPillarSeeds();
if(this.pillarSeeds.size() > 0) {
LOG.warn("Finished search with " + this.pillarSeeds + (this.pillarSeeds.size() == 1 ? " seed." : " seeds."));
} else {
LOG.error("Finished search with no seeds.");
}
this.onStructureData(null);
}
}
@@ -55,13 +68,20 @@ public class SeedCracker implements ModInitializer {
this.structureCache.add(structureData);
}
if(this.structureSeeds == null && this.pillarSeeds != null && this.structureCache.size() >= 3) {
if(this.structureSeeds == null && this.pillarSeeds != null && this.structureCache.size() >= 5) {
this.structureSeeds = new ArrayList<>();
LOG.warn("Looking for structure seeds with " + this.structureCache.size() + " structure features.");
this.pillarSeeds.forEach(pillarSeed -> {
timeMachine.buildStructureSeeds(pillarSeed, this.structureCache, this.structureSeeds);
});
if(this.structureSeeds.size() > 0) {
LOG.warn("Finished search with " + this.structureSeeds.size() + (this.structureSeeds.size() == 1 ? " seed." : " seeds."));
} else {
LOG.error("Finished search with no seeds.");
}
this.structureCache.clear();
this.onBiomeData(null);
} else if(this.structureSeeds != null && structureData != null) {
@@ -76,21 +96,31 @@ public class SeedCracker implements ModInitializer {
}
}
public void onBiomeData(BiomeData biomeData) {
if(biomeData != null) {
public boolean onBiomeData(BiomeData biomeData) {
boolean added = false;
if(biomeData != null && !this.biomeCache.contains(biomeData)) {
this.biomeCache.add(biomeData);
added = true;
}
if(this.worldSeeds == null && this.structureSeeds != null && this.biomeCache.size() >= 3) {
if(this.worldSeeds == null && this.structureSeeds != null && this.biomeCache.size() >= 6) {
this.worldSeeds = new ArrayList<>();
LOG.warn("Looking for world seeds with " + this.biomeCache.size() + " biomes.");
this.structureSeeds.forEach(structureSeed -> {
for(long i = 0; i < (1L << 16); i++) {
long worldSeed = (i << 48) | structureSeed;
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;
BiomeLayerSampler sampler = BiomeLayers.build(worldSeed, LevelGeneratorType.DEFAULT,
BiomeSourceType.VANILLA_LAYERED.getConfig().getGeneratorSettings())[1];
for(BiomeData data: this.biomeCache) {
if(!data.test(worldSeed)) {
for (BiomeData data : this.biomeCache) {
if (!data.test(worldSeed, sampler)) {
goodSeed = false;
break;
}
@@ -100,17 +130,30 @@ public class SeedCracker implements ModInitializer {
this.worldSeeds.add(worldSeed);
}
}
});
}
if(this.worldSeeds.size() > 0) {
LOG.warn("Finished search with " + this.worldSeeds + (this.worldSeeds.size() == 1 ? " seed." : " seeds."));
} else {
LOG.error("Finished search with no seeds.");
}
this.biomeCache.clear();
} else if(this.worldSeeds != null && biomeData != null) {
this.worldSeeds.removeIf(worldSeed -> !biomeData.test(worldSeed));
this.worldSeeds.removeIf(worldSeed -> {
BiomeLayerSampler sampler = BiomeLayers.build(worldSeed, LevelGeneratorType.DEFAULT,
BiomeSourceType.VANILLA_LAYERED.getConfig().getGeneratorSettings())[1];
return !biomeData.test(worldSeed, sampler);
});
}
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<>();
@@ -148,7 +191,7 @@ public class SeedCracker implements ModInitializer {
//System.out.println(worldSeed + ", " + biomeLayerSamplers[0].sample(0, 0));
}
});
});
});*/
}
@@ -4,9 +4,6 @@ import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.layer.BiomeLayerSampler;
import net.minecraft.world.biome.layer.BiomeLayers;
import net.minecraft.world.biome.source.BiomeSourceType;
import net.minecraft.world.level.LevelGeneratorType;
public class BiomeData {
@@ -28,15 +25,19 @@ public class BiomeData {
this(x, z, Registry.BIOME.get(biomeId));
}
public boolean test(long worldSeed) {
BiomeLayerSampler[] samplers = this.buildLayerSamplers(worldSeed);
return samplers[0].sample(this.x, this.z) == this.biome;
public boolean test(long worldSeed, BiomeLayerSampler sampler) {
return sampler.sample(this.x, this.z) == this.biome;
}
private BiomeLayerSampler[] buildLayerSamplers(long worldSeed) {
return BiomeLayers.build(worldSeed, LevelGeneratorType.DEFAULT,
BiomeSourceType.VANILLA_LAYERED.getConfig().getGeneratorSettings()
);
@Override
public boolean equals(Object obj) {
if(obj == this)return true;
if(obj instanceof BiomeData) {
return ((BiomeData)obj).biome == this.biome;
}
return false;
}
}
@@ -9,8 +9,8 @@ public class PillarData {
private List<Integer> heights;
public PillarData() {
public PillarData(List<Integer> heights) {
this.heights = heights;
}
public List<Integer> getPillarSeeds() {
@@ -40,6 +40,17 @@ public class StructureData {
return this.feature.test(rand, this.offsetX, this.offsetZ);
}
@Override
public boolean equals(Object obj) {
if(obj == this)return true;
if(obj instanceof StructureData) {
return ((StructureData)obj).regionX == this.regionX && ((StructureData)obj).regionZ == this.regionZ;
}
return false;
}
public abstract static class Feature {
public final int salt;
public final int templeDistance;
@@ -138,4 +149,11 @@ public class StructureData {
}
};
public static final Feature BURIED_TREASURE = new Feature(10387320, 1) {
@Override
public boolean test(ChunkRandom rand, int x, int z) {
return rand.nextFloat() < 0.1f;
}
};
}
@@ -1,10 +1,12 @@
package kaptainwutax.seedcracker.cracker;
import kaptainwutax.seedcracker.SeedCracker;
import kaptainwutax.seedcracker.util.Rand;
import kaptainwutax.seedcracker.util.math.LCG;
import net.minecraft.world.gen.ChunkRandom;
import java.util.List;
import java.util.Set;
public class TimeMachine {
@@ -18,6 +20,10 @@ public class TimeMachine {
ChunkRandom chunkRandom = new ChunkRandom();
for(long i = 0; i < (1L << 32); i++) {
if((i & ((1L << 28) - 1)) == 0) {
SeedCracker.LOG.warn("Progress " + (i * 100.0f) / (1L << 32) + "%...");
}
long structureSeed = this.timeMachine(i, pillarSeed);
boolean goodSeed = true;
@@ -45,7 +51,7 @@ public class TimeMachine {
currentSeed |= (long)pillarSeed << 16;
currentSeed |= partialWorldSeed & 0xFFFFL;
currentSeed = inverseLCG.nextSeed(currentSeed);
currentSeed = this.inverseLCG.nextSeed(currentSeed);
currentSeed ^= Rand.JAVA_LCG.multiplier;
return currentSeed;
}
@@ -0,0 +1,57 @@
package kaptainwutax.seedcracker.finder;
import kaptainwutax.seedcracker.SeedCracker;
import kaptainwutax.seedcracker.cracker.BiomeData;
import kaptainwutax.seedcracker.render.Cube;
import net.minecraft.client.util.math.Vector4f;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.Heightmap;
import net.minecraft.world.World;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.dimension.DimensionType;
import java.util.ArrayList;
import java.util.List;
public class BiomeFinder extends Finder {
public BiomeFinder(World world, ChunkPos chunkPos) {
super(world, chunkPos);
}
@Override
public List<BlockPos> findInChunk() {
List<BlockPos> result = new ArrayList<>();
for(int x = 0; x < 16; x++) {
for(int z = 0; z < 16; z++) {
BlockPos blockPos = this.chunkPos.getCenterBlockPos().add(x, 0, z);
Biome biome = this.world.getBiome(blockPos);
if(SeedCracker.get().onBiomeData(new BiomeData(blockPos.getX(), blockPos.getZ(), biome))) {
blockPos = this.world.getTopPosition(Heightmap.Type.WORLD_SURFACE, blockPos).down();
result.add(blockPos);
}
}
}
result.forEach(pos -> {
this.renderers.add(new Cube(pos, new Vector4f(0.0f, 1.0f, 0.0f, 1.0f)));
});
return result;
}
@Override
public boolean isValidDimension(DimensionType dimension) {
return dimension == DimensionType.OVERWORLD;
}
public static List<Finder> create(World world, ChunkPos chunkPos) {
List<Finder> finders = new ArrayList<>();
finders.add(new BiomeFinder(world, chunkPos));
return finders;
}
}
@@ -1,5 +1,7 @@
package kaptainwutax.seedcracker.finder;
import kaptainwutax.seedcracker.SeedCracker;
import kaptainwutax.seedcracker.cracker.StructureData;
import kaptainwutax.seedcracker.render.Cube;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
@@ -33,7 +35,7 @@ public class BuriedTreasureFinder extends BlockFinder {
//Buried treasure chests always generate at (9, 9) within a chunk.
int localX = pos.getX() & 15;
int localZ = pos.getZ() & 15;
//if(localX != 9 || localZ != 9)return true;
if(localX != 9 || localZ != 9)return true;
return false;
});
@@ -57,7 +59,10 @@ public class BuriedTreasureFinder extends BlockFinder {
return false;
});
result.forEach(pos -> this.renderers.add(new Cube(pos, new Vector4f(1.0f, 1.0f, 0.0f, 1.0f))));
result.forEach(pos -> {
this.renderers.add(new Cube(pos, new Vector4f(1.0f, 1.0f, 0.0f, 1.0f)));
SeedCracker.get().onStructureData(new StructureData(this.chunkPos, StructureData.BURIED_TREASURE));
});
return result;
}
@@ -1,5 +1,7 @@
package kaptainwutax.seedcracker.finder;
import kaptainwutax.seedcracker.SeedCracker;
import kaptainwutax.seedcracker.cracker.StructureData;
import kaptainwutax.seedcracker.render.Cuboid;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
@@ -30,14 +32,18 @@ public class DesertTempleFinder extends AbstractTempleFinder {
result.forEach((pieceFinder, positions) -> {
positions.removeIf(pos -> {
Biome biome = world.getBiome(pos);
Biome biome = world.getBiome(pos.add(9, 0, 9));
if(!biome.hasStructureFeature(Feature.DESERT_PYRAMID))return true;
return false;
});
combinedResult.addAll(positions);
positions.forEach(pos -> this.renderers.add(new Cuboid(pos, pieceFinder.getLayout(), new Vector4f(1.0f, 0.0f, 1.0f, 1.0f))));
positions.forEach(pos -> {
this.renderers.add(new Cuboid(pos, pieceFinder.getLayout(), new Vector4f(1.0f, 0.0f, 1.0f, 1.0f)));
SeedCracker.get().onStructureData(new StructureData(this.chunkPos, StructureData.DESERT_PYRAMID));
});
});
return combinedResult;
@@ -1,33 +1,33 @@
package kaptainwutax.seedcracker.finder;
import kaptainwutax.seedcracker.SeedCracker;
import kaptainwutax.seedcracker.cracker.PillarData;
import kaptainwutax.seedcracker.render.Cube;
import net.minecraft.block.Blocks;
import net.minecraft.client.util.math.Vector4f;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3i;
import net.minecraft.world.World;
import net.minecraft.world.dimension.DimensionType;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class EndPillarsFinder extends Finder {
protected BedrockMarkerFinder[] bedrockMarkers = {
new BedrockMarkerFinder(this.world, this.chunkPos, new BlockPos(12, 0, 39)),
new BedrockMarkerFinder(this.world, this.chunkPos, new BlockPos(-13, 0, 39)),
new BedrockMarkerFinder(this.world, this.chunkPos, new BlockPos(-34, 0, 24)),
new BedrockMarkerFinder(this.world, this.chunkPos, new BlockPos(-42, 0, -1)),
new BedrockMarkerFinder(this.world, this.chunkPos, new BlockPos(-34, 0, -25)),
new BedrockMarkerFinder(this.world, this.chunkPos, new BlockPos(-13, 0, -40)),
new BedrockMarkerFinder(this.world, this.chunkPos, new BlockPos(12, 0, -40)),
new BedrockMarkerFinder(this.world, this.chunkPos, new BlockPos(33, 0, -25)),
new BedrockMarkerFinder(this.world, this.chunkPos, new BlockPos(42, 0, 0)),
new BedrockMarkerFinder(this.world, this.chunkPos, new BlockPos(33, 0, 24))
};
protected BedrockMarkerFinder[] bedrockMarkers = new BedrockMarkerFinder[10];
public EndPillarsFinder(World world, ChunkPos chunkPos) {
super(world, chunkPos);
for(int i = 0; i < this.bedrockMarkers.length; i++) {
int x = MathHelper.floor(42.0D * Math.cos(2.0D * (-Math.PI + (Math.PI / 10.0D) * (double)i)));
int z = MathHelper.floor(42.0D * Math.sin(2.0D * (-Math.PI + (Math.PI / 10.0D) * (double)i)));
this.bedrockMarkers[i] = new BedrockMarkerFinder(this.world, new ChunkPos(new BlockPos(x, 0, z)), new BlockPos(x, 0, z));
}
}
@Override
@@ -38,7 +38,10 @@ public class EndPillarsFinder extends Finder {
result.addAll(bedrockMarker.findInChunk());
}
result.forEach(pos -> this.renderers.add(new Cube(pos, new Vector4f(0.5f, 0.0f, 0.5f, 1.0f))));
if(result.size() == this.bedrockMarkers.length) {
result.forEach(pos -> this.renderers.add(new Cube(pos, new Vector4f(0.5f, 0.0f, 0.5f, 1.0f))));
SeedCracker.get().onPillarData(new PillarData(result.stream().map(Vec3i::getY).collect(Collectors.toList())));
}
return result;
}
@@ -56,21 +59,16 @@ public class EndPillarsFinder extends Finder {
public class BedrockMarkerFinder extends BlockFinder {
protected boolean isInChunk = true;
public BedrockMarkerFinder(World world, ChunkPos chunkPos, BlockPos xz) {
super(world, chunkPos, Blocks.BEDROCK);
int localX = xz.getX() & 15;
int localZ = xz.getZ() & 15;
if(chunkPos.getStartX() + localX != xz.getX() || chunkPos.getStartZ() + localZ != xz.getZ()) {
this.isInChunk = false;
return;
}
this.searchPositions.removeIf(pos -> {
if(pos.getX() != localX)return true;
if(pos.getY() < 76)return true;
if(pos.getY() > 76 + 3 * 10)return true;
if(pos.getZ() != localZ)return true;
return false;
});
@@ -78,7 +76,7 @@ public class EndPillarsFinder extends Finder {
@Override
public List<BlockPos> findInChunk() {
return this.isInChunk ? super.findInChunk() : new ArrayList<>();
return super.findInChunk();
}
@Override
@@ -1,5 +1,7 @@
package kaptainwutax.seedcracker.finder;
import kaptainwutax.seedcracker.SeedCracker;
import kaptainwutax.seedcracker.cracker.StructureData;
import kaptainwutax.seedcracker.render.Cuboid;
import net.minecraft.block.*;
import net.minecraft.block.enums.WallMountLocation;
@@ -30,14 +32,18 @@ public class JungleTempleFinder extends AbstractTempleFinder {
result.forEach((pieceFinder, positions) -> {
positions.removeIf(pos -> {
Biome biome = world.getBiome(pos);
Biome biome = world.getBiome(pos.add(9, 0, 9));
if(!biome.hasStructureFeature(Feature.JUNGLE_TEMPLE))return true;
return false;
});
combinedResult.addAll(positions);
positions.forEach(pos -> this.renderers.add(new Cuboid(pos, pieceFinder.getLayout(), new Vector4f(1.0f, 0.0f, 1.0f, 1.0f))));
positions.forEach(pos -> {
this.renderers.add(new Cuboid(pos, pieceFinder.getLayout(), new Vector4f(1.0f, 0.0f, 1.0f, 1.0f)));
SeedCracker.get().onStructureData(new StructureData(this.chunkPos, StructureData.JUNGLE_TEMPLE));
});
});
return combinedResult;
@@ -1,5 +1,7 @@
package kaptainwutax.seedcracker.finder;
import kaptainwutax.seedcracker.SeedCracker;
import kaptainwutax.seedcracker.cracker.StructureData;
import kaptainwutax.seedcracker.render.Cuboid;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
@@ -31,14 +33,18 @@ public class SwampHutFinder extends AbstractTempleFinder {
result.forEach((pieceFinder, positions) -> {
positions.removeIf(pos -> {
Biome biome = world.getBiome(pos);
Biome biome = world.getBiome(pos.add(9, 0, 9));
if(!biome.hasStructureFeature(Feature.SWAMP_HUT))return true;
return false;
});
combinedResult.addAll(positions);
positions.forEach(pos -> this.renderers.add(new Cuboid(pos, pieceFinder.getLayout(), new Vector4f(1.0f, 0.0f, 1.0f, 1.0f))));
positions.forEach(pos -> {
this.renderers.add(new Cuboid(pos, pieceFinder.getLayout(), new Vector4f(1.0f, 0.0f, 1.0f, 1.0f)));
SeedCracker.get().onStructureData(new StructureData(this.chunkPos, StructureData.SWAMP_HUT));
});
});
return combinedResult;
@@ -1,6 +1,7 @@
package kaptainwutax.seedcracker.mixin;
import kaptainwutax.seedcracker.FinderQueue;
import kaptainwutax.seedcracker.SeedCracker;
import net.minecraft.client.world.ClientWorld;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@@ -12,6 +13,7 @@ public abstract class ClientWorldMixin {
@Inject(method = "disconnect", at = @At("TAIL"))
private void disconnect(CallbackInfo ci) {
SeedCracker.get().clear();
FinderQueue.get().clear();
}