diff --git a/src/main/java/ca/recrown/islandsurvivalcraft/world/generation/IslandWorldChunkGenerator.java b/src/main/java/ca/recrown/islandsurvivalcraft/world/generation/IslandWorldChunkGenerator.java index 9fed7f1..c4392a8 100644 --- a/src/main/java/ca/recrown/islandsurvivalcraft/world/generation/IslandWorldChunkGenerator.java +++ b/src/main/java/ca/recrown/islandsurvivalcraft/world/generation/IslandWorldChunkGenerator.java @@ -4,7 +4,6 @@ import java.util.LinkedList; import java.util.Random; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import java.util.concurrent.Future; import org.bukkit.Chunk; @@ -28,60 +27,83 @@ public class IslandWorldChunkGenerator extends ChunkGenerator implements Listene private final Cache blockValueCache = new Cache<>(102400); private final Cache biomeCache = new Cache<>(102400); private final Cache chunkExistenceCache = new Cache<>(16384); + private final BiomeSelector biomeSelector = new BiomeSelector(); private final ExecutorService executor = Utilities.ISC_EXECUTOR; private volatile World currentWorld; + public IslandWorldChunkGenerator() { + biomeSelector.initialize(); + } + @Override public ChunkData generateChunkData(World world, Random random, int chunkX, int chunkZ, BiomeGrid biomeGrid) { this.currentWorld = world; IslandWorldMapper mapper = new IslandWorldMapper(random, blockValueCache); TemperatureMapGenerator temperatureMapGenerator = new TemperatureMapGenerator(world.getSeed()); - BiomeSelector biomeSelector = new BiomeSelector(random); - biomeSelector.initialize(); - WorldHeightShader heightShader = new WorldHeightShader(world.getSeed(), mapper, world.getSeaLevel(), - world.getMaxHeight(), 3); + WorldHeightShader heightShader = new WorldHeightShader(world.getSeed(), mapper, world.getSeaLevel(), world.getMaxHeight(), 3); BiomeGenerator biomeGenerator = new UniBiomeIslandGenerator(); int maxHeight = world.getMaxHeight(); LinkedList> tasks = new LinkedList<>(); ChunkData chunkData = createChunkData(world); + Future preLoader = executor.submit(() -> { + for (int x = 0; x < Utilities.CHUNK_SIZE; x++) { + for (int z = 0; z < Utilities.CHUNK_SIZE; z++) { + if (Thread.currentThread().isInterrupted()) return false; + mapper.getWorldBlockValue(Utilities.CHUNK_SIZE * chunkX + x, Utilities.CHUNK_SIZE * chunkZ + z); + } + } + return true; + }); Biome[][] biomes = new Biome[Utilities.CHUNK_SIZE][Utilities.CHUNK_SIZE]; - for (int localX = 0; localX < Utilities.CHUNK_SIZE; localX++) { - for (int localZ = 0; localZ < Utilities.CHUNK_SIZE; localZ++) { - if (biomes[localX][localZ] == null) { - biomeGenerator.generateBiomeColumn(biomes, world, chunkX, chunkZ, localX, localZ, mapper, biomeSelector, + for (int x = 0; x < Utilities.CHUNK_SIZE; x++) { + for (int z = 0; z < Utilities.CHUNK_SIZE; z++) { + final int desX = x; + final int desZ = z; + if (biomes[desX][desZ] == null) { + biomeGenerator.generateBiomeColumn(biomes, world, chunkX, chunkZ, desX, desZ, mapper, biomeSelector, temperatureMapGenerator, biomeCache, chunkExistenceCache); } - if (biomes[localX][localZ] == null) throw new IllegalStateException("Biome was null."); - - final int biomeX = localX; - final int biomeZ = localZ; + + if (biomes[desX][desZ] == null) throw new IllegalStateException("Biome was null."); tasks.add(executor.submit(() -> { for (int y = 0; y < maxHeight; y++) { - biomeGrid.setBiome(biomeX, y, biomeZ, biomes[biomeX][biomeZ]); + biomeGrid.setBiome(desX, y, desZ, biomes[desX][desZ]); } return true; })); - final int worldX = 16 * chunkX + localX; - final int worldZ = 16 * chunkZ + localZ; - int height = heightShader.getAltitude(worldX, worldZ, biomes[localX][localZ]); - chunkData.setRegion(localX, 1, localZ, localX + 1, height, localZ + 1, Material.DIAMOND_BLOCK); + final int worldX = Utilities.CHUNK_SIZE * chunkX + desX; + final int worldZ = Utilities.CHUNK_SIZE * chunkZ + desZ; + int height = heightShader.getAltitude(worldX, worldZ, biomes[desX][desZ]); + chunkData.setRegion(desX, 1, desZ, desX + 1, height, desZ + 1, Material.DIAMOND_BLOCK); } } chunkData.setRegion(0, 0, 0, 16, 1, 16, Material.BEDROCK); - while (!tasks.isEmpty()) { - try { + + preLoader.cancel(true); + try { + while (!tasks.isEmpty()) { tasks.poll().get(); - } catch (ExecutionException | InterruptedException e) { - e.printStackTrace(); - throw new IllegalStateException(e.getCause().getMessage()); } + } catch (ExecutionException | InterruptedException e) { + e.printStackTrace(); + throw new IllegalStateException(e.getCause().getMessage()); } return chunkData; } + @Override + public boolean canSpawn(World world, int x, int z) { + return super.canSpawn(world, x, z); + } + + @Override + public boolean isParallelCapable() { + return true; + } + @EventHandler(priority = EventPriority.MONITOR) public void onChunkLoaded(ChunkLoadEvent event) { if (event.isNewChunk()) {