diff --git a/README.md b/README.md index f35e44c..d3e5898 100644 --- a/README.md +++ b/README.md @@ -1,33 +1 @@ -# SeedCracker - -## Installation - -Download and install the [fabric mod loader](https://fabricmc.net/use/). - -Then download the lastest [release](https://github.com/KaptainWutax/SeedCracker/releases) of SeedCracker and put the `.jar` file in the `%appdata%/.minecraft/mods/` folder. - -## Usage - -Launch minercaft with the fabric loader profile. - -Explore the world you want to crack the seed and find at least 5 structures or decorators (like Monument, Temple, Mansion, Treasure, Dungeon...), in the background while you explore the world, SeedCracker will collect biomes coordinates. - -Then go on the main End island to load the pillars and the seed cracking process should start and take arround one minute. - -## Usefull command - -renderer option: `/seed render outlines (ON/OFF/XRAY)` - -seed finder option: `/seed finder category (BIOMES/ORES/OTHERS/STRUCTURES) (ON/OFF)` - -## Video Tutorial - -https://youtu.be/1ChmLi9og8Q - -## Contributors - -[KaptainWutax](https://github.com/KaptainWutax) - the mod - -[neil](https://www.youtube.com/channel/UCbM3acUrR8Ku6pjgRUNPnbQ/featured) - video tutorial - -[Nekzuris](https://github.com/Nekzuris) - readme +SeedCracker diff --git a/gradle.properties b/gradle.properties index fed7f06..107467d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,12 +3,12 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://fabricmc.net/use - minecraft_version=1.15 - yarn_mappings=1.15+build.2 + minecraft_version=1.14.4 + yarn_mappings=1.14.4+build.15 loader_version=0.7.2+build.174 # Mod Properties - mod_version = 0.0.2-alpha + mod_version = 1.0.0 maven_group = kaptainwutax archives_base_name = seedcracker diff --git a/src/main/java/kaptainwutax/seedcracker/SeedCracker.java b/src/main/java/kaptainwutax/seedcracker/SeedCracker.java index 0805c1c..7d7037f 100644 --- a/src/main/java/kaptainwutax/seedcracker/SeedCracker.java +++ b/src/main/java/kaptainwutax/seedcracker/SeedCracker.java @@ -1,39 +1,95 @@ package kaptainwutax.seedcracker; -import io.netty.util.internal.ConcurrentSet; +import com.google.common.collect.Lists; import kaptainwutax.seedcracker.cracker.*; -import kaptainwutax.seedcracker.cracker.population.DecoratorData; -import kaptainwutax.seedcracker.cracker.structure.StructureData; +import kaptainwutax.seedcracker.cracker.population.PopulationData; import kaptainwutax.seedcracker.finder.FinderQueue; import kaptainwutax.seedcracker.render.RenderQueue; import kaptainwutax.seedcracker.util.Log; import kaptainwutax.seedcracker.util.Rand; import net.fabricmc.api.ModInitializer; -import net.minecraft.world.level.LevelProperties; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.math.MutableIntBoundingBox; +import net.minecraft.util.registry.Registry; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.biome.Biomes; +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.gen.ChunkRandom; +import net.minecraft.world.gen.feature.Feature; +import net.minecraft.world.gen.feature.StrongholdFeature; +import net.minecraft.world.level.LevelGeneratorType; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; -import java.util.Set; +import java.util.Random; public class SeedCracker implements ModInitializer { private static final SeedCracker INSTANCE = new SeedCracker(); - public long hashedWorldSeed = -1; - public List worldSeeds = null; - public Set structureSeeds = null; + public List structureSeeds = null; public List pillarSeeds = null; private TimeMachine timeMachine = new TimeMachine(); private List structureCache = new ArrayList<>(); - private List decoratorCache = new ArrayList<>(); + private List populationCache = new ArrayList<>(); private List biomeCache = new ArrayList<>(); - @Override + @Override public void onInitialize() { RenderQueue.get().add("hand", FinderQueue.get()::renderFinders); DecoratorCache.get().initialize(); + /* + System.out.println("FETCHING SEEDS============"); + long structureSeed = 29131954246896L; + ChunkPos chunkPos = new ChunkPos(117, 23); + + for(long j = 0; j < (1L << 16); j++) { + long worldSeed = (j << 48) | structureSeed; + + if(initialize(worldSeed).contains(chunkPos)) { + System.out.println(worldSeed); + this.checkWorldSeed(worldSeed, chunkPos); + } + } + System.out.println("FETCHING SEEDS============"); + */ + + /* + System.out.println(9348141881871L ^ Rand.JAVA_LCG.multiplier); + DungeonData data = new DungeonData(new ChunkPos(18, 8), Biomes.JUNGLE, new ArrayList<>(), new ArrayList<>()); + data.test(-2418316773073950375L); + + try { + BufferedWriter writer = new BufferedWriter(new FileWriter("kaktoos14.txt")); + + for(int i = 0; i < (1 << 16); i++) { + long worldSeed = 9368770777595L | ((long)i << 48); + + BiomeLayerSampler sampler = BiomeLayers.build(worldSeed, LevelGeneratorType.DEFAULT, + BiomeSourceType.VANILLA_LAYERED.getConfig().getGeneratorSettings())[1]; + + if(sampler.sample(8, 8) == Biomes.DESERT) { + writer.write(worldSeed + "\n"); + } + } + + writer.flush(); + writer.close(); + } catch (IOException e) { + e.printStackTrace(); + }*/ + } + + private void checkWorldSeed(long worldSeed, ChunkPos pos) { + StrongholdFeature.Start start = new StrongholdFeature.Start(Feature.STRONGHOLD, pos.x, pos.z, Biomes.PLAINS, MutableIntBoundingBox.empty(), 0, worldSeed); } public static SeedCracker get() { @@ -41,13 +97,12 @@ public class SeedCracker implements ModInitializer { } public void clear() { - this.hashedWorldSeed = -1; this.worldSeeds = null; this.structureSeeds = null; this.pillarSeeds = null; this.structureCache.clear(); this.biomeCache.clear(); - this.decoratorCache.clear(); + this.populationCache.clear(); } public synchronized boolean onPillarData(PillarData pillarData) { @@ -83,7 +138,7 @@ public class SeedCracker implements ModInitializer { Log.warn("Looking for structure seeds with " + this.populationCache.size() + " population features."); this.pillarSeeds.forEach(pillarSeed -> { - timeMachine.buildStructureSeeds(pillarSeed, this.structureCache, this.decoratorCache, this.structureSeeds); + timeMachine.buildStructureSeeds(pillarSeed, this.structureCache, this.populationCache, this.structureSeeds); }); if(this.structureSeeds.size() > 0) { @@ -93,12 +148,13 @@ public class SeedCracker implements ModInitializer { } this.structureCache.clear(); - this.onDecoratorData(null); + this.onPopulationData(null); this.onBiomeData(null); } else if(this.structureSeeds != null && structureData != null) { this.structureSeeds.removeIf(structureSeed -> { - Rand rand = new Rand(0L); - return !structureData.test(structureSeed, rand); + ChunkRandom chunkRandom = new ChunkRandom(); + chunkRandom.setStructureSeed(structureSeed, structureData.getRegionX(), structureData.getRegionZ(), structureData.getSalt()); + return !structureData.test(chunkRandom); }); this.onBiomeData(null); @@ -107,11 +163,11 @@ public class SeedCracker implements ModInitializer { return added; } - public synchronized boolean onDecoratorData(DecoratorData decoratorData) { + public synchronized boolean onPopulationData(PopulationData populationData) { boolean added = false; - if(decoratorData != null && !this.decoratorCache.contains(decoratorData)) { - this.decoratorCache.add(decoratorData); + if(populationData != null && !this.populationCache.contains(populationData)) { + this.populationCache.add(populationData); added = true; } @@ -134,33 +190,16 @@ public class SeedCracker implements ModInitializer { for(int i = 0; i < this.structureSeeds.size(); i++) { Log.warn("Progress " + (i * 100.0f) / this.structureSeeds.size() + "%..."); - for(long structureSeed: this.structureSeeds) { - for(long j = 0; j < (1L << 16); j++) { - long worldSeed = (j << 48) | structureSeed; - long hash = LevelProperties.sha256Hash(worldSeed); + long structureSeed = this.structureSeeds.get(i); - if(hash == this.hashedWorldSeed) { - this.worldSeeds.add(worldSeed); - Log.warn("Finished search with " + this.worldSeeds + (this.worldSeeds.size() == 1 ? " seed." : " seeds.")); - return added; - } - } - } - - Log.error("Finished search with no seeds, reverting to biomes."); - } - - Log.warn("Looking for world seeds with " + this.biomeCache.size() + " biomes."); - - this.structureSeeds.forEach(structureSeed -> { - for(long j = 0; j < (1L << 16); j++) { + for (long j = 0; j < (1L << 16); j++) { long worldSeed = (j << 48) | structureSeed; boolean goodSeed = true; - - FakeBiomeSource fakeBiomeSource = new FakeBiomeSource(worldSeed); + BiomeLayerSampler sampler = BiomeLayers.build(worldSeed, LevelGeneratorType.DEFAULT, + BiomeSourceType.VANILLA_LAYERED.getConfig().getGeneratorSettings())[1]; for(BiomeData data : this.biomeCache) { - if(!data.test(fakeBiomeSource)) { + if (!data.test(worldSeed, sampler)) { goodSeed = false; break; } @@ -170,7 +209,7 @@ 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.")); @@ -179,14 +218,16 @@ public class SeedCracker implements ModInitializer { } } else if(this.worldSeeds != null && biomeData != null) { this.worldSeeds.removeIf(worldSeed -> { - FakeBiomeSource fakeBiomeSource = new FakeBiomeSource(worldSeed); - return !biomeData.test(fakeBiomeSource); + BiomeLayerSampler sampler = BiomeLayers.build(worldSeed, LevelGeneratorType.DEFAULT, + 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) { - FakeBiomeSource fakeBiomeSource = new FakeBiomeSource(worldSeed); - if(!data.test(fakeBiomeSource))return true; + BiomeLayerSampler sampler = BiomeLayers.build(worldSeed, LevelGeneratorType.DEFAULT, + BiomeSourceType.VANILLA_LAYERED.getConfig().getGeneratorSettings())[1]; + if(!biomeData.test(worldSeed, sampler))return true; } return false; @@ -196,4 +237,116 @@ public class SeedCracker implements ModInitializer { return added; } + public static void main(String[] args) throws Exception { + for(int i = 0; i < 10000; i++) { + Rand rand = new Rand(i, false); + if(rand.nextInt(700) == 0)System.out.println(i); + } + + /*Random rand = new Random(1234L); + + 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); + });*/ + + /* + System.out.println(validSeed(65867021031296932L)); + + BufferedReader reader = new BufferedReader(new FileReader("run/seeds.txt")); + BufferedWriter writer = new BufferedWriter(new FileWriter("run/kaktoos14.txt")); + + while(reader.ready()) { + long seed = Long.parseLong(reader.readLine().split(Pattern.quote(" "))[0]); + seed ^= Rand.JAVA_LCG.multiplier; + seed -= 60007; + + writer.write(seed + "===========================================\n"); + + for(int i = 0; i < (1 << 16); i++) { + long worldSeed = seed | ((long)i << 48); + + BiomeLayerSampler sampler = BiomeLayers.build(worldSeed, LevelGeneratorType.DEFAULT, + BiomeSourceType.VANILLA_LAYERED.getConfig().getGeneratorSettings())[1]; + + if(sampler.sample(8, 8) == Biomes.DESERT) { + writer.write(worldSeed + "\n"); + } + } + + writer.flush(); + } + + writer.close();*/ + } + + private static List initialize(long worldSeed) { + BiomeLayerSampler sampler = BiomeLayers.build(worldSeed, LevelGeneratorType.DEFAULT, + BiomeSourceType.VANILLA_LAYERED.getConfig().getGeneratorSettings())[0]; + + List startPositions = new ArrayList<>(); + List validBiomes = Lists.newArrayList(); + Iterator biomeIterator = Registry.BIOME.iterator(); + + while(biomeIterator.hasNext()) { + Biome biome = (Biome)biomeIterator.next(); + if(biome != null && biome.hasStructureFeature(Feature.STRONGHOLD)) { + validBiomes.add(biome); + } + } + + Random rand = new Random(worldSeed); + double randomRadian = rand.nextDouble() * Math.PI * 2.0D; + + //Actually 128, but we don't care about all of them. + for(int i = 0; i < 3; ++i) { + double double_2 = 128.0D + (rand.nextDouble() - 0.5D) * 80.0D; + int x = (int)Math.round(Math.cos(randomRadian) * double_2); + int z = (int)Math.round(Math.sin(randomRadian) * double_2); + + BlockPos locatedPos = locateBiome(sampler, (x << 4) + 8, (z << 4) + 8, 112, validBiomes, rand); + + if(locatedPos != null) { + x = locatedPos.getX() >> 4; + z = locatedPos.getZ() >> 4; + } + + startPositions.add(new ChunkPos(x, z)); + randomRadian += (Math.PI * 2.0D) / 3.0d; + } + + return startPositions; + } + + public static BlockPos locateBiome(BiomeLayerSampler sampler, int x, int z, int size, List validBiomes, Random rand) { + int int_4 = x - size >> 2; + int int_5 = z - size >> 2; + int int_6 = x + size >> 2; + int int_7 = z + size >> 2; + int int_8 = int_6 - int_4 + 1; + int int_9 = int_7 - int_5 + 1; + Biome[] biomeSample = sampler.sample(int_4, int_5, int_8, int_9); + BlockPos pos = null; + int int_10 = 0; + + for(int i = 0; i < int_8 * int_9; ++i) { + int int_12 = int_4 + i % int_8 << 2; + int int_13 = int_5 + i / int_8 << 2; + if (validBiomes.contains(biomeSample[i])) { + if(pos == null || rand.nextInt(int_10 + 1) == 0) { + pos = new BlockPos(int_12, 0, int_13); + } + + ++int_10; + } + } + + return pos; + } + } diff --git a/src/main/java/kaptainwutax/seedcracker/cracker/BiomeData.java b/src/main/java/kaptainwutax/seedcracker/cracker/BiomeData.java index 97231fd..268f66a 100644 --- a/src/main/java/kaptainwutax/seedcracker/cracker/BiomeData.java +++ b/src/main/java/kaptainwutax/seedcracker/cracker/BiomeData.java @@ -3,7 +3,7 @@ package kaptainwutax.seedcracker.cracker; import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; import net.minecraft.world.biome.Biome; -import net.minecraft.world.biome.source.VoronoiBiomeAccessType; +import net.minecraft.world.biome.layer.BiomeLayerSampler; public class BiomeData { @@ -25,20 +25,8 @@ public class BiomeData { this(x, z, Registry.BIOME.get(biomeId)); } - public boolean test(FakeBiomeSource source) { - return VoronoiBiomeAccessType.INSTANCE.getBiome(source.getHashedSeed(), this.x,0, this.z, source) == this.biome; - } - - public int getX() { - return this.x; - } - - public int getZ() { - return this.z; - } - - public Biome getBiome() { - return this.biome; + public boolean test(long worldSeed, BiomeLayerSampler sampler) { + return sampler.sample(this.x, this.z) == this.biome; } @Override diff --git a/src/main/java/kaptainwutax/seedcracker/cracker/DecoratorCache.java b/src/main/java/kaptainwutax/seedcracker/cracker/DecoratorCache.java index 261bfec..dc05b5e 100644 --- a/src/main/java/kaptainwutax/seedcracker/cracker/DecoratorCache.java +++ b/src/main/java/kaptainwutax/seedcracker/cracker/DecoratorCache.java @@ -39,7 +39,7 @@ public class DecoratorCache { } private void initializeBiomeStep(Biome biome, GenerationStep.Feature genStep) { - List> features = biome.getFeaturesForStep(genStep); + List> features = biome.getFeaturesForStep(genStep); for(int i = 0; i < features.size(); i++) { FeatureConfig config = features.get(i).config; diff --git a/src/main/java/kaptainwutax/seedcracker/cracker/FakeBiomeSource.java b/src/main/java/kaptainwutax/seedcracker/cracker/FakeBiomeSource.java deleted file mode 100644 index cf7968c..0000000 --- a/src/main/java/kaptainwutax/seedcracker/cracker/FakeBiomeSource.java +++ /dev/null @@ -1,49 +0,0 @@ -package kaptainwutax.seedcracker.cracker; - -import com.google.common.collect.ImmutableSet; -import net.minecraft.world.biome.Biome; -import net.minecraft.world.biome.Biomes; -import net.minecraft.world.biome.layer.BiomeLayers; -import net.minecraft.world.biome.source.BiomeLayerSampler; -import net.minecraft.world.biome.source.BiomeSource; -import net.minecraft.world.gen.chunk.OverworldChunkGeneratorConfig; -import net.minecraft.world.level.LevelGeneratorType; -import net.minecraft.world.level.LevelProperties; - -import java.util.Set; - -public class FakeBiomeSource extends BiomeSource { - - public static final OverworldChunkGeneratorConfig CHUNK_GEN_CONFIG = new OverworldChunkGeneratorConfig(); - - private static final Set BIOMES; - private final BiomeLayerSampler biomeSampler; - - private long seed; - private long hashedSeed; - - public FakeBiomeSource(long worldSeed) { - super(BIOMES); - this.seed = worldSeed; - this.hashedSeed = LevelProperties.sha256Hash(worldSeed); - this.biomeSampler = BiomeLayers.build(this.seed, LevelGeneratorType.DEFAULT, CHUNK_GEN_CONFIG); - } - - @Override - public Biome getBiomeForNoiseGen(int biomeX, int biomeY, int biomeZ) { - return this.biomeSampler.sample(biomeX, biomeZ); - } - - public long getSeed() { - return this.seed; - } - - public long getHashedSeed() { - return this.hashedSeed; - } - - static { - BIOMES = ImmutableSet.of(Biomes.OCEAN, Biomes.PLAINS, Biomes.DESERT, Biomes.MOUNTAINS, Biomes.FOREST, Biomes.TAIGA, Biomes.SWAMP, Biomes.RIVER, Biomes.FROZEN_OCEAN, Biomes.FROZEN_RIVER, Biomes.SNOWY_TUNDRA, Biomes.SNOWY_MOUNTAINS, Biomes.MUSHROOM_FIELDS, Biomes.MUSHROOM_FIELD_SHORE, Biomes.BEACH, Biomes.DESERT_HILLS, Biomes.WOODED_HILLS, Biomes.TAIGA_HILLS, Biomes.MOUNTAIN_EDGE, Biomes.JUNGLE, Biomes.JUNGLE_HILLS, Biomes.JUNGLE_EDGE, Biomes.DEEP_OCEAN, Biomes.STONE_SHORE, Biomes.SNOWY_BEACH, Biomes.BIRCH_FOREST, Biomes.BIRCH_FOREST_HILLS, Biomes.DARK_FOREST, Biomes.SNOWY_TAIGA, Biomes.SNOWY_TAIGA_HILLS, Biomes.GIANT_TREE_TAIGA, Biomes.GIANT_TREE_TAIGA_HILLS, Biomes.WOODED_MOUNTAINS, Biomes.SAVANNA, Biomes.SAVANNA_PLATEAU, Biomes.BADLANDS, Biomes.WOODED_BADLANDS_PLATEAU, Biomes.BADLANDS_PLATEAU, Biomes.WARM_OCEAN, Biomes.LUKEWARM_OCEAN, Biomes.COLD_OCEAN, Biomes.DEEP_WARM_OCEAN, Biomes.DEEP_LUKEWARM_OCEAN, Biomes.DEEP_COLD_OCEAN, Biomes.DEEP_FROZEN_OCEAN, Biomes.SUNFLOWER_PLAINS, Biomes.DESERT_LAKES, Biomes.GRAVELLY_MOUNTAINS, Biomes.FLOWER_FOREST, Biomes.TAIGA_MOUNTAINS, Biomes.SWAMP_HILLS, Biomes.ICE_SPIKES, Biomes.MODIFIED_JUNGLE, Biomes.MODIFIED_JUNGLE_EDGE, Biomes.TALL_BIRCH_FOREST, Biomes.TALL_BIRCH_HILLS, Biomes.DARK_FOREST_HILLS, Biomes.SNOWY_TAIGA_MOUNTAINS, Biomes.GIANT_SPRUCE_TAIGA, Biomes.GIANT_SPRUCE_TAIGA_HILLS, Biomes.MODIFIED_GRAVELLY_MOUNTAINS, Biomes.SHATTERED_SAVANNA, Biomes.SHATTERED_SAVANNA_PLATEAU, Biomes.ERODED_BADLANDS, Biomes.MODIFIED_WOODED_BADLANDS_PLATEAU, Biomes.MODIFIED_BADLANDS_PLATEAU); - } - -} diff --git a/src/main/java/kaptainwutax/seedcracker/cracker/PillarData.java b/src/main/java/kaptainwutax/seedcracker/cracker/PillarData.java index ba1c7d9..acba647 100644 --- a/src/main/java/kaptainwutax/seedcracker/cracker/PillarData.java +++ b/src/main/java/kaptainwutax/seedcracker/cracker/PillarData.java @@ -7,39 +7,39 @@ import java.util.Random; public class PillarData { - private List heights; + private List heights; - public PillarData(List heights) { - this.heights = heights; - } + public PillarData(List heights) { + this.heights = heights; + } - public List getPillarSeeds() { - List result = new ArrayList<>(); + public List getPillarSeeds() { + List result = new ArrayList<>(); - for(int pillarSeed = 0; pillarSeed < (1 << 16); pillarSeed++) { - List h = this.getPillarHeights(pillarSeed); - if(h.equals(this.heights)) result.add(pillarSeed); - } + for(int pillarSeed = 0; pillarSeed < (1 << 16); pillarSeed++) { + List h = this.getPillarHeights(pillarSeed); + if(h.equals(heights))result.add(pillarSeed); + } - return result; - } + return result; + } - public List getPillarHeights(int spikeSeed) { - List indices = new ArrayList<>(); + public List getPillarHeights(int spikeSeed) { + List indices = new ArrayList<>(); - for(int i = 0; i < 10; i++) { - indices.add(i); - } + for (int i = 0; i < 10; i++) { + indices.add(i); + } - Collections.shuffle(indices, new Random(spikeSeed)); + Collections.shuffle(indices, new Random(spikeSeed)); - List heights = new ArrayList<>(); + List heights = new ArrayList<>(); - for(Integer index : indices) { - heights.add(76 + index * 3); - } + for (Integer index: indices) { + heights.add(76 + index * 3); + } - return heights; - } + return heights; + } } diff --git a/src/main/java/kaptainwutax/seedcracker/cracker/StructureData.java b/src/main/java/kaptainwutax/seedcracker/cracker/StructureData.java new file mode 100644 index 0000000..6338445 --- /dev/null +++ b/src/main/java/kaptainwutax/seedcracker/cracker/StructureData.java @@ -0,0 +1,172 @@ +package kaptainwutax.seedcracker.cracker; + +import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.gen.ChunkRandom; + +public class StructureData { + + private int regionX; + private int regionZ; + private int offsetX; + private int offsetZ; + private Feature feature; + + public StructureData(ChunkPos chunkPos, Feature feature) { + this.feature = feature; + this.feature.build(this, chunkPos); + } + + public int getRegionX() { + return this.regionX; + } + + public int getRegionZ() { + return this.regionZ; + } + + public int getOffsetX() { + return this.offsetX; + } + + public int getOffsetZ() { + return this.offsetZ; + } + + public int getSalt() { + return this.feature.salt; + } + + public Feature getFeature() { + return this.feature; + } + + public boolean test(ChunkRandom rand) { + return this.feature.test(rand, this.offsetX, this.offsetZ); + } + + @Override + public boolean equals(Object obj) { + if(obj == this)return true; + + if(obj instanceof StructureData) { + StructureData structureData = ((StructureData)obj); + return structureData.regionX == this.regionX && structureData.regionZ == this.regionZ && structureData.feature == this.feature; + } + + return false; + } + + public abstract static class Feature { + public final int salt; + public final int distance; + + public Feature(int salt, int distance) { + this.salt = salt; + this.distance = distance; + } + + public void build(StructureData data, ChunkPos chunkPos) { + int chunkX = chunkPos.x; + int chunkZ = chunkPos.z; + + chunkX = chunkX < 0 ? chunkX - this.distance + 1 : chunkX; + chunkZ = chunkZ < 0 ? chunkZ - this.distance + 1 : chunkZ; + + //Pick out in which region the chunk is. + int regionX = (chunkX / this.distance); + int regionZ = (chunkZ / this.distance); + + data.regionX = regionX; + data.regionZ = regionZ; + + regionX *= this.distance; + regionZ *= this.distance; + + data.offsetX = chunkPos.x - regionX; + data.offsetZ = chunkPos.z - regionZ; + } + + public abstract boolean test(ChunkRandom rand, int x, int z); + } + + public static final Feature DESERT_PYRAMID = new Feature(14357617, 32) { + @Override + public boolean test(ChunkRandom rand, int x, int z) { + return rand.nextInt(24) == x && rand.nextInt(24) == z; + } + }; + + public static final Feature IGLOO = new Feature(14357618, 32) { + @Override + public boolean test(ChunkRandom rand, int x, int z) { + return rand.nextInt(24) == x && rand.nextInt(24) == z; + } + }; + + public static final Feature JUNGLE_TEMPLE = new Feature(14357619, 32) { + @Override + public boolean test(ChunkRandom rand, int x, int z) { + return rand.nextInt(24) == x && rand.nextInt(24) == z; + } + }; + + public static final Feature SWAMP_HUT = new Feature(14357620, 32) { + @Override + public boolean test(ChunkRandom rand, int x, int z) { + return rand.nextInt(24) == x && rand.nextInt(24) == z; + } + }; + + public static final Feature OCEAN_RUIN = new Feature(14357621, 16) { + @Override + public boolean test(ChunkRandom rand, int x, int z) { + return rand.nextInt(8) == x && rand.nextInt(8) == z; + } + }; + + public static final Feature SHIPWRECK = new Feature(165745295, 16) { + @Override + public boolean test(ChunkRandom rand, int x, int z) { + return rand.nextInt(8) == x && rand.nextInt(8) == z; + } + }; + + public static final Feature PILLAGER_OUTPOST = new Feature(165745296, 32) { + @Override + public boolean test(ChunkRandom rand, int x, int z) { + return rand.nextInt(24) == x && rand.nextInt(24) == z; + } + }; + + public static final Feature END_CITY = new Feature(10387313, 20) { + @Override + public boolean test(ChunkRandom rand, int x, int z) { + return (rand.nextInt(9) + rand.nextInt(9)) / 2 == x + && (rand.nextInt(9) + rand.nextInt(9)) / 2 == z; + } + }; + + public static final Feature OCEAN_MONUMENT = new Feature(10387313, 32) { + @Override + public boolean test(ChunkRandom rand, int x, int z) { + return (rand.nextInt(27) + rand.nextInt(27)) / 2 == x + && (rand.nextInt(27) + rand.nextInt(27)) / 2 == z; + } + }; + + 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; + } + }; + + public static final Feature WOODLAND_MANSION = new Feature(10387319, 80) { + @Override + public boolean test(ChunkRandom rand, int x, int z) { + return (rand.nextInt(60) + rand.nextInt(60)) / 2 == x + && (rand.nextInt(60) + rand.nextInt(60)) / 2 == z; + } + }; + +} diff --git a/src/main/java/kaptainwutax/seedcracker/cracker/TimeMachine.java b/src/main/java/kaptainwutax/seedcracker/cracker/TimeMachine.java index 14beb04..d7d2d1c 100644 --- a/src/main/java/kaptainwutax/seedcracker/cracker/TimeMachine.java +++ b/src/main/java/kaptainwutax/seedcracker/cracker/TimeMachine.java @@ -5,82 +5,46 @@ import kaptainwutax.seedcracker.cracker.population.PopulationData; import kaptainwutax.seedcracker.util.Log; import kaptainwutax.seedcracker.util.Rand; import kaptainwutax.seedcracker.util.math.LCG; +import net.minecraft.world.gen.ChunkRandom; -import java.util.ArrayList; import java.util.List; -import java.util.Set; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.atomic.AtomicInteger; public class TimeMachine { - + private LCG inverseLCG = Rand.JAVA_LCG.combine(-2); - public int THREAD_COUNT = 4; - public ExecutorService SERVICE = Executors.newFixedThreadPool(THREAD_COUNT); - - private boolean isRunning = false; public TimeMachine() { } - public List bruteforceRegion(int pillarSeed, int region, long size, List structureDataList, List decoratorDataList) { - List result = new ArrayList<>(); - Rand rand = new Rand(0L); + public List buildStructureSeeds(int pillarSeed, List structureDataList, List populationDataList, List structureSeeds) { + ChunkRandom chunkRandom = new ChunkRandom(); for(long i = 0; i < (1L << 32); i++) { if((i & ((1L << 28) - 1)) == 0) { Log.warn("Progress " + (i * 100.0f) / (1L << 32) + "%..."); } - for(long i = start; i < end; i++) { long structureSeed = this.timeMachine(i, pillarSeed); boolean goodSeed = true; for(StructureData structureData: structureDataList) { if(!goodSeed)break; - if(!structureData.test(structureSeed, rand))goodSeed = false; + chunkRandom.setStructureSeed(structureSeed, structureData.getRegionX(), + structureData.getRegionZ(), structureData.getSalt()); + if(!structureData.test(chunkRandom))goodSeed = false; } - for(DecoratorData decoratorData : decoratorDataList) { + for(PopulationData populationData: populationDataList) { if(!goodSeed)break; - if(!decoratorData.test(structureSeed))goodSeed = false; + if(!populationData.test(structureSeed))goodSeed = false; } if(goodSeed) { - result.add(structureSeed); + structureSeeds.add(structureSeed); } } - return result; - } - - public Set buildStructureSeeds(int pillarSeed, List structureDataList, List decoratorDataList, Set structureSeeds) { - if(this.isRunning) { - throw new IllegalStateException("Time Machine is already running"); - } - - this.isRunning = true; - long size = (long)Math.ceil((double)(1L << 32) / THREAD_COUNT); - AtomicInteger progress = new AtomicInteger(); - - for(int i = 0; i < THREAD_COUNT; i++) { - int finalI = i; - - SERVICE.submit(() -> { - structureSeeds.addAll(this.bruteforceRegion(pillarSeed, finalI, size, structureDataList, decoratorDataList)); - Log.warn("Completed thread " + finalI + "!"); - progress.getAndIncrement(); - }); - } - - while(progress.get() < THREAD_COUNT) { - try {Thread.sleep(20);} - catch(InterruptedException e) {e.printStackTrace();} - } - - this.isRunning = false; return structureSeeds; } @@ -95,8 +59,4 @@ public class TimeMachine { return currentSeed; } - public void stop() { - this.isRunning = false; - } - } diff --git a/src/main/java/kaptainwutax/seedcracker/cracker/population/DecoratorData.java b/src/main/java/kaptainwutax/seedcracker/cracker/population/DecoratorData.java deleted file mode 100644 index 55c73e9..0000000 --- a/src/main/java/kaptainwutax/seedcracker/cracker/population/DecoratorData.java +++ /dev/null @@ -1,56 +0,0 @@ -package kaptainwutax.seedcracker.cracker.population; - -import kaptainwutax.seedcracker.cracker.DecoratorCache; -import kaptainwutax.seedcracker.util.Rand; -import net.minecraft.util.math.ChunkPos; -import net.minecraft.world.biome.Biome; -import net.minecraft.world.gen.decorator.Decorator; - -public abstract class DecoratorData { - - private final ChunkPos chunkPos; - private final Decorator decorator; - private final Biome biome; - - public DecoratorData(ChunkPos chunkPos, Decorator decorator, Biome biome) { - this.chunkPos = chunkPos; - this.decorator = decorator; - this.biome = biome; - } - - public final boolean test(long structureSeed) { - long decoratorSeed = this.getPopulationSeed(structureSeed, this.chunkPos.x << 4, this.chunkPos.z << 4); - int salt = DecoratorCache.get().getSalt(this.biome, this.decorator, true); - - if(salt == DecoratorCache.INVALID) { - return false; - } - - decoratorSeed += salt; - decoratorSeed ^= Rand.JAVA_LCG.multiplier; - decoratorSeed &= Rand.JAVA_LCG.modulo - 1; - return this.testDecorator(new Rand(decoratorSeed, false)); - } - - public long getPopulationSeed(long structureSeed, int x, int z) { - Rand rand = new Rand(structureSeed, true); - long a = rand.nextLong() | 1L; - long b = rand.nextLong() | 1L; - return (long)x * a + (long)z * b ^ structureSeed; - } - - public abstract boolean testDecorator(Rand rand); - - @Override - public boolean equals(Object obj) { - if(obj == this)return true; - - if(obj instanceof DecoratorData) { - DecoratorData decoratorData = ((DecoratorData)obj); - return decoratorData.chunkPos.equals(this.chunkPos) && decoratorData.decorator == this.decorator; - } - - return false; - } - -} diff --git a/src/main/java/kaptainwutax/seedcracker/cracker/population/DungeonData.java b/src/main/java/kaptainwutax/seedcracker/cracker/population/DungeonData.java index 621fcc3..6aad60b 100644 --- a/src/main/java/kaptainwutax/seedcracker/cracker/population/DungeonData.java +++ b/src/main/java/kaptainwutax/seedcracker/cracker/population/DungeonData.java @@ -9,7 +9,7 @@ import net.minecraft.world.gen.decorator.Decorator; import java.util.List; -public class DungeonData extends DecoratorData { +public class DungeonData extends PopulationData { public static LCG REVERSE_SKIP = Rand.JAVA_LCG.combine(-1); public static LCG Y_START_SKIP = Rand.JAVA_LCG.combine(2); @@ -28,26 +28,33 @@ public class DungeonData extends DecoratorData { } @Override - public boolean testDecorator(Rand rand) { + public boolean testDecorator(long decoratorSeed) { if(this.starts.isEmpty())return true; //TODO: This currently only supports 1 dungeon per chunk. BlockPos start = this.starts.get(0); + long currentSeed = decoratorSeed; + boolean valid = false; + for(int i = 0; i < 8; i++) { - int x = rand.nextInt(16); - int z = rand.nextInt(16); - int y = rand.nextInt(256); + currentSeed = i == 0 ? Y_START_SKIP.nextSeed(currentSeed) : Y_SKIP.nextSeed(currentSeed); - if(y == start.getY() && x == start.getX() && z == start.getZ()) { - return true; + if(currentSeed >> 40 == start.getY()) { + valid = true; + break; } - - rand.nextInt(2); - rand.nextInt(2); } - return false; + if(!valid)return false; + + int x = (int)(REVERSE_SKIP.nextSeed(currentSeed) >> 44); + if(x != start.getX())return false; + + int z = (int)(Rand.JAVA_LCG.nextSeed(currentSeed) >> 44); + if(z != start.getZ())return false; + + return true; } } diff --git a/src/main/java/kaptainwutax/seedcracker/cracker/population/EmeraldOreData.java b/src/main/java/kaptainwutax/seedcracker/cracker/population/EmeraldOreData.java index 947594e..68236f5 100644 --- a/src/main/java/kaptainwutax/seedcracker/cracker/population/EmeraldOreData.java +++ b/src/main/java/kaptainwutax/seedcracker/cracker/population/EmeraldOreData.java @@ -10,7 +10,7 @@ import net.minecraft.world.gen.decorator.Decorator; import java.util.List; import java.util.stream.Collectors; -public class EmeraldOreData extends DecoratorData { +public class EmeraldOreData extends PopulationData { public static final LCG[] SKIP = { Rand.JAVA_LCG.combine(0), @@ -30,18 +30,19 @@ public class EmeraldOreData extends DecoratorData { } @Override - public boolean testDecorator(Rand rand) { + public boolean testDecorator(long decoratorSeed) { if(this.starts.isEmpty())return true; //TODO: This currently only supports 1 emerald per chunk. BlockPos start = this.starts.get(0); + Rand rand = new Rand(decoratorSeed, false); int b = rand.nextInt(6); for(int i = 0; i < b + 3; i++) { int x = rand.nextInt(16); - int z = rand.nextInt(16); int y = rand.nextInt(28) + 4; + int z = rand.nextInt(16); if(y == start.getY() && x == start.getX() && z == start.getZ()) { return true; diff --git a/src/main/java/kaptainwutax/seedcracker/cracker/population/EndGatewayData.java b/src/main/java/kaptainwutax/seedcracker/cracker/population/EndGatewayData.java index ef9d24e..896bbe7 100644 --- a/src/main/java/kaptainwutax/seedcracker/cracker/population/EndGatewayData.java +++ b/src/main/java/kaptainwutax/seedcracker/cracker/population/EndGatewayData.java @@ -6,7 +6,7 @@ import net.minecraft.util.math.ChunkPos; import net.minecraft.world.biome.Biome; import net.minecraft.world.gen.decorator.Decorator; -public class EndGatewayData extends DecoratorData { +public class EndGatewayData extends PopulationData { private int xOffset; private int zOffset; @@ -20,7 +20,9 @@ public class EndGatewayData extends DecoratorData { } @Override - public boolean testDecorator(Rand rand) { + public boolean testDecorator(long decoratorSeed) { + Rand rand = new Rand(decoratorSeed, false); + if(rand.nextInt(700) != 0)return false; if(rand.nextInt(16) != this.xOffset)return false; if(rand.nextInt(16) != this.zOffset)return false; diff --git a/src/main/java/kaptainwutax/seedcracker/cracker/population/PopulationData.java b/src/main/java/kaptainwutax/seedcracker/cracker/population/PopulationData.java new file mode 100644 index 0000000..55b3a01 --- /dev/null +++ b/src/main/java/kaptainwutax/seedcracker/cracker/population/PopulationData.java @@ -0,0 +1,104 @@ +package kaptainwutax.seedcracker.cracker.population; + +import kaptainwutax.seedcracker.cracker.DecoratorCache; +import kaptainwutax.seedcracker.util.Rand; +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.HashMap; +import java.util.List; +import java.util.Map; + +public abstract class PopulationData { + + private final ChunkPos chunkPos; + private final Decorator decorator; + private final Biome biome; + + public PopulationData(ChunkPos chunkPos, Decorator decorator, Biome biome) { + this.chunkPos = chunkPos; + this.decorator = decorator; + this.biome = biome; + } + + public final boolean test(long structureSeed) { + long decoratorSeed = this.getPopulationSeed(structureSeed, this.chunkPos.x << 4, this.chunkPos.z << 4); + int salt = DecoratorCache.get().getSalt(this.biome, this.decorator, true); + + if(salt == DecoratorCache.INVALID) { + return false; + } + + decoratorSeed += salt; + decoratorSeed ^= Rand.JAVA_LCG.multiplier; + decoratorSeed &= Rand.JAVA_LCG.modulo - 1; + return this.testDecorator(decoratorSeed); + } + + public long getPopulationSeed(long structureSeed, int x, int z) { + Rand rand = new Rand(structureSeed, true); + long a = rand.nextLong() | 1L; + long b = rand.nextLong() | 1L; + return (long)x * a + (long)z * b ^ structureSeed; + } + + public abstract boolean testDecorator(long decoratorSeed); + + @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.decorator == this.decorator; + } + + return false; + } + + + public abstract static class Feature { + private Map CACHE = new HashMap<>(); + + 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) { + if(CACHE.containsKey(biome)) { + return new ChunkRandom(CACHE.get(biome)); + } + + List> 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()); + long seed = chunkRandom.setFeatureSeed(populationSeed, i, this.genStep.ordinal()); + CACHE.put(biome, seed ^ Rand.JAVA_LCG.multiplier); + return chunkRandom; + } + } + + return null; + } + } + +} diff --git a/src/main/java/kaptainwutax/seedcracker/cracker/structure/StructureData.java b/src/main/java/kaptainwutax/seedcracker/cracker/structure/StructureData.java deleted file mode 100644 index 219a96e..0000000 --- a/src/main/java/kaptainwutax/seedcracker/cracker/structure/StructureData.java +++ /dev/null @@ -1,42 +0,0 @@ -package kaptainwutax.seedcracker.cracker.structure; - -import kaptainwutax.seedcracker.cracker.structure.type.FeatureType; -import kaptainwutax.seedcracker.util.Seeds; -import kaptainwutax.seedcracker.util.Rand; -import net.minecraft.util.math.ChunkPos; - -public class StructureData { - - public int chunkX; - public int chunkZ; - public int regionX; - public int regionZ; - public int offsetX; - public int offsetZ; - private final int salt; - private FeatureType featureType; - - public StructureData(ChunkPos chunkPos, FeatureType featureType) { - this.featureType = featureType; - this.salt = this.featureType.salt; - this.featureType.build(this, chunkPos); - } - - public boolean test(long structureSeed, Rand rand) { - Seeds.setRegionSeed(rand, structureSeed, this.regionX, this.regionZ, this.salt); - return this.featureType.test(rand, this, structureSeed); - } - - @Override - public boolean equals(Object obj) { - if(obj == this)return true; - - if(obj instanceof StructureData) { - StructureData structureData = ((StructureData)obj); - return structureData.regionX == this.regionX && structureData.regionZ == this.regionZ && structureData.featureType == this.featureType; - } - - return false; - } - -} diff --git a/src/main/java/kaptainwutax/seedcracker/cracker/structure/StructureFeatures.java b/src/main/java/kaptainwutax/seedcracker/cracker/structure/StructureFeatures.java deleted file mode 100644 index c7f58ab..0000000 --- a/src/main/java/kaptainwutax/seedcracker/cracker/structure/StructureFeatures.java +++ /dev/null @@ -1,62 +0,0 @@ -package kaptainwutax.seedcracker.cracker.structure; - -import kaptainwutax.seedcracker.cracker.structure.type.AbstractTempleType; -import kaptainwutax.seedcracker.cracker.structure.type.FeatureType; -import kaptainwutax.seedcracker.cracker.structure.type.RarityType; -import kaptainwutax.seedcracker.cracker.structure.type.TriangularType; -import kaptainwutax.seedcracker.util.Rand; -import kaptainwutax.seedcracker.util.Seeds; - -public class StructureFeatures { - - public static final FeatureType DESERT_PYRAMID = new AbstractTempleType(14357617, 32, 24); - - public static final FeatureType IGLOO = new AbstractTempleType(14357618, 32, 24); - - public static final FeatureType JUNGLE_TEMPLE = new AbstractTempleType(14357619, 32, 24); - - public static final FeatureType SWAMP_HUT = new AbstractTempleType(14357620, 32, 24); - - public static final FeatureType OCEAN_RUIN = new AbstractTempleType(14357621, 16, 8); - - public static final FeatureType SHIPWRECK = new AbstractTempleType(165745295, 16, 8); - - public static final FeatureType PILLAGER_OUTPOST = new AbstractTempleType(165745296, 32, 24) { - @Override - public boolean test(Rand rand, StructureData data, long structureSeed) { - if(!super.test(rand, data, structureSeed))return false; - Seeds.setWeakSeed(rand, structureSeed, data.chunkX, data.chunkZ); - return rand.nextInt(5) == 0; - } - }; - - public static final FeatureType VILLAGE = new AbstractTempleType(10387312, 32, 24); - - public static final FeatureType END_CITY = new TriangularType(10387313, 20, 9); - - public static final FeatureType OCEAN_MONUMENT = new TriangularType(10387313, 32, 27); - - public static final FeatureType WOODLAND_MANSION = new TriangularType(10387319, 80, 60); - - public static final FeatureType BURIED_TREASURE = new RarityType(10387320, 1, 0.01F); - - public static final FeatureType NETHER_FORTRESS = new FeatureType(-1, 1) { - @Override - public boolean test(Rand rand, StructureData data, long structureSeed) { - Seeds.setWeakSeed(rand, structureSeed, data.chunkX, data.chunkZ); - - return rand.nextInt(3) == 0 - && data.chunkX == ((data.chunkX >> 4) << 4) + 4 + rand.nextInt(8) - && data.chunkZ == ((data.chunkZ >> 4) << 4) + 4 + rand.nextInt(8); - } - }; - - public static final FeatureType MINESHAFT = new FeatureType(-1, 1) { - @Override - public boolean test(Rand rand, StructureData data, long structureSeed) { - Seeds.setStructureStartSeed(rand, structureSeed, data.chunkX, data.chunkZ); - return rand.nextDouble() < 0.004D; - } - }; - -} diff --git a/src/main/java/kaptainwutax/seedcracker/cracker/structure/type/AbstractTempleType.java b/src/main/java/kaptainwutax/seedcracker/cracker/structure/type/AbstractTempleType.java deleted file mode 100644 index 76b842f..0000000 --- a/src/main/java/kaptainwutax/seedcracker/cracker/structure/type/AbstractTempleType.java +++ /dev/null @@ -1,20 +0,0 @@ -package kaptainwutax.seedcracker.cracker.structure.type; - -import kaptainwutax.seedcracker.cracker.structure.StructureData; -import kaptainwutax.seedcracker.util.Rand; - -public class AbstractTempleType extends FeatureType { - - protected final int offset; - - public AbstractTempleType(int salt, int distance, int offset) { - super(salt, distance); - this.offset = offset; - } - - @Override - public boolean test(Rand rand, StructureData data, long structureSeed) { - return rand.nextInt(this.offset) == data.offsetX && rand.nextInt(this.offset) == data.offsetZ; - } - -} diff --git a/src/main/java/kaptainwutax/seedcracker/cracker/structure/type/FeatureType.java b/src/main/java/kaptainwutax/seedcracker/cracker/structure/type/FeatureType.java deleted file mode 100644 index 1f0057a..0000000 --- a/src/main/java/kaptainwutax/seedcracker/cracker/structure/type/FeatureType.java +++ /dev/null @@ -1,43 +0,0 @@ -package kaptainwutax.seedcracker.cracker.structure.type; - -import kaptainwutax.seedcracker.cracker.structure.StructureData; -import kaptainwutax.seedcracker.util.Rand; -import net.minecraft.util.math.ChunkPos; - -public abstract class FeatureType { - - public final int salt; - public final int distance; - - public FeatureType(int salt, int distance) { - this.salt = salt; - this.distance = distance; - } - - public void build(T data, ChunkPos chunkPos) { - int chunkX = chunkPos.x; - int chunkZ = chunkPos.z; - - data.chunkX = chunkX; - data.chunkZ = chunkZ; - - chunkX = chunkX < 0 ? chunkX - this.distance + 1 : chunkX; - chunkZ = chunkZ < 0 ? chunkZ - this.distance + 1 : chunkZ; - - //Pick out in which region the chunk is. - int regionX = (chunkX / this.distance); - int regionZ = (chunkZ / this.distance); - - data.regionX = regionX; - data.regionZ = regionZ; - - regionX *= this.distance; - regionZ *= this.distance; - - data.offsetX = chunkPos.x - regionX; - data.offsetZ = chunkPos.z - regionZ; - } - - public abstract boolean test(Rand rand, T data, long structureSeed); - -} diff --git a/src/main/java/kaptainwutax/seedcracker/cracker/structure/type/RarityType.java b/src/main/java/kaptainwutax/seedcracker/cracker/structure/type/RarityType.java deleted file mode 100644 index bcf4db0..0000000 --- a/src/main/java/kaptainwutax/seedcracker/cracker/structure/type/RarityType.java +++ /dev/null @@ -1,20 +0,0 @@ -package kaptainwutax.seedcracker.cracker.structure.type; - -import kaptainwutax.seedcracker.cracker.structure.StructureData; -import kaptainwutax.seedcracker.util.Rand; - -public class RarityType extends FeatureType { - - private float rarity; - - public RarityType(int salt, int distance, float rarity) { - super(salt, distance); - this.rarity = rarity; - } - - @Override - public boolean test(Rand rand, StructureData data, long structureSeed) { - return rand.nextFloat() < this.rarity; - } - -} diff --git a/src/main/java/kaptainwutax/seedcracker/cracker/structure/type/TriangularType.java b/src/main/java/kaptainwutax/seedcracker/cracker/structure/type/TriangularType.java deleted file mode 100644 index b7467d5..0000000 --- a/src/main/java/kaptainwutax/seedcracker/cracker/structure/type/TriangularType.java +++ /dev/null @@ -1,22 +0,0 @@ -package kaptainwutax.seedcracker.cracker.structure.type; - - -import kaptainwutax.seedcracker.cracker.structure.StructureData; -import kaptainwutax.seedcracker.util.Rand; - -public class TriangularType extends FeatureType { - - protected final int peak; - - public TriangularType(int salt, int distance, int peak) { - super(salt, distance); - this.peak = peak; - } - - @Override - public boolean test(Rand rand, StructureData data, long structureSeed) { - return (rand.nextInt(this.peak) + rand.nextInt(this.peak)) / 2 == data.offsetX - && (rand.nextInt(this.peak) + rand.nextInt(this.peak)) / 2 == data.offsetZ; - } - -} diff --git a/src/main/java/kaptainwutax/seedcracker/feature/decoration/DecorationFeature.java b/src/main/java/kaptainwutax/seedcracker/feature/decoration/DecorationFeature.java new file mode 100644 index 0000000..811406e --- /dev/null +++ b/src/main/java/kaptainwutax/seedcracker/feature/decoration/DecorationFeature.java @@ -0,0 +1,23 @@ +package kaptainwutax.seedcracker.feature.decoration; + +import net.minecraft.block.Block; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public abstract class DecorationFeature { + + protected World world; + protected BlockPos pos; + + public DecorationFeature(World world, BlockPos pos) { + this.world = world; + this.pos = pos; + } + + public abstract void reverseSeed(); + + public Block getBlockAt(BlockPos pos) { + return this.world.getBlockState(pos).getBlock(); + } + +} diff --git a/src/main/java/kaptainwutax/seedcracker/feature/decoration/DungeonFeature.java b/src/main/java/kaptainwutax/seedcracker/feature/decoration/DungeonFeature.java new file mode 100644 index 0000000..6b33bf6 --- /dev/null +++ b/src/main/java/kaptainwutax/seedcracker/feature/decoration/DungeonFeature.java @@ -0,0 +1,91 @@ +package kaptainwutax.seedcracker.feature.decoration; + +import kaptainwutax.seedcracker.util.Rand; +import net.minecraft.block.Block; +import net.minecraft.block.Blocks; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3i; +import net.minecraft.world.World; + +import java.util.ArrayList; +import java.util.List; + +public class DungeonFeature extends DecorationFeature { + + private static int MOSSY_COBBLESTONE_CALL = 0; + private static int COBBLESTONE_CALL = 1; + + public DungeonFeature(World world, BlockPos pos) { + super(world, pos); + } + + @Override + public void reverseSeed() { + BlockPos decoratorPos = this.getLocalPos(this.pos); + Vec3i dungeonSize = this.getDungeonSize(this.pos); + + List floorCalls = new ArrayList<>(); + + for(int xo = -dungeonSize.getX(); xo <= dungeonSize.getX(); xo++) { + for(int zo = -dungeonSize.getZ(); zo <= dungeonSize.getZ(); zo++) { + Block block = this.world.getBlockState(this.pos.add(xo, -1, zo)).getBlock(); + + if(block == Blocks.MOSSY_COBBLESTONE) { + floorCalls.add(MOSSY_COBBLESTONE_CALL); + } else if(block == Blocks.COBBLESTONE) { + floorCalls.add(COBBLESTONE_CALL); + } + } + } + + List dungeonSeeds = this.getDungeonSeeds(dungeonSize, floorCalls); + List decoratorSeeds = new ArrayList<>(); + + for(long dungeonSeed: dungeonSeeds) { + long decoratorSeed = Rand.JAVA_LCG.combine(-3).nextSeed(dungeonSeed); + Rand rand = new Rand(decoratorSeed, false); + if(rand.nextInt(16) != decoratorPos.getX())continue; + if(rand.nextInt(256) != decoratorPos.getY())continue; + if(rand.nextInt(16) != decoratorPos.getZ())continue; + decoratorSeeds.add(decoratorSeed); + } + + decoratorSeeds.forEach(System.out::println); + } + + public BlockPos getLocalPos(BlockPos pos) { + return new BlockPos(pos.getX() & 15, pos.getY(), pos.getZ() & 15); + } + + public Vec3i getDungeonSize(BlockPos spawnerPos) { + for(int xo = 4; xo >= 3; xo--) { + for(int zo = 4; zo >= 3; zo--) { + Block block = this.getBlockAt(spawnerPos.add(xo, -1, zo)); + if(block != Blocks.MOSSY_COBBLESTONE)continue; + if(block != Blocks.COBBLESTONE)continue; + return new Vec3i(xo, 0, zo); + } + } + + return Vec3i.ZERO; + } + + public List getDungeonSeeds(Vec3i dungeonSize, List floorCalls) { + List floorSeeds = new ArrayList<>(); + + //TODO: Lattice magic to find floorSeeds from floorCalls. + + List dungeonSeeds = new ArrayList<>(); + + for(long floorSeed: floorSeeds) { + long dungeonSeed = Rand.JAVA_LCG.combine(-2).nextSeed(floorSeed); + Rand rand = new Rand(dungeonSeed, false); + if(rand.nextInt(2) + 3 != dungeonSize.getX())continue; + if(rand.nextInt(2) + 3 != dungeonSize.getZ())continue; + dungeonSeeds.add(dungeonSeed); + } + + return dungeonSeeds; + } + +} diff --git a/src/main/java/kaptainwutax/seedcracker/finder/BiomeFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/BiomeFinder.java index d92abe1..34eace5 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/BiomeFinder.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/BiomeFinder.java @@ -9,7 +9,6 @@ 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.biome.Biomes; import net.minecraft.world.dimension.DimensionType; import java.util.ArrayList; @@ -30,11 +29,6 @@ public class BiomeFinder extends Finder { BlockPos blockPos = this.chunkPos.getCenterBlockPos().add(x, 0, z); Biome biome = this.world.getBiome(blockPos); - //TODO: Fix this multi-threading issue. - if(biome == Biomes.THE_VOID) { - continue; - } - if(SeedCracker.get().onBiomeData(new BiomeData(blockPos.getX(), blockPos.getZ(), biome))) { blockPos = this.world.getTopPosition(Heightmap.Type.WORLD_SURFACE, blockPos).down(); result.add(blockPos); diff --git a/src/main/java/kaptainwutax/seedcracker/finder/BlockFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/BlockFinder.java index 4d5f351..280e459 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/BlockFinder.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/BlockFinder.java @@ -17,7 +17,7 @@ public abstract class BlockFinder extends Finder { public BlockFinder(World world, ChunkPos chunkPos, Block block) { super(world, chunkPos); - this.targetBlockStates.addAll(block.getStateManager().getStates()); + this.targetBlockStates.addAll(block.getStateFactory().getStates()); } public BlockFinder(World world, ChunkPos chunkPos, BlockState... blockStates) { diff --git a/src/main/java/kaptainwutax/seedcracker/finder/DefaultFinderConfig.java b/src/main/java/kaptainwutax/seedcracker/finder/DefaultFinderConfig.java index 865411a..5ea5391 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/DefaultFinderConfig.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/DefaultFinderConfig.java @@ -3,6 +3,7 @@ package kaptainwutax.seedcracker.finder; public class DefaultFinderConfig extends FinderConfig { public DefaultFinderConfig() { + super(); this.typeStates.put(Type.DIAMOND_ORE, false); this.typeStates.put(Type.INFESTED_STONE_ORE, false); this.typeStates.put(Type.IGLOO, false); diff --git a/src/main/java/kaptainwutax/seedcracker/finder/Finder.java b/src/main/java/kaptainwutax/seedcracker/finder/Finder.java index 8b2cbd3..09e9946 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/Finder.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/Finder.java @@ -55,17 +55,16 @@ public abstract class Finder { DimensionType playerDim = mc.player.world.dimension.getType(); if(finderDim != playerDim)return false; - - int renderDistance = mc.options.viewDistance * 16 + 16; Vec3d playerPos = mc.player.getPos(); - for(Renderer renderer: this.renderers) { - BlockPos pos = renderer.getPos(); - double distance = playerPos.squaredDistanceTo(pos.getX(), playerPos.y, pos.getZ()); - if(distance <= renderDistance * renderDistance + 32)return true; - } + double distance = playerPos.squaredDistanceTo( + this.chunkPos.x * 16, + playerPos.y, + this.chunkPos.z * 16 + ); - return false; + int renderDistance = mc.options.viewDistance * 16 + 16; + return distance <= renderDistance * renderDistance + 32; } public void render() { diff --git a/src/main/java/kaptainwutax/seedcracker/finder/FinderConfig.java b/src/main/java/kaptainwutax/seedcracker/finder/FinderConfig.java index d69a16a..c00650c 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/FinderConfig.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/FinderConfig.java @@ -75,7 +75,6 @@ public class FinderConfig { MONUMENT(OceanMonumentFinder::create, Category.STRUCTURES), SWAMP_HUT(SwampHutFinder::create, Category.STRUCTURES), MANSION(MansionFinder::create, Category.STRUCTURES), - SHIPWRECK(ShipwreckFinder::create, Category.STRUCTURES), END_PILLARS(EndPillarsFinder::create, Category.OTHERS), END_GATEWAY(EndGatewayFinder::create, Category.OTHERS), diff --git a/src/main/java/kaptainwutax/seedcracker/finder/FinderQueue.java b/src/main/java/kaptainwutax/seedcracker/finder/FinderQueue.java index bdb31cb..882332a 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/FinderQueue.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/FinderQueue.java @@ -1,8 +1,6 @@ package kaptainwutax.seedcracker.finder; import com.mojang.blaze3d.platform.GlStateManager; -import com.mojang.blaze3d.systems.RenderSystem; -import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.math.ChunkPos; import net.minecraft.world.World; @@ -42,12 +40,9 @@ public class FinderQueue { }); } - public void renderFinders(MatrixStack matrixStack) { + public void renderFinders() { if(this.renderType == RenderType.OFF)return; - RenderSystem.pushMatrix(); - RenderSystem.multMatrix(matrixStack.peek().getModel()); - GlStateManager.disableTexture(); //Makes it render through blocks. @@ -61,7 +56,11 @@ public class FinderQueue { } }); - RenderSystem.popMatrix(); + GlStateManager.enableTexture(); + + if(this.renderType == RenderType.XRAY) { + GlStateManager.enableDepthTest(); + } } public void clear() { diff --git a/src/main/java/kaptainwutax/seedcracker/finder/population/DungeonFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/population/DungeonFinder.java index 3287d91..12b0c9b 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/population/DungeonFinder.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/population/DungeonFinder.java @@ -69,7 +69,7 @@ public class DungeonFinder extends BlockFinder { .map(pos -> this.getFloorCalls(this.getDungeonSize(pos), pos)).collect(Collectors.toList()); result.forEach(pos -> { - if(SeedCracker.get().onDecoratorData(new DungeonData(this.chunkPos, biome, starts, floorCallsList))) { + if(SeedCracker.get().onPopulationData(new DungeonData(this.chunkPos, biome, starts, floorCallsList))) { this.renderers.add(new Cube(pos, new Vector4f(1.0f, 0.0f, 0.0f, 1.0f))); } }); diff --git a/src/main/java/kaptainwutax/seedcracker/finder/population/EndGatewayFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/population/EndGatewayFinder.java index 497806f..53dfafc 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/population/EndGatewayFinder.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/population/EndGatewayFinder.java @@ -48,7 +48,7 @@ public class EndGatewayFinder extends BlockFinder { if(height >= 3 && height <= 9) { newResult.add(pos); - if(SeedCracker.get().onDecoratorData(new EndGatewayData(this.chunkPos, biome, pos, height))) { + if(SeedCracker.get().onPopulationData(new EndGatewayData(this.chunkPos, biome, pos, height))) { this.renderers.add(new Cuboid(pos.add(-1, -2, -1), pos.add(2, 3, 2), new Vector4f(0.4f, 0.4f, 0.82f, 1.0f))); } } diff --git a/src/main/java/kaptainwutax/seedcracker/finder/population/ore/EmeraldOreFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/population/ore/EmeraldOreFinder.java index bc876bf..16eb421 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/population/ore/EmeraldOreFinder.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/population/ore/EmeraldOreFinder.java @@ -21,8 +21,6 @@ import java.util.List; public class EmeraldOreFinder extends BlockFinder { protected static List SEARCH_POSITIONS = Finder.buildSearchPositions(Finder.CHUNK_POSITIONS, pos -> { - if(pos.getY() < 4)return true; - if(pos.getY() > 28 + 4)return true; return false; }); @@ -41,7 +39,7 @@ public class EmeraldOreFinder extends BlockFinder { List result = super.findInChunk(); - if(!result.isEmpty() && SeedCracker.get().onDecoratorData(new EmeraldOreData(this.chunkPos, biome, result))) { + if(!result.isEmpty() && SeedCracker.get().onPopulationData(new EmeraldOreData(this.chunkPos, biome, result))) { result.forEach(pos -> { this.renderers.add(new Cube(pos, new Vector4f(0.0f, 1.0f, 0.0f, 1.0f))); }); diff --git a/src/main/java/kaptainwutax/seedcracker/finder/structure/BuriedTreasureFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/structure/BuriedTreasureFinder.java index 8969a26..270a9d4 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/structure/BuriedTreasureFinder.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/structure/BuriedTreasureFinder.java @@ -1,8 +1,7 @@ package kaptainwutax.seedcracker.finder.structure; import kaptainwutax.seedcracker.SeedCracker; -import kaptainwutax.seedcracker.cracker.structure.StructureData; -import kaptainwutax.seedcracker.cracker.structure.StructureFeatures; +import kaptainwutax.seedcracker.cracker.StructureData; import kaptainwutax.seedcracker.finder.BlockFinder; import kaptainwutax.seedcracker.finder.Finder; import kaptainwutax.seedcracker.render.Cube; @@ -27,7 +26,7 @@ public class BuriedTreasureFinder extends BlockFinder { int localX = pos.getX() & 15; int localZ = pos.getZ() & 15; if(localX != 9 || localZ != 9)return true; - if(pos.getY() > 90)return true; + return false; }); @@ -56,23 +55,28 @@ public class BuriedTreasureFinder extends BlockFinder { @Override public List findInChunk() { - Biome biome = world.getBiome(this.chunkPos.getCenterBlockPos().add(9, 0, 9)); - if(!biome.hasStructureFeature(Feature.BURIED_TREASURE))return new ArrayList<>(); - + //Gets all the positions with a chest in the chunk. List result = super.findInChunk(); result.removeIf(pos -> { + //Chest can't be waterlogged! BlockState chest = world.getBlockState(pos); if(chest.get(ChestBlock.WATERLOGGED))return true; + //Only so many blocks can hold a treasure chest. BlockState chestHolder = world.getBlockState(pos.down()); if(!CHEST_HOLDERS.contains(chestHolder))return true; + //Check if the biome contains the buried treasure feature. + Biome biome = world.getBiome(pos); + if(!biome.hasStructureFeature(Feature.BURIED_TREASURE))return true; + + //Damn that chest be lucky! return false; }); result.forEach(pos -> { - if(SeedCracker.get().onStructureData(new StructureData(this.chunkPos, StructureFeatures.BURIED_TREASURE))) { + if(SeedCracker.get().onStructureData(new StructureData(this.chunkPos, StructureData.BURIED_TREASURE))) { this.renderers.add(new Cube(pos, new Vector4f(1.0f, 1.0f, 0.0f, 1.0f))); } }); diff --git a/src/main/java/kaptainwutax/seedcracker/finder/structure/DesertTempleFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/structure/DesertTempleFinder.java index 36bdc0e..31283d7 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/structure/DesertTempleFinder.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/structure/DesertTempleFinder.java @@ -1,8 +1,7 @@ package kaptainwutax.seedcracker.finder.structure; import kaptainwutax.seedcracker.SeedCracker; -import kaptainwutax.seedcracker.cracker.structure.StructureData; -import kaptainwutax.seedcracker.cracker.structure.StructureFeatures; +import kaptainwutax.seedcracker.cracker.StructureData; import kaptainwutax.seedcracker.finder.Finder; import kaptainwutax.seedcracker.render.Cuboid; import net.minecraft.block.BlockState; @@ -36,7 +35,7 @@ public class DesertTempleFinder extends AbstractTempleFinder { combinedResult.addAll(positions); positions.forEach(pos -> { - if( SeedCracker.get().onStructureData(new StructureData(this.chunkPos, StructureFeatures.DESERT_PYRAMID))) { + if( SeedCracker.get().onStructureData(new StructureData(this.chunkPos, StructureData.DESERT_PYRAMID))) { this.renderers.add(new Cuboid(pos, pieceFinder.getLayout(), new Vector4f(1.0f, 0.0f, 1.0f, 1.0f))); } }); diff --git a/src/main/java/kaptainwutax/seedcracker/finder/structure/EndCityFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/structure/EndCityFinder.java index 487146f..04702d4 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/structure/EndCityFinder.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/structure/EndCityFinder.java @@ -1,8 +1,7 @@ package kaptainwutax.seedcracker.finder.structure; import kaptainwutax.seedcracker.SeedCracker; -import kaptainwutax.seedcracker.cracker.structure.StructureData; -import kaptainwutax.seedcracker.cracker.structure.StructureFeatures; +import kaptainwutax.seedcracker.cracker.StructureData; import kaptainwutax.seedcracker.finder.Finder; import kaptainwutax.seedcracker.render.Cube; import kaptainwutax.seedcracker.render.Cuboid; @@ -86,7 +85,7 @@ public class EndCityFinder extends Finder { combinedResult.addAll(positions); positions.forEach(pos -> { - if(SeedCracker.get().onStructureData(new StructureData(this.chunkPos, StructureFeatures.END_CITY))) { + if(SeedCracker.get().onStructureData(new StructureData(this.chunkPos, StructureData.END_CITY))) { this.renderers.add(new Cuboid(pos, pieceFinder.getLayout(), new Vector4f(0.6f, 0.0f, 0.6f, 1.0f))); this.renderers.add(new Cube(pos, new Vector4f(0.6f, 0.0f, 0.6f, 1.0f))); } diff --git a/src/main/java/kaptainwutax/seedcracker/finder/structure/IglooFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/structure/IglooFinder.java index 4fa937d..3ee0986 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/structure/IglooFinder.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/structure/IglooFinder.java @@ -1,8 +1,7 @@ package kaptainwutax.seedcracker.finder.structure; import kaptainwutax.seedcracker.SeedCracker; -import kaptainwutax.seedcracker.cracker.structure.StructureData; -import kaptainwutax.seedcracker.cracker.structure.StructureFeatures; +import kaptainwutax.seedcracker.cracker.StructureData; import kaptainwutax.seedcracker.finder.Finder; import kaptainwutax.seedcracker.render.Cube; import kaptainwutax.seedcracker.render.Cuboid; @@ -45,7 +44,7 @@ public class IglooFinder extends AbstractTempleFinder { combinedResult.addAll(positions); positions.forEach(pos -> { - if(SeedCracker.get().onStructureData(new StructureData(this.chunkPos, StructureFeatures.IGLOO))) { + if(SeedCracker.get().onStructureData(new StructureData(this.chunkPos, StructureData.IGLOO))) { this.renderers.add(new Cuboid(pos, pieceFinder.getLayout(), new Vector4f(0.0f, 1.0f, 1.0f, 1.0f))); this.renderers.add(new Cube(pos, new Vector4f(0.0f, 1.0f, 1.0f, 1.0f))); } diff --git a/src/main/java/kaptainwutax/seedcracker/finder/structure/JungleTempleFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/structure/JungleTempleFinder.java index 96be497..19d2be6 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/structure/JungleTempleFinder.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/structure/JungleTempleFinder.java @@ -1,8 +1,7 @@ package kaptainwutax.seedcracker.finder.structure; import kaptainwutax.seedcracker.SeedCracker; -import kaptainwutax.seedcracker.cracker.structure.StructureData; -import kaptainwutax.seedcracker.cracker.structure.StructureFeatures; +import kaptainwutax.seedcracker.cracker.StructureData; import kaptainwutax.seedcracker.finder.Finder; import kaptainwutax.seedcracker.render.Cuboid; import net.minecraft.block.*; @@ -36,7 +35,7 @@ public class JungleTempleFinder extends AbstractTempleFinder { combinedResult.addAll(positions); positions.forEach(pos -> { - if(SeedCracker.get().onStructureData(new StructureData(this.chunkPos, StructureFeatures.JUNGLE_TEMPLE))) { + if(SeedCracker.get().onStructureData(new StructureData(this.chunkPos, StructureData.JUNGLE_TEMPLE))) { this.renderers.add(new Cuboid(pos, pieceFinder.getLayout(), new Vector4f(1.0f, 0.0f, 1.0f, 1.0f))); } }); diff --git a/src/main/java/kaptainwutax/seedcracker/finder/structure/MansionFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/structure/MansionFinder.java index efef387..e51b59f 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/structure/MansionFinder.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/structure/MansionFinder.java @@ -1,8 +1,7 @@ package kaptainwutax.seedcracker.finder.structure; import kaptainwutax.seedcracker.SeedCracker; -import kaptainwutax.seedcracker.cracker.structure.StructureData; -import kaptainwutax.seedcracker.cracker.structure.StructureFeatures; +import kaptainwutax.seedcracker.cracker.StructureData; import kaptainwutax.seedcracker.finder.Finder; import kaptainwutax.seedcracker.render.Cube; import kaptainwutax.seedcracker.render.Cuboid; @@ -14,9 +13,7 @@ import net.minecraft.util.math.ChunkPos; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3i; import net.minecraft.world.World; -import net.minecraft.world.biome.Biome; import net.minecraft.world.dimension.DimensionType; -import net.minecraft.world.gen.feature.Feature; import java.util.ArrayList; import java.util.HashMap; @@ -26,6 +23,7 @@ import java.util.Map; public class MansionFinder extends Finder { protected static List SEARCH_POSITIONS = buildSearchPositions(CHUNK_POSITIONS, pos -> { + if(pos.getY() != 64)return true; if((pos.getX() & 15) != 0)return true; if((pos.getZ() & 15) != 0)return true; return false; @@ -37,32 +35,31 @@ public class MansionFinder extends Finder { public MansionFinder(World world, ChunkPos chunkPos) { super(world, chunkPos); - for(Direction direction: Direction.values()) { - PieceFinder finder = new PieceFinder(world, chunkPos, direction, this.size); + Direction.Type.HORIZONTAL.forEach(direction -> { + PieceFinder finder = new PieceFinder(world, chunkPos, direction, size); finder.searchPositions = SEARCH_POSITIONS; buildStructure(finder); this.finders.add(finder); - } + }); } @Override public List findInChunk() { - Biome biome = this.world.getBiome(this.chunkPos.getCenterBlockPos().add(9, 0, 9)); - - if(!biome.hasStructureFeature(Feature.WOODLAND_MANSION)) { - return new ArrayList<>(); - } - Map> result = this.findInChunkPieces(); List combinedResult = new ArrayList<>(); result.forEach((pieceFinder, positions) -> { + positions.removeIf(pos -> { + //Figure this out, it's not a trivial task. + return false; + }); + combinedResult.addAll(positions); positions.forEach(pos -> { - if(SeedCracker.get().onStructureData(new StructureData(this.chunkPos, StructureFeatures.WOODLAND_MANSION))) { + if(SeedCracker.get().onStructureData(new StructureData(this.chunkPos, StructureData.WOODLAND_MANSION))) { this.renderers.add(new Cuboid(pos, pieceFinder.getLayout(), new Vector4f(0.4f, 0.26f, 0.13f, 1.0f))); this.renderers.add(new Cube(this.chunkPos.getCenterBlockPos().add(0, pos.getY(), 0), new Vector4f(0.4f, 0.26f, 0.13f, 1.0f))); } @@ -83,26 +80,12 @@ public class MansionFinder extends Finder { } public void buildStructure(PieceFinder finder) { - BlockState air = Blocks.AIR.getDefaultState(); BlockState cobblestone = Blocks.COBBLESTONE.getDefaultState(); BlockState birchPlanks = Blocks.BIRCH_PLANKS.getDefaultState(); BlockState redCarpet = Blocks.RED_CARPET.getDefaultState(); BlockState whiteCarpet = Blocks.WHITE_CARPET.getDefaultState(); - finder.fillWithOutline(0, 0, 0, 15, 0, 15, birchPlanks, birchPlanks, false); - finder.fillWithOutline(0, 0, 8, 6, 0, 12, null, null, false); - finder.fillWithOutline(0, 0, 12, 9, 0, 15, null, null, false); - finder.fillWithOutline(15, 0, 0, 15, 0, 15, cobblestone, cobblestone, false); - finder.addBlock(Blocks.DARK_OAK_LOG.getDefaultState(), 15, 0, 15); - finder.addBlock(Blocks.DARK_OAK_LOG.getDefaultState(), 15, 0, 7); - finder.addBlock(Blocks.DARK_OAK_LOG.getDefaultState(), 14, 0, 7); - - finder.fillWithOutline(9, 1, 0, 9, 1, 8, whiteCarpet, whiteCarpet, false); - finder.addBlock(whiteCarpet, 8,1, 8); - finder.fillWithOutline(13, 1, 0, 13, 1, 8, whiteCarpet, whiteCarpet, false); - finder.addBlock(whiteCarpet, 14,1, 8); - - finder.fillWithOutline(10, 1, 0, 12, 1, 15, redCarpet, redCarpet, false); + //TODO: Finish this. } @Override diff --git a/src/main/java/kaptainwutax/seedcracker/finder/structure/OceanMonumentFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/structure/OceanMonumentFinder.java index 7484456..f4f3cb0 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/structure/OceanMonumentFinder.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/structure/OceanMonumentFinder.java @@ -1,8 +1,7 @@ package kaptainwutax.seedcracker.finder.structure; import kaptainwutax.seedcracker.SeedCracker; -import kaptainwutax.seedcracker.cracker.structure.StructureData; -import kaptainwutax.seedcracker.cracker.structure.StructureFeatures; +import kaptainwutax.seedcracker.cracker.StructureData; import kaptainwutax.seedcracker.finder.Finder; import kaptainwutax.seedcracker.render.Cube; import kaptainwutax.seedcracker.render.Cuboid; @@ -58,7 +57,7 @@ public class OceanMonumentFinder extends Finder { positions.forEach(pos -> { ChunkPos monumentStart = new ChunkPos(this.chunkPos.x + 1, this.chunkPos.z + 1); - if(SeedCracker.get().onStructureData(new StructureData(monumentStart, StructureFeatures.OCEAN_MONUMENT))) { + if(SeedCracker.get().onStructureData(new StructureData(monumentStart, StructureData.OCEAN_MONUMENT))) { this.renderers.add(new Cuboid(pos, pieceFinder.getLayout(), new Vector4f(0.0f, 0.0f, 1.0f, 1.0f))); this.renderers.add(new Cube(monumentStart.getCenterBlockPos().add(0, pos.getY(), 0), new Vector4f(0.0f, 0.0f, 1.0f, 1.0f))); } diff --git a/src/main/java/kaptainwutax/seedcracker/finder/structure/PieceFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/structure/PieceFinder.java index b6df258..02a57af 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/structure/PieceFinder.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/structure/PieceFinder.java @@ -18,7 +18,7 @@ import java.util.Map; public class PieceFinder extends Finder { protected Map structure = new LinkedHashMap<>(); - private BlockBox boundingBox; + private MutableIntBoundingBox boundingBox; protected List searchPositions = new ArrayList<>(); protected Direction facing; @@ -40,12 +40,12 @@ public class PieceFinder extends Finder { this.depth = size.getZ(); if(this.facing.getAxis() == Direction.Axis.Z) { - this.boundingBox = new BlockBox( + this.boundingBox = new MutableIntBoundingBox( 0, 0, 0, size.getX() - 1, size.getY() - 1, size.getZ() - 1 ); } else { - this.boundingBox = new BlockBox( + this.boundingBox = new MutableIntBoundingBox( 0, 0, 0, size.getZ() - 1, size.getY() - 1, size.getX() - 1 ); @@ -71,7 +71,7 @@ public class PieceFinder extends Finder { //FOR DEBUGGING PIECES. if(this.debug) { MinecraftClient.getInstance().execute(() -> { - int y = this.rotation.ordinal() * 10 + this.mirror.ordinal() * 20 + 120; + int y = this.rotation.ordinal() * 10 + this.mirror.ordinal() * 20 + 100; if (this.chunkPos.x % 2 == 0 && this.chunkPos.z % 2 == 0) { this.structure.forEach((pos, state) -> { @@ -89,7 +89,7 @@ public class PieceFinder extends Finder { BlockState state = this.world.getBlockState(pos); //Blockstate may change when it gets placed in the world, that's why it's using the block here. - if(entry.getValue() != null && !state.getBlock().equals(entry.getValue().getBlock())) { + if(!state.getBlock().equals(entry.getValue().getBlock())) { found = false; break; } @@ -200,6 +200,10 @@ public class PieceFinder extends Finder { } protected void addBlock(BlockState state, int x, int y, int z) { + if(state == null) { + return; + } + BlockPos pos = new BlockPos( this.applyXTransform(x, z), this.applyYTransform(y), @@ -207,11 +211,6 @@ public class PieceFinder extends Finder { ); if(this.boundingBox.contains(pos)) { - if(state == null) { - this.structure.remove(pos); - return; - } - if (this.mirror != BlockMirror.NONE) { state = state.mirror(this.mirror); } @@ -220,7 +219,6 @@ public class PieceFinder extends Finder { state = state.rotate(this.rotation); } - this.structure.put(pos, state); } } diff --git a/src/main/java/kaptainwutax/seedcracker/finder/structure/ShipwreckFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/structure/ShipwreckFinder.java deleted file mode 100644 index 9dbc88f..0000000 --- a/src/main/java/kaptainwutax/seedcracker/finder/structure/ShipwreckFinder.java +++ /dev/null @@ -1,211 +0,0 @@ -package kaptainwutax.seedcracker.finder.structure; - -import kaptainwutax.seedcracker.SeedCracker; -import kaptainwutax.seedcracker.cracker.structure.StructureData; -import kaptainwutax.seedcracker.cracker.structure.StructureFeatures; -import kaptainwutax.seedcracker.finder.BlockFinder; -import kaptainwutax.seedcracker.finder.Finder; -import kaptainwutax.seedcracker.render.Cube; -import kaptainwutax.seedcracker.render.Cuboid; -import net.minecraft.block.*; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.block.entity.ChestBlockEntity; -import net.minecraft.block.enums.ChestType; -import net.minecraft.client.util.math.Vector4f; -import net.minecraft.util.math.BlockBox; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.ChunkPos; -import net.minecraft.util.math.Direction; -import net.minecraft.world.World; -import net.minecraft.world.biome.Biome; -import net.minecraft.world.dimension.DimensionType; -import net.minecraft.world.gen.feature.Feature; - -import java.util.ArrayList; -import java.util.List; - -public class ShipwreckFinder extends BlockFinder { - - protected static List SEARCH_POSITIONS = Finder.buildSearchPositions(Finder.CHUNK_POSITIONS, pos -> { - return false; - }); - - public ShipwreckFinder(World world, ChunkPos chunkPos) { - super(world, chunkPos, Blocks.CHEST); - this.searchPositions = SEARCH_POSITIONS; - } - - @Override - public List findInChunk() { - Biome biome = this.world.getBiome(this.chunkPos.getCenterBlockPos().add(9, 0, 9)); - - if(!biome.hasStructureFeature(Feature.SHIPWRECK)) { - return new ArrayList<>(); - } - - List result = super.findInChunk(); - - result.removeIf(pos -> { - BlockState state = this.world.getBlockState(pos); - if(state.get(ChestBlock.CHEST_TYPE) != ChestType.SINGLE)return true; - - BlockEntity blockEntity = this.world.getBlockEntity(pos); - if(!(blockEntity instanceof ChestBlockEntity))return true; - - return !this.onChestFound(pos); - }); - - return result; - } - - /** - * Source: https://github.com/skyrising/casual-mod/blob/master/src/main/java/de/skyrising/casual/ShipwreckFinder.java - * */ - private boolean onChestFound(BlockPos pos) { - BlockPos.Mutable mutablePos = new BlockPos.Mutable(pos); - Direction chestFacing = world.getBlockState(pos).get(ChestBlock.FACING); - - int[] stairs = new int[4]; - int totalStairs = 0; - int[] trapdoors = new int[4]; - int totalTrapdoors = 0; - for(int y = -1; y <= 2; y++) { - for(int x = -1; x <= 1; x++) { - for(int z = -1; z <= 1; z++) { - if (x == 0 && y == 0 && z == 0)continue; - mutablePos.set(pos.getX() + x, pos.getY() + y, pos.getZ() + z); - BlockState neighborState = world.getBlockState(mutablePos); - Block neighborBlock = neighborState.getBlock(); - if(neighborBlock == Blocks.VOID_AIR)return false; - - if(neighborBlock instanceof StairsBlock) { - stairs[y + 1]++; - totalStairs++; - } else if(neighborBlock instanceof TrapdoorBlock) { - trapdoors[y + 1]++; - totalTrapdoors++; - } - } - } - } - //System.out.printf("%s: chest facing %s\n", pos, chestFacing); - int chestX = 4; - int chestY = 2; - int chestZ = 0; - int length = 16; - int height = 9; - Direction direction = chestFacing; - - if(trapdoors[3] > 4) { // with_mast[_degraded] - chestZ = 9; - height = 21; - length = 28; - } else if(totalTrapdoors == 0 && stairs[3] == 3) { // upsidedown_backhalf[_degraded] - if(stairs[0] == 0) { - chestX = 2; - chestZ = 12; - direction = chestFacing.getOpposite(); - } else { // redundant - chestX = 3; - chestY = 5; - chestZ = 5; - direction = chestFacing.rotateYClockwise(); - } - } else if(totalTrapdoors == 0) { // rightsideup that have backhalf - if(stairs[0] == 4) { - if(totalStairs > 4) { - chestX = 6; - chestY = 4; - chestZ = 12; - direction = chestFacing.getOpposite(); - } else { // sideways backhalf - chestX = 6; - chestY = 3; - chestZ = 8; - length = 17; - direction = chestFacing.getOpposite(); - } - } else if(stairs[0] == 3 && totalStairs > 5) { - chestX = 5; - chestZ = 6; - direction = chestFacing.rotateYCounterclockwise(); - } - - mutablePos.set(pos); - mutablePos.setOffset(0, -chestY, 0); - mutablePos.setOffset(direction.rotateYClockwise(), chestX - 4); - mutablePos.setOffset(direction, -chestZ - 1); - - if(this.world.getBlockState(mutablePos).getMaterial() == Material.WOOD) { - if(length == 17) { // sideways - chestZ += 11; - length += 11; - } else { - chestZ += 12; - length += 12; - } - mutablePos.setOffset(0, 10, 0); - - if(this.world.getBlockState(mutablePos).getBlock() instanceof LogBlock) { - height = 21; - } - } - } else if(totalTrapdoors == 2 && trapdoors[3] == 2 && stairs[3] == 3) { // rightsideup_fronthalf[_degraded] - chestZ = 8; - length = 24; - } - - if(chestZ != 0) { - mutablePos.set(pos); - mutablePos.setOffset(direction, 15 - chestZ); - mutablePos.setOffset(direction.rotateYClockwise(), chestX - 4); - BlockPos.Mutable pos2 = new BlockPos.Mutable(mutablePos); - pos2.setOffset(0, -chestY, 0); - pos2.setOffset(direction, -15); - pos2.setOffset(direction.rotateYClockwise(), 4); - BlockPos.Mutable pos3 = new BlockPos.Mutable(pos2); - pos3.setOffset(direction, length - 1); - pos3.setOffset(direction.rotateYClockwise(), -8); - pos3.setOffset(0, height - 1, 0); - - BlockBox box = new BlockBox( - Math.min(pos2.getX(), pos3.getX()), pos2.getY(), Math.min(pos2.getZ(), pos3.getZ()), - Math.max(pos2.getX(), pos3.getX()), pos3.getY(), Math.max(pos2.getZ(), pos3.getZ())); - - mutablePos.setOffset(-4, -chestY, -15); - - if((mutablePos.getX() & 0xf) == 0 && (mutablePos.getZ() & 0xf) == 0) { - if(SeedCracker.get().onStructureData(new StructureData(new ChunkPos(mutablePos), StructureFeatures.SHIPWRECK))) { - this.renderers.add(new Cuboid(box, new Vector4f(1.0f, 0.0f, 1.0f, 1.0f))); - this.renderers.add(new Cube(new ChunkPos(mutablePos).getCenterBlockPos().offset(Direction.UP, mutablePos.getY()), new Vector4f(1.0f, 0.0f, 1.0f, 1.0f))); - return true; - } - } - } - - return false; - } - - @Override - public boolean isValidDimension(DimensionType dimension) { - return dimension == DimensionType.OVERWORLD; - } - - public static List create(World world, ChunkPos chunkPos) { - List finders = new ArrayList<>(); - finders.add(new ShipwreckFinder(world, chunkPos)); - - finders.add(new ShipwreckFinder(world, new ChunkPos(chunkPos.x - 1, chunkPos.z))); - finders.add(new ShipwreckFinder(world, new ChunkPos(chunkPos.x, chunkPos.z - 1))); - finders.add(new ShipwreckFinder(world, new ChunkPos(chunkPos.x - 1, chunkPos.z - 1))); - - finders.add(new ShipwreckFinder(world, new ChunkPos(chunkPos.x + 1, chunkPos.z))); - finders.add(new ShipwreckFinder(world, new ChunkPos(chunkPos.x, chunkPos.z + 1))); - finders.add(new ShipwreckFinder(world, new ChunkPos(chunkPos.x + 1, chunkPos.z + 1))); - - finders.add(new ShipwreckFinder(world, new ChunkPos(chunkPos.x - 1, chunkPos.z - 1))); - finders.add(new ShipwreckFinder(world, new ChunkPos(chunkPos.x - 1, chunkPos.z + 1))); - return finders; - } - -} diff --git a/src/main/java/kaptainwutax/seedcracker/finder/structure/SwampHutFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/structure/SwampHutFinder.java index 84bbe23..2f03449 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/structure/SwampHutFinder.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/structure/SwampHutFinder.java @@ -1,8 +1,7 @@ package kaptainwutax.seedcracker.finder.structure; import kaptainwutax.seedcracker.SeedCracker; -import kaptainwutax.seedcracker.cracker.structure.StructureData; -import kaptainwutax.seedcracker.cracker.structure.StructureFeatures; +import kaptainwutax.seedcracker.cracker.StructureData; import kaptainwutax.seedcracker.finder.Finder; import kaptainwutax.seedcracker.render.Cuboid; import net.minecraft.block.BlockState; @@ -37,7 +36,7 @@ public class SwampHutFinder extends AbstractTempleFinder { combinedResult.addAll(positions); positions.forEach(pos -> { - if(SeedCracker.get().onStructureData(new StructureData(this.chunkPos, StructureFeatures.SWAMP_HUT))) { + if(SeedCracker.get().onStructureData(new StructureData(this.chunkPos, StructureData.SWAMP_HUT))) { this.renderers.add(new Cuboid(pos, pieceFinder.getLayout(), new Vector4f(1.0f, 0.0f, 1.0f, 1.0f))); } }); diff --git a/src/main/java/kaptainwutax/seedcracker/mixin/ClientPlayNetworkHandlerMixin.java b/src/main/java/kaptainwutax/seedcracker/mixin/ClientPlayNetworkHandlerMixin.java index f88eca7..fc75998 100644 --- a/src/main/java/kaptainwutax/seedcracker/mixin/ClientPlayNetworkHandlerMixin.java +++ b/src/main/java/kaptainwutax/seedcracker/mixin/ClientPlayNetworkHandlerMixin.java @@ -2,7 +2,6 @@ package kaptainwutax.seedcracker.mixin; import com.mojang.authlib.GameProfile; import com.mojang.brigadier.CommandDispatcher; -import kaptainwutax.seedcracker.SeedCracker; import kaptainwutax.seedcracker.command.ClientCommands; import kaptainwutax.seedcracker.finder.FinderQueue; import net.minecraft.client.MinecraftClient; @@ -10,7 +9,6 @@ import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.network.ClientPlayNetworkHandler; import net.minecraft.client.network.packet.ChunkDataS2CPacket; import net.minecraft.client.network.packet.CommandTreeS2CPacket; -import net.minecraft.client.network.packet.PlayerRespawnS2CPacket; import net.minecraft.client.world.ClientWorld; import net.minecraft.network.ClientConnection; import net.minecraft.server.command.CommandSource; @@ -46,9 +44,4 @@ public abstract class ClientPlayNetworkHandlerMixin { ClientCommands.registerCommands((CommandDispatcher)(Object)this.commandDispatcher); } - @Inject(method = "onPlayerRespawn", at = @At("HEAD")) - public void onPlayerRespawn(PlayerRespawnS2CPacket packet, CallbackInfo ci) { - SeedCracker.get().hashedWorldSeed = packet.method_22425(); - } - } diff --git a/src/main/java/kaptainwutax/seedcracker/mixin/ClientWorldMixin.java b/src/main/java/kaptainwutax/seedcracker/mixin/ClientWorldMixin.java index ab6ee10..60e4157 100644 --- a/src/main/java/kaptainwutax/seedcracker/mixin/ClientWorldMixin.java +++ b/src/main/java/kaptainwutax/seedcracker/mixin/ClientWorldMixin.java @@ -1,15 +1,14 @@ package kaptainwutax.seedcracker.mixin; -import kaptainwutax.seedcracker.SeedCracker; import kaptainwutax.seedcracker.finder.FinderQueue; +import kaptainwutax.seedcracker.SeedCracker; import net.minecraft.client.world.ClientWorld; -import net.minecraft.world.biome.Biome; -import net.minecraft.world.biome.Biomes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.concurrent.Executors; @Mixin(ClientWorld.class) public abstract class ClientWorldMixin { @@ -18,11 +17,8 @@ public abstract class ClientWorldMixin { private void disconnect(CallbackInfo ci) { SeedCracker.get().clear(); FinderQueue.get().clear(); - } - - @Inject(method = "getGeneratorStoredBiome", at = @At("HEAD"), cancellable = true) - private void getGeneratorStoredBiome(int x, int y, int z, CallbackInfoReturnable ci) { - ci.setReturnValue(Biomes.THE_VOID); + FinderQueue.SERVICE.shutdown(); + FinderQueue.SERVICE = Executors.newFixedThreadPool(5); } } diff --git a/src/main/java/kaptainwutax/seedcracker/mixin/GameRendererMixin.java b/src/main/java/kaptainwutax/seedcracker/mixin/GameRendererMixin.java index b79d43b..2345295 100644 --- a/src/main/java/kaptainwutax/seedcracker/mixin/GameRendererMixin.java +++ b/src/main/java/kaptainwutax/seedcracker/mixin/GameRendererMixin.java @@ -2,7 +2,6 @@ package kaptainwutax.seedcracker.mixin; import kaptainwutax.seedcracker.render.RenderQueue; import net.minecraft.client.render.GameRenderer; -import net.minecraft.client.util.math.MatrixStack; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -11,14 +10,14 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(GameRenderer.class) public abstract class GameRendererMixin { - @Inject(method = "renderWorld", at = @At("HEAD")) - private void renderWorldStart(float delta, long time, MatrixStack matrixStack, CallbackInfo ci) { - RenderQueue.get().setTrackRender(matrixStack); + @Inject(method = "renderCenter", at = @At("HEAD")) + private void renderCenterStart(float delta, long time, CallbackInfo ci) { + RenderQueue.get().setTrackRender(true); } - @Inject(method = "renderWorld", at = @At("TAIL")) - private void renderWorldFinish(float delta, long time, MatrixStack matrixStack, CallbackInfo ci) { - RenderQueue.get().setTrackRender(null); + @Inject(method = "renderCenter", at = @At("TAIL")) + private void renderCenterFinish(float delta, long time, CallbackInfo ci) { + RenderQueue.get().setTrackRender(false); } } diff --git a/src/main/java/kaptainwutax/seedcracker/render/Cube.java b/src/main/java/kaptainwutax/seedcracker/render/Cube.java index a446139..5c734a2 100644 --- a/src/main/java/kaptainwutax/seedcracker/render/Cube.java +++ b/src/main/java/kaptainwutax/seedcracker/render/Cube.java @@ -18,9 +18,4 @@ public class Cube extends Cuboid { super(pos, new Vec3i(1, 1, 1), color); } - @Override - public BlockPos getPos() { - return this.start; - } - } diff --git a/src/main/java/kaptainwutax/seedcracker/render/Cuboid.java b/src/main/java/kaptainwutax/seedcracker/render/Cuboid.java index 201efff..d0e7ffb 100644 --- a/src/main/java/kaptainwutax/seedcracker/render/Cuboid.java +++ b/src/main/java/kaptainwutax/seedcracker/render/Cuboid.java @@ -1,7 +1,6 @@ package kaptainwutax.seedcracker.render; import net.minecraft.client.util.math.Vector4f; -import net.minecraft.util.math.BlockBox; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3i; @@ -25,10 +24,6 @@ public class Cuboid extends Renderer { this(start, new Vec3i(end.getX() - start.getX(), end.getY() - start.getY(), end.getZ() - start.getZ()), color); } - public Cuboid(BlockBox box, Vector4f color) { - this(new BlockPos(box.minX, box.minY, box.minZ), new BlockPos(box.maxX, box.maxY, box.maxZ), color); - } - public Cuboid(BlockPos start, Vec3i size, Vector4f color) { this.start = start; this.size = size; @@ -57,9 +52,4 @@ public class Cuboid extends Renderer { } } - @Override - public BlockPos getPos() { - return this.start.add(this.size.getX() / 2, this.size.getY() / 2, this.size.getZ() / 2); - } - } diff --git a/src/main/java/kaptainwutax/seedcracker/render/Line.java b/src/main/java/kaptainwutax/seedcracker/render/Line.java index 43daa6c..2113892 100644 --- a/src/main/java/kaptainwutax/seedcracker/render/Line.java +++ b/src/main/java/kaptainwutax/seedcracker/render/Line.java @@ -5,7 +5,6 @@ import net.minecraft.client.render.BufferBuilder; import net.minecraft.client.render.Tessellator; import net.minecraft.client.render.VertexFormats; import net.minecraft.client.util.math.Vector4f; -import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; public class Line extends Renderer { @@ -34,7 +33,7 @@ public class Line extends Renderer { Vec3d camPos = this.mc.gameRenderer.getCamera().getPos(); Tessellator tessellator = Tessellator.getInstance(); - BufferBuilder buffer = tessellator.getBuffer(); + BufferBuilder buffer = tessellator.getBufferBuilder(); //This is how thick the line is. GlStateManager.lineWidth(2.0f); @@ -49,24 +48,18 @@ public class Line extends Renderer { } protected void putVertex(BufferBuilder buffer, Vec3d camPos, Vec3d pos) { - buffer.vertex( - pos.getX() - camPos.x, - pos.getY() - camPos.y, - pos.getZ() - camPos.z - ).color( - this.color.getX(), - this.color.getY(), - this.color.getZ(), - this.color.getW() - ).next(); - } - - @Override - public BlockPos getPos() { - double x = (this.end.getX() - this.start.getX()) / 2 + this.start.getX(); - double y = (this.end.getY() - this.start.getY()) / 2 + this.start.getY(); - double z = (this.end.getZ() - this.start.getZ()) / 2 + this.start.getZ(); - return new BlockPos(x, y, z); + for(int i = 0; i < 2; i++) { + buffer.vertex( + pos.getX() - camPos.x, + pos.getY() - camPos.y, + pos.getZ() - camPos.z + ).color( + this.color.getX(), + this.color.getY(), + this.color.getZ(), + this.color.getW() + ).next(); + } } } diff --git a/src/main/java/kaptainwutax/seedcracker/render/RenderQueue.java b/src/main/java/kaptainwutax/seedcracker/render/RenderQueue.java index e993726..0029650 100644 --- a/src/main/java/kaptainwutax/seedcracker/render/RenderQueue.java +++ b/src/main/java/kaptainwutax/seedcracker/render/RenderQueue.java @@ -1,22 +1,19 @@ package kaptainwutax.seedcracker.render; -import net.minecraft.client.util.math.MatrixStack; - import java.util.*; -import java.util.function.Consumer; public class RenderQueue { private final static RenderQueue INSTANCE = new RenderQueue(); - private Map>> typeRunnableMap = new HashMap<>(); - private MatrixStack matrixStack = null; + private Map> typeRunnableMap = new HashMap<>(); + private boolean trackRender = false; public static RenderQueue get() { return INSTANCE; } - public void add(String type, Consumer runnable) { + public void add(String type, Runnable runnable) { Objects.requireNonNull(type); Objects.requireNonNull(runnable); @@ -24,11 +21,11 @@ public class RenderQueue { this.typeRunnableMap.put(type, new ArrayList<>()); } - List> runnableList = this.typeRunnableMap.get(type); + List runnableList = this.typeRunnableMap.get(type); runnableList.add(runnable); } - public void remove(String type, Consumer runnable) { + public void remove(String type, Runnable runnable) { Objects.requireNonNull(type); Objects.requireNonNull(runnable); @@ -36,17 +33,17 @@ public class RenderQueue { return; } - List> runnableList = this.typeRunnableMap.get(type); + List runnableList = this.typeRunnableMap.get(type); runnableList.remove(runnable); } - public void setTrackRender(MatrixStack matrixStack) { - this.matrixStack = matrixStack; + public void setTrackRender(boolean flag) { + this.trackRender = flag; } public void onRender(String type) { - if(this.matrixStack == null || !this.typeRunnableMap.containsKey(type))return; - this.typeRunnableMap.get(type).forEach(r -> r.accept(this.matrixStack)); + if(!this.trackRender || !this.typeRunnableMap.containsKey(type))return; + this.typeRunnableMap.get(type).forEach(Runnable::run); } } diff --git a/src/main/java/kaptainwutax/seedcracker/render/Renderer.java b/src/main/java/kaptainwutax/seedcracker/render/Renderer.java index d1c97af..88485bd 100644 --- a/src/main/java/kaptainwutax/seedcracker/render/Renderer.java +++ b/src/main/java/kaptainwutax/seedcracker/render/Renderer.java @@ -10,8 +10,6 @@ public abstract class Renderer { public abstract void render(); - public abstract BlockPos getPos(); - protected Vec3d toVec3d(BlockPos pos) { return new Vec3d(pos.getX(), pos.getY(), pos.getZ()); } diff --git a/src/main/java/kaptainwutax/seedcracker/util/Rand.java b/src/main/java/kaptainwutax/seedcracker/util/Rand.java index 003c66b..e045f46 100644 --- a/src/main/java/kaptainwutax/seedcracker/util/Rand.java +++ b/src/main/java/kaptainwutax/seedcracker/util/Rand.java @@ -2,8 +2,6 @@ package kaptainwutax.seedcracker.util; import kaptainwutax.seedcracker.util.math.LCG; -import java.util.Random; - public class Rand implements Cloneable { public static final LCG JAVA_LCG = new LCG(0x5DEECE66DL, 0xBL, 1L << 48); @@ -71,10 +69,6 @@ public class Rand implements Cloneable { return (((long)this.next(27) << 27) + this.next(27)) / (double)(1L << 54); } - public Random toRandom() { - return new Random(this.seed ^ JAVA_LCG.multiplier); - } - @Override public boolean equals(Object obj) { if(obj == this)return true; diff --git a/src/main/java/kaptainwutax/seedcracker/util/Seeds.java b/src/main/java/kaptainwutax/seedcracker/util/Seeds.java deleted file mode 100644 index 2939f23..0000000 --- a/src/main/java/kaptainwutax/seedcracker/util/Seeds.java +++ /dev/null @@ -1,29 +0,0 @@ -package kaptainwutax.seedcracker.util; - -public class Seeds { - - public static long setRegionSeed(Rand rand, long worldSeed, int regionX, int regionZ, int salt) { - long seed = (long)regionX * 341873128712L + (long)regionZ * 132897987541L + worldSeed + (long)salt; - rand.setSeed(seed, true); - return seed; - } - - public static long setStructureStartSeed(Rand rand, long worldSeed, int chunkX, int chunkZ) { - rand.setSeed(worldSeed, true); - long a = rand.nextLong(); - long b = rand.nextLong(); - long seed = (long)chunkX * a ^ (long)chunkZ * b ^ worldSeed; - rand.setSeed(seed, true); - return seed; - } - - public static long setWeakSeed(Rand rand, long worldSeed, int chunkX, int chunkZ) { - int sX = chunkX >> 4; - int sZ = chunkZ >> 4; - long seed = (long)(sX ^ sZ << 4) ^ worldSeed; - rand.setSeed(seed, true); - rand.nextInt(); - return seed; - } - -} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index d992d04..2c48cd5 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -1,7 +1,7 @@ { "schemaVersion": 1, "id": "seedcracker", - "version": "0.0.2", + "version": "0.0.1", "name": "Seed Cracker", "description": "This is an example description! Tell everyone what your mod is about!",