From c6fd9a833c54dff55c09e47d3b2be126b560f8b6 Mon Sep 17 00:00:00 2001 From: Harrison Date: Wed, 29 Apr 2020 19:14:20 -0500 Subject: [PATCH] Revert to "Island world chunk generator now pre-generates island values." This reverts commit e40bf74cb83707e1fa72ba231cb26a2f9450d8d5. --- .../islandsurvivalcraft/caching/Cache.java | 28 +++++--- .../generation/IslandWorldChunkGenerator.java | 68 +++++++------------ 2 files changed, 42 insertions(+), 54 deletions(-) diff --git a/src/main/java/ca/recrown/islandsurvivalcraft/caching/Cache.java b/src/main/java/ca/recrown/islandsurvivalcraft/caching/Cache.java index 3cb3964..cb48cf6 100644 --- a/src/main/java/ca/recrown/islandsurvivalcraft/caching/Cache.java +++ b/src/main/java/ca/recrown/islandsurvivalcraft/caching/Cache.java @@ -1,13 +1,17 @@ package ca.recrown.islandsurvivalcraft.caching; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.locks.ReentrantLock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock; +import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock; public class Cache { private final int maxSize; private final ConcurrentHashMap> data; private final UsageStack usage = new UsageStack<>(); - private final ReentrantLock lock = new ReentrantLock(); + private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); + private final WriteLock writeLock = lock.writeLock(); + private final ReadLock readLock = lock.readLock(); public Cache(int maxSize) { data = new ConcurrentHashMap<>(maxSize + 1, 0.75f, 6); @@ -29,7 +33,7 @@ public class Cache { if (data.containsKey(key)) { data.get(key).value = value; } else { - lock.lock(); + writeLock.lock(); try { CacheValue val = new CacheValue<>(); val.key = key; @@ -40,7 +44,7 @@ public class Cache { data.remove(usage.pop().key); } } finally { - lock.unlock(); + writeLock.unlock(); } } } @@ -53,9 +57,15 @@ public class Cache { * @return the value associated to the key. */ public V get(K key) { - CacheValue value = data.get(key); - if (value == null) return null; - usage.tryMoveToTop(value); + readLock.lock(); + CacheValue value = null; + try { + if (!data.containsKey(key)) return null; + value = data.get(key); + usage.tryMoveToTop(value); + } finally { + readLock.unlock(); + } return value.value; } @@ -63,12 +73,12 @@ public class Cache { * Clears the cache of all values. */ public void clearCache() { - lock.lock(); + writeLock.lock(); try { data.clear(); usage.clear(); } finally { - lock.unlock(); + writeLock.unlock(); } } } \ No newline at end of file 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 c4392a8..9fed7f1 100644 --- a/src/main/java/ca/recrown/islandsurvivalcraft/world/generation/IslandWorldChunkGenerator.java +++ b/src/main/java/ca/recrown/islandsurvivalcraft/world/generation/IslandWorldChunkGenerator.java @@ -4,6 +4,7 @@ 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; @@ -27,83 +28,60 @@ 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()); - WorldHeightShader heightShader = new WorldHeightShader(world.getSeed(), mapper, world.getSeaLevel(), world.getMaxHeight(), 3); + BiomeSelector biomeSelector = new BiomeSelector(random); + biomeSelector.initialize(); + 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 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, + 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, temperatureMapGenerator, biomeCache, chunkExistenceCache); } - - if (biomes[desX][desZ] == null) throw new IllegalStateException("Biome was null."); + if (biomes[localX][localZ] == null) throw new IllegalStateException("Biome was null."); + + final int biomeX = localX; + final int biomeZ = localZ; tasks.add(executor.submit(() -> { for (int y = 0; y < maxHeight; y++) { - biomeGrid.setBiome(desX, y, desZ, biomes[desX][desZ]); + biomeGrid.setBiome(biomeX, y, biomeZ, biomes[biomeX][biomeZ]); } return true; })); - 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); + 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); } } chunkData.setRegion(0, 0, 0, 16, 1, 16, Material.BEDROCK); - - preLoader.cancel(true); - try { - while (!tasks.isEmpty()) { + while (!tasks.isEmpty()) { + try { 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()) {