diff --git a/gradle.properties b/gradle.properties index c511653..107467d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,8 +4,8 @@ org.gradle.jvmargs=-Xmx1G # Fabric Properties # check these on https://fabricmc.net/use minecraft_version=1.14.4 - yarn_mappings=1.14.4+build.12 - loader_version=0.6.2+build.166 + yarn_mappings=1.14.4+build.15 + loader_version=0.7.2+build.174 # Mod Properties mod_version = 1.0.0 @@ -14,4 +14,4 @@ org.gradle.jvmargs=-Xmx1G # Dependencies # currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api - fabric_version=0.3.2+build.218-1.14 + fabric_version=0.4.1+build.245-1.14 diff --git a/src/main/java/kaptainwutax/seedcracker/FinderQueue.java b/src/main/java/kaptainwutax/seedcracker/FinderQueue.java deleted file mode 100644 index 4f8c95f..0000000 --- a/src/main/java/kaptainwutax/seedcracker/FinderQueue.java +++ /dev/null @@ -1,96 +0,0 @@ -package kaptainwutax.seedcracker; - -import com.mojang.blaze3d.platform.GlStateManager; -import io.netty.util.internal.ConcurrentSet; -import kaptainwutax.seedcracker.finder.*; -import kaptainwutax.seedcracker.util.FinderBuilder; -import net.minecraft.util.math.ChunkPos; -import net.minecraft.world.World; - -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -public class FinderQueue { - - private final static FinderQueue INSTANCE = new FinderQueue(); - public static final ExecutorService SERVICE = Executors.newFixedThreadPool(5); - - public RenderType renderType = RenderType.XRAY; - private List finderBuilders = new ArrayList<>(); - private Set activeFinders = new ConcurrentSet<>(); - - private FinderQueue() { - this.clear(); - } - - public static FinderQueue get() { - return INSTANCE; - } - - public void onChunkData(World world, ChunkPos chunkPos) { - this.finderBuilders.forEach(finderBuilder -> { - SERVICE.submit(() -> { - List finders = finderBuilder.build(world, chunkPos); - - finders.forEach(finder -> { - if (finder.isValidDimension(finder.getWorld().dimension.getType())) { - finder.findInChunk(); - if(!finder.isUseless()) { - this.activeFinders.add(finder); - } - } - }); - }); - }); - } - - public void renderFinders() { - if(this.renderType == RenderType.OFF)return; - - GlStateManager.disableTexture(); - - //Makes it render through blocks. - if(this.renderType == RenderType.XRAY) { - GlStateManager.disableDepthTest(); - } - - this.activeFinders.forEach(finder -> { - if(finder.shouldRender()) { - finder.render(); - } - }); - - GlStateManager.enableTexture(); - - if(this.renderType == RenderType.XRAY) { - GlStateManager.enableDepthTest(); - } - } - - public void clear() { - this.activeFinders.clear(); - this.finderBuilders.clear(); - - this.finderBuilders.add(DungeonFinder::create); - this.finderBuilders.add(BuriedTreasureFinder::create); - this.finderBuilders.add(SwampHutFinder::create); - this.finderBuilders.add(DesertTempleFinder::create); - this.finderBuilders.add(JungleTempleFinder::create); - this.finderBuilders.add(EndPillarsFinder::create); - this.finderBuilders.add(BiomeFinder::create); - this.finderBuilders.add(OceanMonumentFinder::create); - this.finderBuilders.add(EndCityFinder::create); - this.finderBuilders.add(IglooFinder::create); - - //this.finderBuilders.add(DiamondOreFinder::create); - //this.finderBuilders.add(InfestedStoneOreFinder::create); - } - - public enum RenderType { - OFF, ON, XRAY - } - -} diff --git a/src/main/java/kaptainwutax/seedcracker/SeedCracker.java b/src/main/java/kaptainwutax/seedcracker/SeedCracker.java index 5c18988..bcbf862 100644 --- a/src/main/java/kaptainwutax/seedcracker/SeedCracker.java +++ b/src/main/java/kaptainwutax/seedcracker/SeedCracker.java @@ -1,21 +1,31 @@ package kaptainwutax.seedcracker; +import com.google.common.collect.Lists; import kaptainwutax.seedcracker.cracker.*; +import kaptainwutax.seedcracker.finder.FinderQueue; import kaptainwutax.seedcracker.render.RenderQueue; +import kaptainwutax.seedcracker.util.Rand; import net.fabricmc.api.ModInitializer; 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.Random; -import java.util.stream.IntStream; public class SeedCracker implements ModInitializer { @@ -31,9 +41,54 @@ public class SeedCracker implements ModInitializer { 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() { @@ -46,6 +101,7 @@ public class SeedCracker implements ModInitializer { this.pillarSeeds = null; this.structureCache.clear(); this.biomeCache.clear(); + this.populationCache.clear(); } public synchronized boolean onPillarData(PillarData pillarData) { @@ -75,12 +131,13 @@ public class SeedCracker implements ModInitializer { added = true; } - if(this.structureSeeds == null && this.pillarSeeds != null && this.structureCache.size() >= 3) { + if(this.structureSeeds == null && this.pillarSeeds != null && this.structureCache.size() + this.populationCache.size() >= 5) { this.structureSeeds = new ArrayList<>(); LOG.warn("Looking for structure seeds with " + this.structureCache.size() + " structure features."); + LOG.warn("Looking for structure seeds with " + this.populationCache.size() + " population features."); this.pillarSeeds.forEach(pillarSeed -> { - timeMachine.buildStructureSeeds(pillarSeed, this.structureCache, this.structureSeeds); + timeMachine.buildStructureSeeds(pillarSeed, this.structureCache, this.populationCache, this.structureSeeds); }); if(this.structureSeeds.size() > 0) { @@ -113,37 +170,7 @@ public class SeedCracker implements ModInitializer { added = true; } - if(this.worldSeeds == null && this.structureSeeds != null && this.populationCache.size() >= 4) { - this.worldSeeds = new ArrayList<>(); - LOG.warn("Looking for world seeds with " + this.populationCache.size() + " decorators."); - - for(int i = 0; i < this.structureSeeds.size(); i++) { - SeedCracker.LOG.warn("Progress " + (i * 100.0f) / this.structureSeeds.size() + "%..."); - - long structureSeed = this.structureSeeds.get(i); - - for(long j = 0; j < (1L << 16); j++) { - long worldSeed = (j << 48) | structureSeed; - boolean goodSeed = true; - - for(PopulationData data: this.populationCache) { - if(!data.test(worldSeed)) { - goodSeed = false; - break; - } - } - - if(goodSeed) { - this.worldSeeds.add(worldSeed); - } - } - } - - LOG.warn("Finished search with " + this.worldSeeds + (this.worldSeeds.size() == 1 ? " seed." : " seeds.")); - } else if(this.worldSeeds != null && populationData != null) { - this.worldSeeds.removeIf(worldSeed -> !populationData.test(worldSeed)); - } - + this.onStructureData(null); return added; } @@ -209,8 +236,13 @@ public class SeedCracker implements ModInitializer { return added; } - public static void main(String[] args) { - Random rand = new Random(1234L); + 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); @@ -220,7 +252,100 @@ public class SeedCracker implements ModInitializer { 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/command/ClientCommand.java b/src/main/java/kaptainwutax/seedcracker/command/ClientCommand.java index 3de448d..6a01a5a 100644 --- a/src/main/java/kaptainwutax/seedcracker/command/ClientCommand.java +++ b/src/main/java/kaptainwutax/seedcracker/command/ClientCommand.java @@ -2,10 +2,10 @@ package kaptainwutax.seedcracker.command; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import kaptainwutax.seedcracker.ClientCommands; import net.minecraft.client.MinecraftClient; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.text.LiteralText; +import net.minecraft.util.Formatting; import static net.minecraft.server.command.CommandManager.literal; @@ -16,7 +16,7 @@ public abstract class ClientCommand { public abstract void build(LiteralArgumentBuilder builder); protected final void sendFeedback(String message, boolean overlay) { - MinecraftClient.getInstance().player.addChatMessage(new LiteralText(message), overlay); + MinecraftClient.getInstance().player.addChatMessage(new LiteralText(message).formatted(Formatting.AQUA), overlay); } public final void register(CommandDispatcher dispatcher) { diff --git a/src/main/java/kaptainwutax/seedcracker/ClientCommands.java b/src/main/java/kaptainwutax/seedcracker/command/ClientCommands.java similarity index 84% rename from src/main/java/kaptainwutax/seedcracker/ClientCommands.java rename to src/main/java/kaptainwutax/seedcracker/command/ClientCommands.java index 7a52f40..6efbb71 100644 --- a/src/main/java/kaptainwutax/seedcracker/ClientCommands.java +++ b/src/main/java/kaptainwutax/seedcracker/command/ClientCommands.java @@ -1,10 +1,8 @@ -package kaptainwutax.seedcracker; +package kaptainwutax.seedcracker.command; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; -import kaptainwutax.seedcracker.command.ClientCommand; -import kaptainwutax.seedcracker.command.RenderCommand; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.command.CommandException; @@ -21,21 +19,23 @@ public class ClientCommands { public static final List COMMANDS = new ArrayList<>(); public static RenderCommand RENDER; + public static FinderCommand FINDER; static { COMMANDS.add(RENDER = new RenderCommand()); + COMMANDS.add(FINDER = new FinderCommand()); } public static void registerCommands(CommandDispatcher dispatcher) { COMMANDS.forEach(clientCommand -> clientCommand.register(dispatcher)); } - public static boolean isClientSideCommand(String[] params) { - if(params.length < 2)return false; - if(!PREFIX.equals(params[0]))return false; + public static boolean isClientSideCommand(String[] args) { + if(args.length < 2)return false; + if(!PREFIX.equals(args[0]))return false; for(ClientCommand command: COMMANDS) { - if(command.getName().equals(params[1])) { + if(command.getName().equals(args[1])) { return true; } } @@ -63,7 +63,7 @@ public class ClientCommands { } /** - * Shoutout to Earthcomputer for this awesome class. + * Magic class by Earthcomputer. * https://github.com/Earthcomputer/clientcommands/blob/fabric/src/main/java/net/earthcomputer/clientcommands/command/FakeCommandSource.java * */ public static class FakeCommandSource extends ServerCommandSource { diff --git a/src/main/java/kaptainwutax/seedcracker/command/FinderCommand.java b/src/main/java/kaptainwutax/seedcracker/command/FinderCommand.java new file mode 100644 index 0000000..04a25c8 --- /dev/null +++ b/src/main/java/kaptainwutax/seedcracker/command/FinderCommand.java @@ -0,0 +1,59 @@ +package kaptainwutax.seedcracker.command; + +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import kaptainwutax.seedcracker.finder.FinderConfig; +import kaptainwutax.seedcracker.finder.FinderQueue; +import net.minecraft.server.command.ServerCommandSource; + +import static net.minecraft.server.command.CommandManager.literal; + +public class FinderCommand extends ClientCommand { + + @Override + public String getName() { + return "finder"; + } + + @Override + public void build(LiteralArgumentBuilder builder) { + for(FinderConfig.Type finderType: FinderConfig.Type.values()) { + builder.then(literal("type") + .executes(context -> this.printFinderType(finderType)) + .then(literal(finderType.toString()) + .then(literal("ON").executes(context -> this.setFinderType(finderType, true))) + .then(literal("OFF").executes(context -> this.setFinderType(finderType, false)))) + ); + } + + for(FinderConfig.Category finderCategory: FinderConfig.Category.values()) { + builder.then(literal("category") + .executes(context -> this.printFinderCategory(finderCategory)) + .then(literal(finderCategory.toString()) + .then(literal("ON").executes(context -> this.setFinderCategory(finderCategory, true))) + .then(literal("OFF").executes(context -> this.setFinderCategory(finderCategory, false)))) + ); + } + } + + private int printFinderCategory(FinderConfig.Category finderCategory) { + FinderConfig.Type.getForCategory(finderCategory).forEach(this::printFinderType); + return 0; + } + + private int printFinderType(FinderConfig.Type finderType) { + this.sendFeedback("Finder " + finderType + " is set to [" + String.valueOf(FinderQueue.get().finderConfig.getTypeState(finderType)).toUpperCase() + "].", false); + return 0; + } + + private int setFinderCategory(FinderConfig.Category finderCategory, boolean flag) { + FinderConfig.Type.getForCategory(finderCategory).forEach(finderType -> this.setFinderType(finderType, flag)); + return 0; + } + + private int setFinderType(FinderConfig.Type finderType, boolean flag) { + FinderQueue.get().finderConfig.setTypeState(finderType, flag); + this.sendFeedback("Finder " + finderType + " has been set to [" + String.valueOf(flag).toUpperCase() + "].", false); + return 0; + } + +} diff --git a/src/main/java/kaptainwutax/seedcracker/command/RenderCommand.java b/src/main/java/kaptainwutax/seedcracker/command/RenderCommand.java index 058c026..dd4ad9c 100644 --- a/src/main/java/kaptainwutax/seedcracker/command/RenderCommand.java +++ b/src/main/java/kaptainwutax/seedcracker/command/RenderCommand.java @@ -1,7 +1,7 @@ package kaptainwutax.seedcracker.command; import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import kaptainwutax.seedcracker.FinderQueue; +import kaptainwutax.seedcracker.finder.FinderQueue; import net.minecraft.server.command.ServerCommandSource; import static net.minecraft.server.command.CommandManager.literal; @@ -17,10 +17,13 @@ public class RenderCommand extends ClientCommand { public void build(LiteralArgumentBuilder builder) { builder.then(literal("outlines") .executes(context -> this.printRenderMode()) - .then(literal("XRAY").executes(context -> this.setRenderMode(FinderQueue.RenderType.XRAY))) - .then(literal("ON").executes(context -> this.setRenderMode(FinderQueue.RenderType.ON))) - .then(literal("OFF").executes(context -> this.setRenderMode(FinderQueue.RenderType.OFF))) ); + + for(FinderQueue.RenderType renderType: FinderQueue.RenderType.values()) { + builder.then(literal("outlines") + .then(literal(renderType.toString()).executes(context -> this.setRenderMode(renderType))) + ); + } } private int printRenderMode() { diff --git a/src/main/java/kaptainwutax/seedcracker/cracker/DecoratorCache.java b/src/main/java/kaptainwutax/seedcracker/cracker/DecoratorCache.java new file mode 100644 index 0000000..67bac51 --- /dev/null +++ b/src/main/java/kaptainwutax/seedcracker/cracker/DecoratorCache.java @@ -0,0 +1,69 @@ +package kaptainwutax.seedcracker.cracker; + +import kaptainwutax.seedcracker.SeedCracker; +import net.minecraft.util.registry.Registry; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.gen.GenerationStep; +import net.minecraft.world.gen.decorator.Decorator; +import net.minecraft.world.gen.feature.ConfiguredFeature; +import net.minecraft.world.gen.feature.DecoratedFeatureConfig; +import net.minecraft.world.gen.feature.FeatureConfig; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class DecoratorCache { + + public static int INVALID = -1; + + private static DecoratorCache INSTANCE = new DecoratorCache(); + private boolean initialized = false; + + private Map, Integer>> decoratorSaltMap = new HashMap<>(); + + public static DecoratorCache get() { + return INSTANCE; + } + + public void initialize() { + Registry.BIOME.forEach(biome -> { + this.decoratorSaltMap.put(biome, new HashMap<>()); + + for(GenerationStep.Feature genStep: GenerationStep.Feature.values()) { + this.initializeBiomeStep(biome, genStep); + } + }); + + this.initialized = true; + } + + private void initializeBiomeStep(Biome biome, GenerationStep.Feature genStep) { + List> features = biome.getFeaturesForStep(genStep); + + for(int i = 0; i < features.size(); i++) { + FeatureConfig config = features.get(i).config; + if(!(config instanceof DecoratedFeatureConfig))continue; + this.decoratorSaltMap.get(biome).put(((DecoratedFeatureConfig)config).decorator.decorator, i + genStep.ordinal() * 10000); + } + } + + public int getSalt(Biome biome, Decorator feature, boolean debug) { + if(!this.initialized) { + this.initialize(); + } + + Integer salt = this.decoratorSaltMap.get(biome).get(feature); + + if(salt == null) { + if(debug) { + SeedCracker.LOG.warn(biome.getClass().getSimpleName() + " does not have decorator " + feature + "."); + } + + salt = INVALID; + } + + return salt; + } + +} diff --git a/src/main/java/kaptainwutax/seedcracker/cracker/DungeonData.java b/src/main/java/kaptainwutax/seedcracker/cracker/DungeonData.java index 31b94da..ea97cfb 100644 --- a/src/main/java/kaptainwutax/seedcracker/cracker/DungeonData.java +++ b/src/main/java/kaptainwutax/seedcracker/cracker/DungeonData.java @@ -1,18 +1,20 @@ package kaptainwutax.seedcracker.cracker; +import kaptainwutax.seedcracker.util.Rand; +import kaptainwutax.seedcracker.util.math.LCG; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; import net.minecraft.world.biome.Biome; -import net.minecraft.world.gen.ChunkRandom; -import net.minecraft.world.gen.GenerationStep; import net.minecraft.world.gen.decorator.Decorator; -import java.util.ArrayList; import java.util.List; public class DungeonData extends PopulationData { - public static final Feature DUNGEON = new Feature(GenerationStep.Feature.UNDERGROUND_STRUCTURES, Decorator.DUNGEONS) {}; + public static LCG REVERSE_SKIP = Rand.JAVA_LCG.combine(-1); + public static LCG Y_START_SKIP = Rand.JAVA_LCG.combine(2); + public static LCG Y_SKIP = Rand.JAVA_LCG.combine(5); + public static final Integer COBBLESTONE_CALL = 0; public static final Integer MOSSY_COBBLESTONE_CALL = 1; @@ -20,28 +22,37 @@ public class DungeonData extends PopulationData { private final List> floorCallsList; public DungeonData(ChunkPos chunkPos, Biome biome, List starts, List> floorCallsList) { - super(chunkPos, DUNGEON, biome); + super(chunkPos, Decorator.DUNGEONS, biome); this.starts = starts; this.floorCallsList = floorCallsList; } @Override - public boolean test(ChunkRandom chunkRandom) { - List idsToCheck = new ArrayList<>(); + public boolean testDecorator(long decoratorSeed) { + if(this.starts.isEmpty())return false; + + //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++) { - BlockPos pos = new BlockPos(chunkRandom.nextInt(16), chunkRandom.nextInt(256), chunkRandom.nextInt(16)); - int a = this.starts.indexOf(pos); - if(a != -1)idsToCheck.add(a); + currentSeed = i == 0 ? Y_START_SKIP.nextSeed(currentSeed) : Y_SKIP.nextSeed(currentSeed); - //We assume the dungeon failed, skip 2 calls. - chunkRandom.nextBoolean(); - chunkRandom.nextBoolean(); + if(currentSeed >> 40 == start.getY()) { + valid = true; + break; + } } - if(idsToCheck.size() != this.starts.size())return false; + if(!valid)return false; - //TODO: Implement floor calls. + 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/EmeraldOreData.java b/src/main/java/kaptainwutax/seedcracker/cracker/EmeraldOreData.java new file mode 100644 index 0000000..2df85af --- /dev/null +++ b/src/main/java/kaptainwutax/seedcracker/cracker/EmeraldOreData.java @@ -0,0 +1,55 @@ +package kaptainwutax.seedcracker.cracker; + +import kaptainwutax.seedcracker.util.Rand; +import kaptainwutax.seedcracker.util.math.LCG; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.gen.decorator.Decorator; + +import java.util.List; +import java.util.stream.Collectors; + +public class EmeraldOreData extends PopulationData { + + public static final LCG[] SKIP = { + Rand.JAVA_LCG.combine(0), + Rand.JAVA_LCG.combine(1), + Rand.JAVA_LCG.combine(2), + Rand.JAVA_LCG.combine(3) + }; + + private List starts; + + public EmeraldOreData(ChunkPos chunkPos, Biome biome, List ores) { + super(chunkPos, Decorator.EMERALD_ORE, biome); + + this.starts = ores.stream().map(pos -> { + return new BlockPos(pos.getX() & 15, pos.getY(), pos.getZ() & 15); + }).collect(Collectors.toList()); + } + + @Override + public boolean testDecorator(long decoratorSeed) { + if(this.starts.isEmpty())return false; + + //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; i++) { + int x = rand.nextInt(16); + int y = rand.nextInt(28) + 4; + int z = rand.nextInt(16); + + if(x == start.getX() && y == start.getY() && z == start.getZ()) { + return true; + } + } + + return false; + } + +} diff --git a/src/main/java/kaptainwutax/seedcracker/cracker/EndGatewayData.java b/src/main/java/kaptainwutax/seedcracker/cracker/EndGatewayData.java new file mode 100644 index 0000000..faf06f8 --- /dev/null +++ b/src/main/java/kaptainwutax/seedcracker/cracker/EndGatewayData.java @@ -0,0 +1,34 @@ +package kaptainwutax.seedcracker.cracker; + +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.decorator.Decorator; + +public class EndGatewayData extends PopulationData { + + private int xOffset; + private int zOffset; + private int height; + + public EndGatewayData(ChunkPos chunkPos, Biome biome, BlockPos pos, int height) { + super(chunkPos, Decorator.END_GATEWAY, biome); + this.xOffset = pos.getX() & 15; + this.zOffset = pos.getZ() & 15; + this.height = height; + } + + @Override + 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; + if(rand.nextInt(7) != this.height - 3)return false; + + return true; + } + +} diff --git a/src/main/java/kaptainwutax/seedcracker/cracker/PopulationData.java b/src/main/java/kaptainwutax/seedcracker/cracker/PopulationData.java index 9cdcd04..bb8d23a 100644 --- a/src/main/java/kaptainwutax/seedcracker/cracker/PopulationData.java +++ b/src/main/java/kaptainwutax/seedcracker/cracker/PopulationData.java @@ -1,5 +1,6 @@ package kaptainwutax.seedcracker.cracker; +import kaptainwutax.seedcracker.util.Rand; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; import net.minecraft.world.biome.Biome; @@ -10,26 +11,44 @@ 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 Feature feature; + private final Decorator decorator; private final Biome biome; - public PopulationData(ChunkPos chunkPos, Feature feature, Biome biome) { + public PopulationData(ChunkPos chunkPos, Decorator decorator, Biome biome) { this.chunkPos = chunkPos; - this.feature = feature; + this.decorator = decorator; this.biome = biome; } - public final boolean test(long worldSeed) { - ChunkRandom chunkRandom = this.feature.buildRand(worldSeed, this.biome, this.chunkPos); - return this.test(chunkRandom); + 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 abstract boolean test(ChunkRandom chunkRandom); + 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) { @@ -37,7 +56,7 @@ public abstract class PopulationData { if(obj instanceof PopulationData) { PopulationData populationData = ((PopulationData)obj); - return populationData.chunkPos.equals(this.chunkPos) && populationData.feature == this.feature; + return populationData.chunkPos.equals(this.chunkPos) && populationData.decorator == this.decorator; } return false; @@ -45,6 +64,8 @@ public abstract class PopulationData { public abstract static class Feature { + private Map CACHE = new HashMap<>(); + private GenerationStep.Feature genStep; private Decorator decorator; @@ -54,6 +75,10 @@ public abstract class PopulationData { } 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++) { @@ -65,7 +90,8 @@ public abstract class PopulationData { BlockPos pos = new BlockPos(chunkPos.getStartX(), 0, chunkPos.getStartZ()); ChunkRandom chunkRandom = new ChunkRandom(); long populationSeed = chunkRandom.setSeed(worldSeed, pos.getX(), pos.getZ()); - chunkRandom.setFeatureSeed(populationSeed, i, this.genStep.ordinal()); + long seed = chunkRandom.setFeatureSeed(populationSeed, i, this.genStep.ordinal()); + CACHE.put(biome, seed ^ Rand.JAVA_LCG.multiplier); return chunkRandom; } } diff --git a/src/main/java/kaptainwutax/seedcracker/cracker/TimeMachine.java b/src/main/java/kaptainwutax/seedcracker/cracker/TimeMachine.java index ebe0526..3a074b1 100644 --- a/src/main/java/kaptainwutax/seedcracker/cracker/TimeMachine.java +++ b/src/main/java/kaptainwutax/seedcracker/cracker/TimeMachine.java @@ -6,7 +6,6 @@ import kaptainwutax.seedcracker.util.math.LCG; import net.minecraft.world.gen.ChunkRandom; import java.util.List; -import java.util.Set; public class TimeMachine { @@ -16,7 +15,7 @@ public class TimeMachine { } - public List buildStructureSeeds(int pillarSeed, List structureDataList, List structureSeeds) { + public List buildStructureSeeds(int pillarSeed, List structureDataList, List populationDataList, List structureSeeds) { ChunkRandom chunkRandom = new ChunkRandom(); for(long i = 0; i < (1L << 32); i++) { @@ -28,13 +27,15 @@ public class TimeMachine { boolean goodSeed = true; for(StructureData structureData: structureDataList) { + if(!goodSeed)break; chunkRandom.setStructureSeed(structureSeed, structureData.getRegionX(), structureData.getRegionZ(), structureData.getSalt()); + if(!structureData.test(chunkRandom))goodSeed = false; + } - if(!structureData.test(chunkRandom)) { - goodSeed = false; - break; - } + for(PopulationData populationData: populationDataList) { + if(!goodSeed)break; + if(!populationData.test(structureSeed))goodSeed = false; } if(goodSeed) { diff --git a/src/main/java/kaptainwutax/seedcracker/finder/BiomeFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/BiomeFinder.java index 365a5c3..f75b0d3 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/BiomeFinder.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/BiomeFinder.java @@ -37,7 +37,7 @@ public class BiomeFinder extends Finder { } result.forEach(pos -> { - this.renderers.add(new Cube(pos, new Vector4f(0.0f, 1.0f, 0.0f, 1.0f))); + this.renderers.add(new Cube(pos, new Vector4f(0.05f, 0.2f, 0.125f, 1.0f))); }); return result; diff --git a/src/main/java/kaptainwutax/seedcracker/finder/DefaultFinderConfig.java b/src/main/java/kaptainwutax/seedcracker/finder/DefaultFinderConfig.java new file mode 100644 index 0000000..5ea5391 --- /dev/null +++ b/src/main/java/kaptainwutax/seedcracker/finder/DefaultFinderConfig.java @@ -0,0 +1,13 @@ +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); + this.typeStates.put(Type.MANSION, false); + } + +} diff --git a/src/main/java/kaptainwutax/seedcracker/finder/FinderConfig.java b/src/main/java/kaptainwutax/seedcracker/finder/FinderConfig.java new file mode 100644 index 0000000..c00650c --- /dev/null +++ b/src/main/java/kaptainwutax/seedcracker/finder/FinderConfig.java @@ -0,0 +1,101 @@ +package kaptainwutax.seedcracker.finder; + +import kaptainwutax.seedcracker.finder.population.DungeonFinder; +import kaptainwutax.seedcracker.finder.population.EndGatewayFinder; +import kaptainwutax.seedcracker.finder.population.EndPillarsFinder; +import kaptainwutax.seedcracker.finder.population.ore.DiamondOreFinder; +import kaptainwutax.seedcracker.finder.population.ore.EmeraldOreFinder; +import kaptainwutax.seedcracker.finder.population.ore.InfestedStoneOreFinder; +import kaptainwutax.seedcracker.finder.structure.*; +import kaptainwutax.seedcracker.util.FinderBuilder; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.stream.Collectors; + +public class FinderConfig { + + protected Map typeStates = new HashMap<>(); + protected Map> activeFinders = new ConcurrentHashMap<>(); + + public FinderConfig() { + for(Type type: Type.values()) { + this.typeStates.put(type, true); + } + } + + public List getActiveFinderTypes() { + return this.typeStates.entrySet().stream() + .filter(Map.Entry::getValue) + .map(Map.Entry::getKey) + .collect(Collectors.toList()); + } + + public List getActiveFinders() { + this.activeFinders.values().forEach(finders -> { + finders.removeIf(Finder::isUseless); + }); + + return this.activeFinders.values().stream() + .flatMap(Queue::stream).collect(Collectors.toList()); + } + + public void addFinder(Type type, Finder finder) { + if(finder.isUseless())return; + + if(!this.activeFinders.containsKey(type)) { + this.activeFinders.put(type, new ConcurrentLinkedQueue<>()); + } + + this.activeFinders.get(type).add(finder); + } + + public boolean getTypeState(Type type) { + return this.typeStates.get(type); + } + + public void setTypeState(Type type, boolean flag) { + this.typeStates.put(type, flag); + } + + public enum Category { + STRUCTURES, + BIOMES, + ORES, + OTHERS + } + + public enum Type { + BURIED_TREASURE(BuriedTreasureFinder::create, Category.STRUCTURES), + DESERT_TEMPLE(DesertTempleFinder::create, Category.STRUCTURES), + END_CITY(EndCityFinder::create, Category.STRUCTURES), + IGLOO(IglooFinder::create, Category.STRUCTURES), + JUNGLE_TEMPLE(JungleTempleFinder::create, Category.STRUCTURES), + MONUMENT(OceanMonumentFinder::create, Category.STRUCTURES), + SWAMP_HUT(SwampHutFinder::create, Category.STRUCTURES), + MANSION(MansionFinder::create, Category.STRUCTURES), + + END_PILLARS(EndPillarsFinder::create, Category.OTHERS), + END_GATEWAY(EndGatewayFinder::create, Category.OTHERS), + DUNGEON(DungeonFinder::create, Category.OTHERS), + DIAMOND_ORE(DiamondOreFinder::create, Category.ORES), + INFESTED_STONE_ORE(InfestedStoneOreFinder::create, Category.ORES), + EMERALD_ORE(EmeraldOreFinder::create, Category.ORES), + + BIOME(BiomeFinder::create, Category.BIOMES); + + public final FinderBuilder finderBuilder; + private final Category category; + + Type(FinderBuilder finderBuilder, Category category) { + this.finderBuilder = finderBuilder; + this.category = category; + } + + public static List getForCategory(Category category) { + return Arrays.stream(values()).filter(type -> type.category == category).collect(Collectors.toList()); + } + } + +} diff --git a/src/main/java/kaptainwutax/seedcracker/finder/FinderQueue.java b/src/main/java/kaptainwutax/seedcracker/finder/FinderQueue.java new file mode 100644 index 0000000..882332a --- /dev/null +++ b/src/main/java/kaptainwutax/seedcracker/finder/FinderQueue.java @@ -0,0 +1,75 @@ +package kaptainwutax.seedcracker.finder; + +import com.mojang.blaze3d.platform.GlStateManager; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.World; + +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class FinderQueue { + + private final static FinderQueue INSTANCE = new FinderQueue(); + public static ExecutorService SERVICE = Executors.newFixedThreadPool(5); + + public RenderType renderType = RenderType.XRAY; + public FinderConfig finderConfig = new DefaultFinderConfig(); + + private FinderQueue() { + this.clear(); + } + + public static FinderQueue get() { + return INSTANCE; + } + + public void onChunkData(World world, ChunkPos chunkPos) { + this.finderConfig.getActiveFinderTypes().forEach(type -> { + SERVICE.submit(() -> { + List finders = type.finderBuilder.build(world, chunkPos); + + finders.forEach(finder -> { + if(finder.isValidDimension(world.dimension.getType())) { + this.finderConfig.addFinder(type, finder); + finder.findInChunk(); + this.finderConfig.addFinder(type, finder); + } + }); + }); + }); + } + + public void renderFinders() { + if(this.renderType == RenderType.OFF)return; + + GlStateManager.disableTexture(); + + //Makes it render through blocks. + if(this.renderType == RenderType.XRAY) { + GlStateManager.disableDepthTest(); + } + + this.finderConfig.getActiveFinders().forEach(finder -> { + if(finder.shouldRender()) { + finder.render(); + } + }); + + GlStateManager.enableTexture(); + + if(this.renderType == RenderType.XRAY) { + GlStateManager.enableDepthTest(); + } + } + + public void clear() { + this.renderType = RenderType.XRAY; + this.finderConfig = new DefaultFinderConfig(); + } + + public enum RenderType { + OFF, ON, XRAY + } + +} diff --git a/src/main/java/kaptainwutax/seedcracker/finder/DungeonFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/population/DungeonFinder.java similarity index 97% rename from src/main/java/kaptainwutax/seedcracker/finder/DungeonFinder.java rename to src/main/java/kaptainwutax/seedcracker/finder/population/DungeonFinder.java index 79f3294..e5e3f02 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/DungeonFinder.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/population/DungeonFinder.java @@ -1,7 +1,9 @@ -package kaptainwutax.seedcracker.finder; +package kaptainwutax.seedcracker.finder.population; import kaptainwutax.seedcracker.SeedCracker; import kaptainwutax.seedcracker.cracker.DungeonData; +import kaptainwutax.seedcracker.finder.BlockFinder; +import kaptainwutax.seedcracker.finder.Finder; import kaptainwutax.seedcracker.render.Cube; import kaptainwutax.seedcracker.util.PosIterator; import net.minecraft.block.Block; diff --git a/src/main/java/kaptainwutax/seedcracker/finder/population/EndGatewayFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/population/EndGatewayFinder.java new file mode 100644 index 0000000..959e6ff --- /dev/null +++ b/src/main/java/kaptainwutax/seedcracker/finder/population/EndGatewayFinder.java @@ -0,0 +1,91 @@ +package kaptainwutax.seedcracker.finder.population; + +import kaptainwutax.seedcracker.SeedCracker; +import kaptainwutax.seedcracker.cracker.DecoratorCache; +import kaptainwutax.seedcracker.cracker.EndGatewayData; +import kaptainwutax.seedcracker.finder.BlockFinder; +import kaptainwutax.seedcracker.finder.Finder; +import kaptainwutax.seedcracker.render.Cuboid; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.client.util.math.Vector4f; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.World; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.dimension.DimensionType; +import net.minecraft.world.gen.decorator.Decorator; + +import java.util.ArrayList; +import java.util.List; + +public class EndGatewayFinder extends BlockFinder { + + protected static List SEARCH_POSITIONS = buildSearchPositions(CHUNK_POSITIONS, pos -> { + return false; + }); + + public EndGatewayFinder(World world, ChunkPos chunkPos) { + super(world, chunkPos, Blocks.END_GATEWAY); + this.searchPositions = SEARCH_POSITIONS; + } + + @Override + public List findInChunk() { + //If no end gateway is supposed to populate in this chunk, return. + Biome biome = this.world.getBiome(this.chunkPos.getCenterBlockPos().add(8, 0, 8)); + + if(DecoratorCache.get().getSalt(biome, Decorator.END_GATEWAY, false) == DecoratorCache.INVALID) { + return new ArrayList<>(); + } + + List result = super.findInChunk(); + List newResult = new ArrayList<>(); + + result.forEach(pos -> { + int height = this.findHeight(pos); + + if(height >= 3 && height <= 9) { + newResult.add(pos); + System.out.println("Height is " + 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))); + } + } + }); + + return newResult; + } + + private int findHeight(BlockPos pos) { + int height = 0; + + while(pos.getY() >= 0) { + pos = pos.down(); + height++; + + BlockState state = this.world.getBlockState(pos); + + //Bedrock generates below gateways. + if(state.getBlock() == Blocks.BEDROCK || state.getBlock() != Blocks.END_STONE) { + continue; + } + + break; + } + + return height; + } + + @Override + public boolean isValidDimension(DimensionType dimension) { + return dimension == DimensionType.THE_END; + } + + public static List create(World world, ChunkPos chunkPos) { + List finders = new ArrayList<>(); + finders.add(new EndGatewayFinder(world, chunkPos)); + return finders; + } + +} diff --git a/src/main/java/kaptainwutax/seedcracker/finder/EndPillarsFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/population/EndPillarsFinder.java similarity index 89% rename from src/main/java/kaptainwutax/seedcracker/finder/EndPillarsFinder.java rename to src/main/java/kaptainwutax/seedcracker/finder/population/EndPillarsFinder.java index ab58fc8..9fb5dc6 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/EndPillarsFinder.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/population/EndPillarsFinder.java @@ -1,7 +1,9 @@ -package kaptainwutax.seedcracker.finder; +package kaptainwutax.seedcracker.finder.population; import kaptainwutax.seedcracker.SeedCracker; import kaptainwutax.seedcracker.cracker.PillarData; +import kaptainwutax.seedcracker.finder.BlockFinder; +import kaptainwutax.seedcracker.finder.Finder; import kaptainwutax.seedcracker.render.Cube; import net.minecraft.block.Blocks; import net.minecraft.client.util.math.Vector4f; @@ -45,8 +47,11 @@ public class EndPillarsFinder extends Finder { if(result.size() == this.bedrockMarkers.length) { PillarData pillarData = new PillarData(result.stream().map(Vec3i::getY).collect(Collectors.toList())); - result.forEach(pos -> this.renderers.add(new Cube(pos, new Vector4f(0.5f, 0.0f, 0.5f, 1.0f)))); - SeedCracker.get().onPillarData(pillarData); + + if(SeedCracker.get().onPillarData(pillarData)){ + result.forEach(pos -> this.renderers.add(new Cube(pos, new Vector4f(0.5f, 0.0f, 0.5f, 1.0f)))); + } + } return result; diff --git a/src/main/java/kaptainwutax/seedcracker/finder/OreFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/population/OreFinder.java similarity index 98% rename from src/main/java/kaptainwutax/seedcracker/finder/OreFinder.java rename to src/main/java/kaptainwutax/seedcracker/finder/population/OreFinder.java index 8d967ca..702d19a 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/OreFinder.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/population/OreFinder.java @@ -1,5 +1,6 @@ -package kaptainwutax.seedcracker.finder; +package kaptainwutax.seedcracker.finder.population; +import kaptainwutax.seedcracker.finder.BlockFinder; import kaptainwutax.seedcracker.util.PosIterator; import net.minecraft.block.BlockState; import net.minecraft.util.math.BlockPos; diff --git a/src/main/java/kaptainwutax/seedcracker/finder/DiamondOreFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/population/ore/DiamondOreFinder.java similarity index 62% rename from src/main/java/kaptainwutax/seedcracker/finder/DiamondOreFinder.java rename to src/main/java/kaptainwutax/seedcracker/finder/population/ore/DiamondOreFinder.java index 89b15fe..8784edb 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/DiamondOreFinder.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/population/ore/DiamondOreFinder.java @@ -1,6 +1,6 @@ -package kaptainwutax.seedcracker.finder; +package kaptainwutax.seedcracker.finder.population.ore; -import kaptainwutax.seedcracker.render.Cube; +import kaptainwutax.seedcracker.finder.Finder; import net.minecraft.block.Blocks; import net.minecraft.client.util.math.Vector4f; import net.minecraft.util.math.BlockPos; @@ -10,14 +10,13 @@ import net.minecraft.world.gen.feature.OreFeatureConfig; import java.util.ArrayList; import java.util.List; -import java.util.Set; -public class DiamondOreFinder extends OreFinder { +public class DiamondOreFinder extends SimpleOreFinder { public static OreFeatureConfig CONFIG = new OreFeatureConfig(OreFeatureConfig.Target.NATURAL_STONE, Blocks.DIAMOND_ORE.getDefaultState(), 8); protected static List SEARCH_POSITIONS = buildSearchPositions(CHUNK_POSITIONS, pos -> { - if(pos.getY() > 16)return true; + if(pos.getY() > 16 + 4)return true; return false; }); @@ -27,22 +26,8 @@ public class DiamondOreFinder extends OreFinder { } @Override - public void findOreVeins(List> veins) { - List starts = new ArrayList<>(); - - for(Set vein: veins) { - BlockPos oreStart = new BlockPos( - this.findX(vein, OreFinder.HIGHEST), - this.findY(vein, OreFinder.LOWEST) + 3, - this.findZ(vein, OreFinder.HIGHEST) - ); - - starts.add(oreStart); - } - - starts.forEach(start -> { - this.renderers.add(new Cube(start, new Vector4f(1.0f, 1.0f, 1.0f, 1.0f))); - }); + public Vector4f getRenderColor() { + return new Vector4f(0.0f, 1.0f, 1.0f, 1.0f); } public static List create(World world, ChunkPos chunkPos) { diff --git a/src/main/java/kaptainwutax/seedcracker/finder/population/ore/EmeraldOreFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/population/ore/EmeraldOreFinder.java new file mode 100644 index 0000000..2774fb2 --- /dev/null +++ b/src/main/java/kaptainwutax/seedcracker/finder/population/ore/EmeraldOreFinder.java @@ -0,0 +1,57 @@ +package kaptainwutax.seedcracker.finder.population.ore; + +import kaptainwutax.seedcracker.SeedCracker; +import kaptainwutax.seedcracker.cracker.DecoratorCache; +import kaptainwutax.seedcracker.cracker.EmeraldOreData; +import kaptainwutax.seedcracker.finder.BlockFinder; +import kaptainwutax.seedcracker.finder.Finder; +import kaptainwutax.seedcracker.render.Cube; +import net.minecraft.block.Blocks; +import net.minecraft.client.util.math.Vector4f; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.World; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.dimension.DimensionType; +import net.minecraft.world.gen.decorator.Decorator; + +import java.util.ArrayList; +import java.util.List; + +public class EmeraldOreFinder extends BlockFinder { + + public EmeraldOreFinder(World world, ChunkPos chunkPos) { + super(world, chunkPos, Blocks.EMERALD_ORE); + } + + @Override + public List findInChunk() { + Biome biome = this.world.getBiome(this.chunkPos.getCenterBlockPos().add(8, 0, 8)); + + if(DecoratorCache.get().getSalt(biome, Decorator.EMERALD_ORE, false) == DecoratorCache.INVALID) { + return new ArrayList<>(); + } + + List result = super.findInChunk(); + + if(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))); + }); + } + + return result; + } + + @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 EmeraldOreFinder(world, chunkPos)); + return finders; + } + +} diff --git a/src/main/java/kaptainwutax/seedcracker/finder/InfestedStoneOreFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/population/ore/InfestedStoneOreFinder.java similarity index 57% rename from src/main/java/kaptainwutax/seedcracker/finder/InfestedStoneOreFinder.java rename to src/main/java/kaptainwutax/seedcracker/finder/population/ore/InfestedStoneOreFinder.java index 9ec8791..aa30abc 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/InfestedStoneOreFinder.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/population/ore/InfestedStoneOreFinder.java @@ -1,6 +1,6 @@ -package kaptainwutax.seedcracker.finder; +package kaptainwutax.seedcracker.finder.population.ore; -import kaptainwutax.seedcracker.render.Cube; +import kaptainwutax.seedcracker.finder.Finder; import net.minecraft.block.Blocks; import net.minecraft.client.util.math.Vector4f; import net.minecraft.util.math.BlockPos; @@ -10,14 +10,13 @@ import net.minecraft.world.gen.feature.OreFeatureConfig; import java.util.ArrayList; import java.util.List; -import java.util.Set; -public class InfestedStoneOreFinder extends OreFinder { +public class InfestedStoneOreFinder extends SimpleOreFinder { public static OreFeatureConfig CONFIG = new OreFeatureConfig(OreFeatureConfig.Target.NATURAL_STONE, Blocks.INFESTED_STONE.getDefaultState(), 9); - protected static List SEARCH_POSITIONS = buildSearchPositions(CHUNK_POSITIONS, pos -> { - if(pos.getY() > 70)return true; + protected static List SEARCH_POSITIONS = Finder.buildSearchPositions(Finder.CHUNK_POSITIONS, pos -> { + if(pos.getY() > 64 + 4)return true; return false; }); @@ -27,24 +26,8 @@ public class InfestedStoneOreFinder extends OreFinder { } @Override - public void findOreVeins(List> veins) { - List starts = new ArrayList<>(); - - for(Set vein: veins) { - if(vein.size() != 8)continue; - - BlockPos oreStart = new BlockPos( - this.findX(vein, OreFinder.HIGHEST), - this.findY(vein, OreFinder.LOWEST) + 3, - this.findZ(vein, OreFinder.HIGHEST) - ); - - starts.add(oreStart); - } - - starts.forEach(start -> { - this.renderers.add(new Cube(start, new Vector4f(0.0f, 1.0f, 1.0f, 1.0f))); - }); + public Vector4f getRenderColor() { + return new Vector4f(0.5f, 0.5f, 0.5f, 1.0f); } public static List create(World world, ChunkPos chunkPos) { diff --git a/src/main/java/kaptainwutax/seedcracker/finder/population/ore/SimpleOreFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/population/ore/SimpleOreFinder.java new file mode 100644 index 0000000..d0bf976 --- /dev/null +++ b/src/main/java/kaptainwutax/seedcracker/finder/population/ore/SimpleOreFinder.java @@ -0,0 +1,50 @@ +package kaptainwutax.seedcracker.finder.population.ore; + +import kaptainwutax.seedcracker.finder.population.OreFinder; +import kaptainwutax.seedcracker.render.Cuboid; +import net.minecraft.client.util.math.Vector4f; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.World; +import net.minecraft.world.gen.feature.OreFeatureConfig; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +public abstract class SimpleOreFinder extends OreFinder { + + public SimpleOreFinder(World world, ChunkPos chunkPos, OreFeatureConfig oreFeatureConfig) { + super(world, chunkPos, oreFeatureConfig); + } + + @Override + public void findOreVeins(List> veins) { + List starts = new ArrayList<>(); + + for(Set vein: veins) { + //This is a semi-accurate estimate. + BlockPos oreStart = new BlockPos( + this.findX(vein, OreFinder.HIGHEST), + this.findY(vein, OreFinder.LOWEST) + 2, + this.findZ(vein, OreFinder.HIGHEST) + ); + + starts.add(oreStart); + } + + //If the start overlaps with another chunk, get rid of it. + starts.removeIf(start -> { + if((start.getX() & 15) == 0 || (start.getX() & 15) == 15)return true; + if((start.getZ() & 15) == 0 || (start.getZ() & 15) == 15)return true; + return false; + }); + + starts.forEach(start -> { + this.renderers.add(new Cuboid(start.add(-1, -1, -1), start.add(1, 0, 1), this.getRenderColor())); + }); + } + + public abstract Vector4f getRenderColor(); + +} diff --git a/src/main/java/kaptainwutax/seedcracker/finder/AbstractTempleFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/structure/AbstractTempleFinder.java similarity index 79% rename from src/main/java/kaptainwutax/seedcracker/finder/AbstractTempleFinder.java rename to src/main/java/kaptainwutax/seedcracker/finder/structure/AbstractTempleFinder.java index 1c99e79..f8f9779 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/AbstractTempleFinder.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/structure/AbstractTempleFinder.java @@ -1,11 +1,14 @@ -package kaptainwutax.seedcracker.finder; +package kaptainwutax.seedcracker.finder.structure; +import kaptainwutax.seedcracker.finder.Finder; import net.minecraft.util.math.BlockPos; 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.StructureFeature; import java.util.ArrayList; import java.util.HashMap; @@ -40,9 +43,17 @@ public abstract class AbstractTempleFinder extends Finder { } public List findInChunkPiece(PieceFinder pieceFinder) { + Biome biome = this.world.getBiome(this.chunkPos.getCenterBlockPos().add(9, 0, 9)); + + if(!biome.hasStructureFeature(this.getStructureFeature())) { + return new ArrayList<>(); + } + return pieceFinder.findInChunk(); } + protected abstract StructureFeature getStructureFeature(); + public Map> findInChunkPieces() { Map> result = new HashMap<>(); diff --git a/src/main/java/kaptainwutax/seedcracker/finder/BuriedTreasureFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/structure/BuriedTreasureFinder.java similarity index 92% rename from src/main/java/kaptainwutax/seedcracker/finder/BuriedTreasureFinder.java rename to src/main/java/kaptainwutax/seedcracker/finder/structure/BuriedTreasureFinder.java index a781fb7..270a9d4 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/BuriedTreasureFinder.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/structure/BuriedTreasureFinder.java @@ -1,7 +1,9 @@ -package kaptainwutax.seedcracker.finder; +package kaptainwutax.seedcracker.finder.structure; import kaptainwutax.seedcracker.SeedCracker; import kaptainwutax.seedcracker.cracker.StructureData; +import kaptainwutax.seedcracker.finder.BlockFinder; +import kaptainwutax.seedcracker.finder.Finder; import kaptainwutax.seedcracker.render.Cube; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; @@ -41,6 +43,9 @@ public class BuriedTreasureFinder extends BlockFinder { CHEST_HOLDERS.add(Blocks.COAL_ORE.getDefaultState()); CHEST_HOLDERS.add(Blocks.IRON_ORE.getDefaultState()); CHEST_HOLDERS.add(Blocks.GOLD_ORE.getDefaultState()); + + //Ocean can turn stone into gravel. + CHEST_HOLDERS.add(Blocks.GRAVEL.getDefaultState()); } public BuriedTreasureFinder(World world, ChunkPos chunkPos) { diff --git a/src/main/java/kaptainwutax/seedcracker/finder/DesertTempleFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/structure/DesertTempleFinder.java similarity index 98% rename from src/main/java/kaptainwutax/seedcracker/finder/DesertTempleFinder.java rename to src/main/java/kaptainwutax/seedcracker/finder/structure/DesertTempleFinder.java index 941e459..31283d7 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/DesertTempleFinder.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/structure/DesertTempleFinder.java @@ -1,7 +1,8 @@ -package kaptainwutax.seedcracker.finder; +package kaptainwutax.seedcracker.finder.structure; import kaptainwutax.seedcracker.SeedCracker; import kaptainwutax.seedcracker.cracker.StructureData; +import kaptainwutax.seedcracker.finder.Finder; import kaptainwutax.seedcracker.render.Cuboid; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; @@ -12,8 +13,8 @@ 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.gen.feature.Feature; +import net.minecraft.world.gen.feature.StructureFeature; import java.util.ArrayList; import java.util.List; @@ -31,13 +32,6 @@ public class DesertTempleFinder extends AbstractTempleFinder { List combinedResult = new ArrayList<>(); result.forEach((pieceFinder, positions) -> { - positions.removeIf(pos -> { - Biome biome = world.getBiome(pos.add(9, 0, 9)); - if(!biome.hasStructureFeature(Feature.DESERT_PYRAMID))return true; - - return false; - }); - combinedResult.addAll(positions); positions.forEach(pos -> { @@ -50,6 +44,11 @@ public class DesertTempleFinder extends AbstractTempleFinder { return combinedResult; } + @Override + protected StructureFeature getStructureFeature() { + return Feature.DESERT_PYRAMID; + } + @Override public void buildStructure(PieceFinder finder) { BlockState blockState_1 = Blocks.SANDSTONE_STAIRS.getDefaultState().with(StairsBlock.FACING, Direction.NORTH); diff --git a/src/main/java/kaptainwutax/seedcracker/finder/EndCityFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/structure/EndCityFinder.java similarity index 97% rename from src/main/java/kaptainwutax/seedcracker/finder/EndCityFinder.java rename to src/main/java/kaptainwutax/seedcracker/finder/structure/EndCityFinder.java index 470c805..04702d4 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/EndCityFinder.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/structure/EndCityFinder.java @@ -1,7 +1,8 @@ -package kaptainwutax.seedcracker.finder; +package kaptainwutax.seedcracker.finder.structure; import kaptainwutax.seedcracker.SeedCracker; import kaptainwutax.seedcracker.cracker.StructureData; +import kaptainwutax.seedcracker.finder.Finder; import kaptainwutax.seedcracker.render.Cube; import kaptainwutax.seedcracker.render.Cuboid; import net.minecraft.block.BlockState; diff --git a/src/main/java/kaptainwutax/seedcracker/finder/IglooFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/structure/IglooFinder.java similarity index 75% rename from src/main/java/kaptainwutax/seedcracker/finder/IglooFinder.java rename to src/main/java/kaptainwutax/seedcracker/finder/structure/IglooFinder.java index c176927..3ee0986 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/IglooFinder.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/structure/IglooFinder.java @@ -1,7 +1,8 @@ -package kaptainwutax.seedcracker.finder; +package kaptainwutax.seedcracker.finder.structure; import kaptainwutax.seedcracker.SeedCracker; import kaptainwutax.seedcracker.cracker.StructureData; +import kaptainwutax.seedcracker.finder.Finder; import kaptainwutax.seedcracker.render.Cube; import kaptainwutax.seedcracker.render.Cuboid; import net.minecraft.block.BlockState; @@ -9,39 +10,52 @@ import net.minecraft.block.Blocks; import net.minecraft.client.util.math.Vector4f; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; -import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3i; import net.minecraft.world.World; import net.minecraft.world.dimension.DimensionType; +import net.minecraft.world.gen.feature.Feature; +import net.minecraft.world.gen.feature.StructureFeature; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; -public class IglooFinder extends Finder { +public class IglooFinder extends AbstractTempleFinder { protected static List SEARCH_POSITIONS = buildSearchPositions(CHUNK_POSITIONS, pos -> { return false; }); - protected List finders = new ArrayList<>(); - protected final Vec3i size = new Vec3i(7, 5, 8); - public IglooFinder(World world, ChunkPos chunkPos) { - super(world, chunkPos); - - Direction.Type.HORIZONTAL.forEach(direction -> { - PieceFinder finder = new PieceFinder(world, chunkPos, direction, size); + super(world, chunkPos, new Vec3i(7, 5, 8)); + //Igloos are weird. + this.finders.forEach(finder -> { finder.searchPositions = SEARCH_POSITIONS; - - buildStructure(finder); - this.finders.add(finder); }); } - private void buildStructure(PieceFinder finder) { + @Override + public List findInChunk() { + Map> result = this.findInChunkPieces(); + List combinedResult = new ArrayList<>(); + + result.forEach((pieceFinder, positions) -> { + combinedResult.addAll(positions); + + positions.forEach(pos -> { + 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))); + } + }); + }); + + return combinedResult; + } + + @Override + public void buildStructure(PieceFinder finder) { BlockState air = Blocks.AIR.getDefaultState(); BlockState snow = Blocks.SNOW_BLOCK.getDefaultState(); BlockState ice = Blocks.ICE.getDefaultState(); @@ -72,37 +86,8 @@ public class IglooFinder extends Finder { } @Override - public List findInChunk() { - 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, 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))); - } - }); - }); - - return combinedResult; - } - - public Map> findInChunkPieces() { - Map> result = new HashMap<>(); - - this.finders.forEach(pieceFinder -> { - result.put(pieceFinder, pieceFinder.findInChunk()); - }); - - return result; + protected StructureFeature getStructureFeature() { + return Feature.IGLOO; } @Override diff --git a/src/main/java/kaptainwutax/seedcracker/finder/JungleTempleFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/structure/JungleTempleFinder.java similarity index 96% rename from src/main/java/kaptainwutax/seedcracker/finder/JungleTempleFinder.java rename to src/main/java/kaptainwutax/seedcracker/finder/structure/JungleTempleFinder.java index 09f2998..19d2be6 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/JungleTempleFinder.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/structure/JungleTempleFinder.java @@ -1,7 +1,8 @@ -package kaptainwutax.seedcracker.finder; +package kaptainwutax.seedcracker.finder.structure; import kaptainwutax.seedcracker.SeedCracker; import kaptainwutax.seedcracker.cracker.StructureData; +import kaptainwutax.seedcracker.finder.Finder; import kaptainwutax.seedcracker.render.Cuboid; import net.minecraft.block.*; import net.minecraft.block.enums.WallMountLocation; @@ -12,8 +13,8 @@ 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.gen.feature.Feature; +import net.minecraft.world.gen.feature.StructureFeature; import java.util.ArrayList; import java.util.List; @@ -31,13 +32,6 @@ public class JungleTempleFinder extends AbstractTempleFinder { List combinedResult = new ArrayList<>(); result.forEach((pieceFinder, positions) -> { - positions.removeIf(pos -> { - Biome biome = world.getBiome(pos.add(9, 0, 9)); - if(!biome.hasStructureFeature(Feature.JUNGLE_TEMPLE))return true; - - return false; - }); - combinedResult.addAll(positions); positions.forEach(pos -> { @@ -50,6 +44,11 @@ public class JungleTempleFinder extends AbstractTempleFinder { return combinedResult; } + @Override + protected StructureFeature getStructureFeature() { + return Feature.JUNGLE_TEMPLE; + } + @Override public void buildStructure(PieceFinder finder) { BlockState eastStairs = Blocks.COBBLESTONE_STAIRS.getDefaultState().with(StairsBlock.FACING, Direction.EAST); diff --git a/src/main/java/kaptainwutax/seedcracker/finder/structure/MansionFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/structure/MansionFinder.java new file mode 100644 index 0000000..e51b59f --- /dev/null +++ b/src/main/java/kaptainwutax/seedcracker/finder/structure/MansionFinder.java @@ -0,0 +1,103 @@ +package kaptainwutax.seedcracker.finder.structure; + +import kaptainwutax.seedcracker.SeedCracker; +import kaptainwutax.seedcracker.cracker.StructureData; +import kaptainwutax.seedcracker.finder.Finder; +import kaptainwutax.seedcracker.render.Cube; +import kaptainwutax.seedcracker.render.Cuboid; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.client.util.math.Vector4f; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Vec3i; +import net.minecraft.world.World; +import net.minecraft.world.dimension.DimensionType; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +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; + }); + + protected List finders = new ArrayList<>(); + protected Vec3i size = new Vec3i(16, 8, 16); + + public MansionFinder(World world, ChunkPos chunkPos) { + super(world, chunkPos); + + 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() { + 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, 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))); + } + }); + }); + + return combinedResult; + } + + public Map> findInChunkPieces() { + Map> result = new HashMap<>(); + + this.finders.forEach(pieceFinder -> { + result.put(pieceFinder, pieceFinder.findInChunk()); + }); + + return result; + } + + public void buildStructure(PieceFinder finder) { + BlockState cobblestone = Blocks.COBBLESTONE.getDefaultState(); + BlockState birchPlanks = Blocks.BIRCH_PLANKS.getDefaultState(); + BlockState redCarpet = Blocks.RED_CARPET.getDefaultState(); + BlockState whiteCarpet = Blocks.WHITE_CARPET.getDefaultState(); + + //TODO: Finish this. + } + + @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 MansionFinder(world, chunkPos)); + return finders; + } + +} + diff --git a/src/main/java/kaptainwutax/seedcracker/finder/OceanMonumentFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/structure/OceanMonumentFinder.java similarity index 97% rename from src/main/java/kaptainwutax/seedcracker/finder/OceanMonumentFinder.java rename to src/main/java/kaptainwutax/seedcracker/finder/structure/OceanMonumentFinder.java index 6c4f186..f4f3cb0 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/OceanMonumentFinder.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/structure/OceanMonumentFinder.java @@ -1,7 +1,8 @@ -package kaptainwutax.seedcracker.finder; +package kaptainwutax.seedcracker.finder.structure; import kaptainwutax.seedcracker.SeedCracker; import kaptainwutax.seedcracker.cracker.StructureData; +import kaptainwutax.seedcracker.finder.Finder; import kaptainwutax.seedcracker.render.Cube; import kaptainwutax.seedcracker.render.Cuboid; import net.minecraft.block.BlockState; diff --git a/src/main/java/kaptainwutax/seedcracker/finder/PieceFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/structure/PieceFinder.java similarity index 87% rename from src/main/java/kaptainwutax/seedcracker/finder/PieceFinder.java rename to src/main/java/kaptainwutax/seedcracker/finder/structure/PieceFinder.java index 4335fc6..02a57af 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/PieceFinder.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/structure/PieceFinder.java @@ -1,22 +1,23 @@ -package kaptainwutax.seedcracker.finder; +package kaptainwutax.seedcracker.finder.structure; +import kaptainwutax.seedcracker.finder.Finder; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; +import net.minecraft.client.MinecraftClient; import net.minecraft.util.BlockMirror; import net.minecraft.util.BlockRotation; import net.minecraft.util.math.*; import net.minecraft.world.World; -import net.minecraft.world.chunk.Chunk; import net.minecraft.world.dimension.DimensionType; import java.util.ArrayList; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; public class PieceFinder extends Finder { - protected Map structure = new HashMap<>(); + protected Map structure = new LinkedHashMap<>(); private MutableIntBoundingBox boundingBox; protected List searchPositions = new ArrayList<>(); @@ -28,6 +29,8 @@ public class PieceFinder extends Finder { protected int height; protected int depth; + private boolean debug; + public PieceFinder(World world, ChunkPos chunkPos, Direction facing, Vec3i size) { super(world, chunkPos); @@ -61,19 +64,22 @@ public class PieceFinder extends Finder { public List findInChunk() { List result = new ArrayList<>(); - Chunk chunk = this.world.getChunk(this.chunkPos.getCenterBlockPos()); + if(this.structure.isEmpty()) { + return result; + } + //FOR DEBUGGING PIECES. + if(this.debug) { + MinecraftClient.getInstance().execute(() -> { + int y = this.rotation.ordinal() * 10 + this.mirror.ordinal() * 20 + 100; - /*//FOR DEBUGGING PIECES. - MinecraftClient.getInstance().execute(() -> { - int y = this.rotation.ordinal() * 10 + this.mirror.ordinal() * 20 + 80; - - if(this.chunkPos.x % 2 == 0 && this.chunkPos.z % 2 == 0) { - this.structure.forEach((pos, state) -> { - this.world.setBlockState(this.chunkPos.getCenterBlockPos().add(pos).add(0, y, 0), state); - }); - } - });*/ + if (this.chunkPos.x % 2 == 0 && this.chunkPos.z % 2 == 0) { + this.structure.forEach((pos, state) -> { + this.world.setBlockState(this.chunkPos.getCenterBlockPos().add(pos).add(0, y, 0), state, 0); + }); + } + }); + } for(BlockPos center: this.searchPositions) { boolean found = true; @@ -221,4 +227,9 @@ public class PieceFinder extends Finder { public boolean isValidDimension(DimensionType dimension) { return true; } + + public void setDebug() { + this.debug = true; + } + } diff --git a/src/main/java/kaptainwutax/seedcracker/finder/SwampHutFinder.java b/src/main/java/kaptainwutax/seedcracker/finder/structure/SwampHutFinder.java similarity index 94% rename from src/main/java/kaptainwutax/seedcracker/finder/SwampHutFinder.java rename to src/main/java/kaptainwutax/seedcracker/finder/structure/SwampHutFinder.java index ce8c3c0..2f03449 100644 --- a/src/main/java/kaptainwutax/seedcracker/finder/SwampHutFinder.java +++ b/src/main/java/kaptainwutax/seedcracker/finder/structure/SwampHutFinder.java @@ -1,7 +1,8 @@ -package kaptainwutax.seedcracker.finder; +package kaptainwutax.seedcracker.finder.structure; import kaptainwutax.seedcracker.SeedCracker; import kaptainwutax.seedcracker.cracker.StructureData; +import kaptainwutax.seedcracker.finder.Finder; import kaptainwutax.seedcracker.render.Cuboid; import net.minecraft.block.BlockState; import net.minecraft.block.Blocks; @@ -13,8 +14,8 @@ 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.gen.feature.Feature; +import net.minecraft.world.gen.feature.StructureFeature; import java.util.ArrayList; import java.util.List; @@ -32,13 +33,6 @@ public class SwampHutFinder extends AbstractTempleFinder { List combinedResult = new ArrayList<>(); result.forEach((pieceFinder, positions) -> { - positions.removeIf(pos -> { - Biome biome = world.getBiome(pos.add(9, 0, 9)); - if(!biome.hasStructureFeature(Feature.SWAMP_HUT))return true; - - return false; - }); - combinedResult.addAll(positions); positions.forEach(pos -> { @@ -51,6 +45,11 @@ public class SwampHutFinder extends AbstractTempleFinder { return combinedResult; } + @Override + protected StructureFeature getStructureFeature() { + return Feature.SWAMP_HUT; + } + @Override public void buildStructure(PieceFinder finder) { finder.fillWithOutline(1, 1, 1, 5, 1, 7, Blocks.SPRUCE_PLANKS.getDefaultState(), Blocks.SPRUCE_PLANKS.getDefaultState(), false); diff --git a/src/main/java/kaptainwutax/seedcracker/mixin/ClientPlayNetworkHandlerMixin.java b/src/main/java/kaptainwutax/seedcracker/mixin/ClientPlayNetworkHandlerMixin.java index b774fb7..fc75998 100644 --- a/src/main/java/kaptainwutax/seedcracker/mixin/ClientPlayNetworkHandlerMixin.java +++ b/src/main/java/kaptainwutax/seedcracker/mixin/ClientPlayNetworkHandlerMixin.java @@ -2,8 +2,8 @@ package kaptainwutax.seedcracker.mixin; import com.mojang.authlib.GameProfile; import com.mojang.brigadier.CommandDispatcher; -import kaptainwutax.seedcracker.ClientCommands; -import kaptainwutax.seedcracker.FinderQueue; +import kaptainwutax.seedcracker.command.ClientCommands; +import kaptainwutax.seedcracker.finder.FinderQueue; import net.minecraft.client.MinecraftClient; import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.network.ClientPlayNetworkHandler; diff --git a/src/main/java/kaptainwutax/seedcracker/mixin/ClientPlayerEntityMixin.java b/src/main/java/kaptainwutax/seedcracker/mixin/ClientPlayerEntityMixin.java index ca2edd9..51f44ca 100644 --- a/src/main/java/kaptainwutax/seedcracker/mixin/ClientPlayerEntityMixin.java +++ b/src/main/java/kaptainwutax/seedcracker/mixin/ClientPlayerEntityMixin.java @@ -1,13 +1,15 @@ package kaptainwutax.seedcracker.mixin; import com.mojang.brigadier.StringReader; -import kaptainwutax.seedcracker.ClientCommands; +import kaptainwutax.seedcracker.command.ClientCommands; import net.minecraft.client.network.ClientPlayerEntity; 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 java.util.regex.Pattern; + @Mixin(ClientPlayerEntity.class) public class ClientPlayerEntityMixin { @@ -17,10 +19,8 @@ public class ClientPlayerEntityMixin { StringReader reader = new StringReader(message); reader.skip(); - int cursor = reader.getCursor(); - reader.setCursor(cursor); - if(ClientCommands.isClientSideCommand(message.substring(1).split(" "))) { + if(ClientCommands.isClientSideCommand(message.substring(1).split(Pattern.quote(" ")))) { ClientCommands.executeCommand(reader); ci.cancel(); } diff --git a/src/main/java/kaptainwutax/seedcracker/mixin/ClientWorldMixin.java b/src/main/java/kaptainwutax/seedcracker/mixin/ClientWorldMixin.java index da45518..60e4157 100644 --- a/src/main/java/kaptainwutax/seedcracker/mixin/ClientWorldMixin.java +++ b/src/main/java/kaptainwutax/seedcracker/mixin/ClientWorldMixin.java @@ -1,6 +1,6 @@ package kaptainwutax.seedcracker.mixin; -import kaptainwutax.seedcracker.FinderQueue; +import kaptainwutax.seedcracker.finder.FinderQueue; import kaptainwutax.seedcracker.SeedCracker; import net.minecraft.client.world.ClientWorld; import org.spongepowered.asm.mixin.Mixin; @@ -8,6 +8,8 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import java.util.concurrent.Executors; + @Mixin(ClientWorld.class) public abstract class ClientWorldMixin { @@ -15,6 +17,8 @@ public abstract class ClientWorldMixin { private void disconnect(CallbackInfo ci) { SeedCracker.get().clear(); FinderQueue.get().clear(); + FinderQueue.SERVICE.shutdown(); + FinderQueue.SERVICE = Executors.newFixedThreadPool(5); } }