Chunk generator asyncronously generates block values.
Also added parallel capable override.
This commit is contained in:
		| @@ -4,7 +4,6 @@ import java.util.LinkedList; | |||||||
| import java.util.Random; | import java.util.Random; | ||||||
| import java.util.concurrent.ExecutionException; | import java.util.concurrent.ExecutionException; | ||||||
| import java.util.concurrent.ExecutorService; | import java.util.concurrent.ExecutorService; | ||||||
| import java.util.concurrent.Executors; |  | ||||||
| import java.util.concurrent.Future; | import java.util.concurrent.Future; | ||||||
|  |  | ||||||
| import org.bukkit.Chunk; | import org.bukkit.Chunk; | ||||||
| @@ -28,60 +27,83 @@ public class IslandWorldChunkGenerator extends ChunkGenerator implements Listene | |||||||
|     private final Cache<Point2, Double> blockValueCache = new Cache<>(102400); |     private final Cache<Point2, Double> blockValueCache = new Cache<>(102400); | ||||||
|     private final Cache<Point2, Biome[]> biomeCache = new Cache<>(102400); |     private final Cache<Point2, Biome[]> biomeCache = new Cache<>(102400); | ||||||
|     private final Cache<Point2, Boolean> chunkExistenceCache = new Cache<>(16384); |     private final Cache<Point2, Boolean> chunkExistenceCache = new Cache<>(16384); | ||||||
|  |     private final BiomeSelector biomeSelector = new BiomeSelector(); | ||||||
|     private final ExecutorService executor = Utilities.ISC_EXECUTOR; |     private final ExecutorService executor = Utilities.ISC_EXECUTOR; | ||||||
|     private volatile World currentWorld; |     private volatile World currentWorld; | ||||||
|  |  | ||||||
|  |     public IslandWorldChunkGenerator() { | ||||||
|  |         biomeSelector.initialize(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public ChunkData generateChunkData(World world, Random random, int chunkX, int chunkZ, BiomeGrid biomeGrid) { |     public ChunkData generateChunkData(World world, Random random, int chunkX, int chunkZ, BiomeGrid biomeGrid) { | ||||||
|         this.currentWorld = world; |         this.currentWorld = world; | ||||||
|         IslandWorldMapper mapper = new IslandWorldMapper(random, blockValueCache); |         IslandWorldMapper mapper = new IslandWorldMapper(random, blockValueCache); | ||||||
|         TemperatureMapGenerator temperatureMapGenerator = new TemperatureMapGenerator(world.getSeed()); |         TemperatureMapGenerator temperatureMapGenerator = new TemperatureMapGenerator(world.getSeed()); | ||||||
|         BiomeSelector biomeSelector = new BiomeSelector(random); |         WorldHeightShader heightShader = new WorldHeightShader(world.getSeed(), mapper, world.getSeaLevel(), world.getMaxHeight(), 3); | ||||||
|         biomeSelector.initialize(); |  | ||||||
|         WorldHeightShader heightShader = new WorldHeightShader(world.getSeed(), mapper, world.getSeaLevel(), |  | ||||||
|                 world.getMaxHeight(), 3); |  | ||||||
|         BiomeGenerator biomeGenerator = new UniBiomeIslandGenerator(); |         BiomeGenerator biomeGenerator = new UniBiomeIslandGenerator(); | ||||||
|  |  | ||||||
|         int maxHeight = world.getMaxHeight(); |         int maxHeight = world.getMaxHeight(); | ||||||
|         LinkedList<Future<Boolean>> tasks = new LinkedList<>(); |         LinkedList<Future<Boolean>> tasks = new LinkedList<>(); | ||||||
|         ChunkData chunkData = createChunkData(world); |         ChunkData chunkData = createChunkData(world); | ||||||
|  |         Future<Boolean> 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]; |         Biome[][] biomes = new Biome[Utilities.CHUNK_SIZE][Utilities.CHUNK_SIZE]; | ||||||
|         for (int localX = 0; localX < Utilities.CHUNK_SIZE; localX++) { |         for (int x = 0; x < Utilities.CHUNK_SIZE; x++) { | ||||||
|             for (int localZ = 0; localZ < Utilities.CHUNK_SIZE; localZ++) { |             for (int z = 0; z < Utilities.CHUNK_SIZE; z++) { | ||||||
|                 if (biomes[localX][localZ] == null) { |                 final int desX = x; | ||||||
|                     biomeGenerator.generateBiomeColumn(biomes, world, chunkX, chunkZ, localX, localZ, mapper, biomeSelector, |                 final int desZ = z; | ||||||
|  |                 if (biomes[desX][desZ] == null) { | ||||||
|  |                     biomeGenerator.generateBiomeColumn(biomes, world, chunkX, chunkZ, desX, desZ, mapper, biomeSelector, | ||||||
|                             temperatureMapGenerator, biomeCache, chunkExistenceCache); |                             temperatureMapGenerator, biomeCache, chunkExistenceCache); | ||||||
|                 } |                 } | ||||||
|                 if (biomes[localX][localZ] == null) throw new IllegalStateException("Biome was null."); |                  | ||||||
|  |                 if (biomes[desX][desZ] == null) throw new IllegalStateException("Biome was null."); | ||||||
|                 final int biomeX = localX; |  | ||||||
|                 final int biomeZ = localZ; |  | ||||||
|                 tasks.add(executor.submit(() -> { |                 tasks.add(executor.submit(() -> { | ||||||
|                     for (int y = 0; y < maxHeight; y++) { |                     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; |                     return true; | ||||||
|                 })); |                 })); | ||||||
|  |  | ||||||
|                 final int worldX = 16 * chunkX + localX; |                 final int worldX = Utilities.CHUNK_SIZE * chunkX + desX; | ||||||
|                 final int worldZ = 16 * chunkZ + localZ; |                 final int worldZ = Utilities.CHUNK_SIZE * chunkZ + desZ; | ||||||
|                 int height = heightShader.getAltitude(worldX, worldZ, biomes[localX][localZ]); |                 int height = heightShader.getAltitude(worldX, worldZ, biomes[desX][desZ]); | ||||||
|                 chunkData.setRegion(localX, 1, localZ, localX + 1, height, localZ + 1, Material.DIAMOND_BLOCK); |                 chunkData.setRegion(desX, 1, desZ, desX + 1, height, desZ + 1, Material.DIAMOND_BLOCK); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         chunkData.setRegion(0, 0, 0, 16, 1, 16, Material.BEDROCK); |         chunkData.setRegion(0, 0, 0, 16, 1, 16, Material.BEDROCK); | ||||||
|         while (!tasks.isEmpty()) { |  | ||||||
|             try { |         preLoader.cancel(true); | ||||||
|  |         try { | ||||||
|  |             while (!tasks.isEmpty()) { | ||||||
|                 tasks.poll().get(); |                 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; |         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) |     @EventHandler(priority = EventPriority.MONITOR) | ||||||
|     public void onChunkLoaded(ChunkLoadEvent event) { |     public void onChunkLoaded(ChunkLoadEvent event) { | ||||||
|         if (event.isNewChunk()) { |         if (event.isNewChunk()) { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user