Chunk generator asyncronously generates block values.
Also added parallel capable override.
This commit is contained in:
parent
538b1c3cae
commit
c963ad140f
@ -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()) {
|
||||||
|
Loading…
Reference in New Issue
Block a user