diff --git a/src/main/java/kaptainwutax/seedcracker/SeedCracker.java b/src/main/java/kaptainwutax/seedcracker/SeedCracker.java index e2f9783..d4eb8c9 100644 --- a/src/main/java/kaptainwutax/seedcracker/SeedCracker.java +++ b/src/main/java/kaptainwutax/seedcracker/SeedCracker.java @@ -1,5 +1,6 @@ package kaptainwutax.seedcracker; +import io.netty.util.internal.ConcurrentSet; import kaptainwutax.seedcracker.cracker.*; import kaptainwutax.seedcracker.cracker.population.PopulationData; import kaptainwutax.seedcracker.finder.FinderQueue; @@ -18,6 +19,7 @@ import org.apache.logging.log4j.Logger; import java.util.ArrayList; import java.util.List; +import java.util.Set; public class SeedCracker implements ModInitializer { @@ -27,7 +29,7 @@ public class SeedCracker implements ModInitializer { public static final OverworldChunkGeneratorConfig CHUNK_GEN_CONFIG = new OverworldChunkGeneratorConfig(); public List worldSeeds = null; - public List structureSeeds = null; + public Set structureSeeds = null; public List pillarSeeds = null; private TimeMachine timeMachine = new TimeMachine(); @@ -130,7 +132,7 @@ public class SeedCracker implements ModInitializer { } if(this.structureSeeds == null && this.pillarSeeds != null && this.structureCache.size() + this.populationCache.size() >= 5) { - this.structureSeeds = new ArrayList<>(); + this.structureSeeds = new ConcurrentSet<>(); LOG.warn("Looking for structure seeds with " + this.structureCache.size() + " structure features."); LOG.warn("Looking for structure seeds with " + this.populationCache.size() + " population features."); @@ -186,11 +188,7 @@ public class SeedCracker implements ModInitializer { this.worldSeeds = new ArrayList<>(); LOG.warn("Looking for world seeds with " + this.biomeCache.size() + " biomes."); - 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); - + this.structureSeeds.forEach(structureSeed -> { for (long j = 0; j < (1L << 16); j++) { long worldSeed = (j << 48) | structureSeed; boolean goodSeed = true; @@ -208,7 +206,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.")); diff --git a/src/main/java/kaptainwutax/seedcracker/cracker/TimeMachine.java b/src/main/java/kaptainwutax/seedcracker/cracker/TimeMachine.java index cf3c608..8d8ccce 100644 --- a/src/main/java/kaptainwutax/seedcracker/cracker/TimeMachine.java +++ b/src/main/java/kaptainwutax/seedcracker/cracker/TimeMachine.java @@ -6,24 +6,33 @@ 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 { - + + public int THREAD_COUNT = 8; + public ExecutorService SERVICE = Executors.newFixedThreadPool(THREAD_COUNT); + private LCG inverseLCG = Rand.JAVA_LCG.combine(-2); + private boolean isRunning = false; public TimeMachine() { } - public List buildStructureSeeds(int pillarSeed, List structureDataList, List populationDataList, List structureSeeds) { + public List bruteforceRegion(int pillarSeed, int region, long size, List structureDataList, List populationDataList) { + List result = new ArrayList<>(); ChunkRandom chunkRandom = new ChunkRandom(); - for(long i = 0; i < (1L << 32); i++) { - if((i & ((1L << 28) - 1)) == 0) { - SeedCracker.LOG.warn("Progress " + (i * 100.0f) / (1L << 32) + "%..."); - } + long start = region * size; + long end = start + size; + for(long i = start; i < end; i++) { long structureSeed = this.timeMachine(i, pillarSeed); boolean goodSeed = true; @@ -40,10 +49,39 @@ public class TimeMachine { } if(goodSeed) { - structureSeeds.add(structureSeed); + result.add(structureSeed); } } + return result; + } + + public Set buildStructureSeeds(int pillarSeed, List structureDataList, List populationDataList, 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, populationDataList)); + SeedCracker.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; } @@ -58,4 +96,8 @@ public class TimeMachine { return currentSeed; } + public void stop() { + this.isRunning = false; + } + } diff --git a/src/main/java/kaptainwutax/seedcracker/mixin/ClientWorldMixin.java b/src/main/java/kaptainwutax/seedcracker/mixin/ClientWorldMixin.java index 60e4157..a9e5eea 100644 --- a/src/main/java/kaptainwutax/seedcracker/mixin/ClientWorldMixin.java +++ b/src/main/java/kaptainwutax/seedcracker/mixin/ClientWorldMixin.java @@ -1,15 +1,13 @@ package kaptainwutax.seedcracker.mixin; -import kaptainwutax.seedcracker.finder.FinderQueue; import kaptainwutax.seedcracker.SeedCracker; +import kaptainwutax.seedcracker.finder.FinderQueue; import net.minecraft.client.world.ClientWorld; 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.concurrent.Executors; - @Mixin(ClientWorld.class) public abstract class ClientWorldMixin { @@ -17,8 +15,6 @@ public abstract class ClientWorldMixin { private void disconnect(CallbackInfo ci) { SeedCracker.get().clear(); FinderQueue.get().clear(); - FinderQueue.SERVICE.shutdown(); - FinderQueue.SERVICE = Executors.newFixedThreadPool(5); } }