diff --git a/src/main/java/ca/recrown/islandsurvivalcraft/world/WorldInfo.java b/src/main/java/ca/recrown/islandsurvivalcraft/world/WorldInfo.java index d1b628c..8316be0 100644 --- a/src/main/java/ca/recrown/islandsurvivalcraft/world/WorldInfo.java +++ b/src/main/java/ca/recrown/islandsurvivalcraft/world/WorldInfo.java @@ -7,20 +7,55 @@ import org.bukkit.World; import ca.recrown.islandsurvivalcraft.world.generation.IslandWorldChunkGenerator; public class WorldInfo { - public final long seed; - public final BiomeMap biomeMap; - public final TemperatureMap tempMap; - public final IslandWorldMap islandMap; - public final IslandWorldChunkGenerator generator; + private final WorldInfoManager manager; + private volatile boolean initialized; + public volatile long seed; + public volatile BiomeMap biomeMap; + public volatile TemperatureMap tempMap; + public volatile IslandWorldMap islandMap; + public volatile IslandWorldChunkGenerator generator; - public WorldInfo(World world) { + /** + * Will initialize with the known information extracted from the given world if world is not null. + * If the world is null, this world info will not be initialized and awaits initialization from the generator. + * @param world The world this object is describing. May be null to create a non-initialized info object. + */ + public WorldInfo(WorldInfoManager manager, World world) { + this.manager = manager; + if (world != null) { + initialize(world); + } + } + + public void initialize(World world, IslandWorldChunkGenerator chunkGenerator) { + if (initialized) throw new IllegalStateException("This world information object has already been initialized."); + initialized = true; this.seed = world.getSeed(); Random random = new Random(seed); biomeMap = new BiomeMap(random); tempMap = new TemperatureMap(random); islandMap = new IslandWorldMap(random); - generator = new IslandWorldChunkGenerator(random, islandMap, tempMap, biomeMap, true, world.getSeaLevel(), world.getMaxHeight()); + generator = chunkGenerator; + generator.initialize(random, true, world.getSeaLevel(), world.getMaxHeight()); + manager.register(world, this); } + private void initialize(World world) { + if (initialized) throw new IllegalStateException("This world information object has already been initialized."); + initialized = true; + this.seed = world.getSeed(); + Random random = new Random(seed); + biomeMap = new BiomeMap(random); + tempMap = new TemperatureMap(random); + islandMap = new IslandWorldMap(random); + generator = new IslandWorldChunkGenerator(this); + generator.initialize(random, true, world.getSeaLevel(), world.getMaxHeight()); + } + /** + * @return whether or not this world info is initialized. + */ + public boolean isInitialized() { + return initialized; + } } \ No newline at end of file diff --git a/src/main/java/ca/recrown/islandsurvivalcraft/world/WorldInfoManager.java b/src/main/java/ca/recrown/islandsurvivalcraft/world/WorldInfoManager.java index afbc732..c7b19b6 100644 --- a/src/main/java/ca/recrown/islandsurvivalcraft/world/WorldInfoManager.java +++ b/src/main/java/ca/recrown/islandsurvivalcraft/world/WorldInfoManager.java @@ -12,11 +12,10 @@ import org.bukkit.event.Listener; import org.bukkit.event.world.ChunkLoadEvent; import org.bukkit.generator.ChunkGenerator; -import ca.recrown.islandsurvivalcraft.world.generation.PluginDefaultWorldGenerator; +import ca.recrown.islandsurvivalcraft.world.generation.IslandWorldChunkGenerator; public class WorldInfoManager implements Listener { public final ConcurrentHashMap worldInformation = new ConcurrentHashMap<>(); - private final PluginDefaultWorldGenerator worldGenerator = new PluginDefaultWorldGenerator(this); /** * Return the world info requested for the given world. @@ -27,7 +26,7 @@ public class WorldInfoManager implements Listener { public WorldInfo retrieve(World world) { if (world == null) throw new NullArgumentException("world"); return worldInformation.computeIfAbsent(world.getUID(), (worldInfo) -> { - return new WorldInfo(world); + return new WorldInfo(this, world); }); } @@ -44,7 +43,11 @@ public class WorldInfoManager implements Listener { * @return The chunk generator associated with the given world. */ public ChunkGenerator getChunkGenerator(World world) { - if (world == null) return worldGenerator; + if (world == null) { + WorldInfo worldInfo = new WorldInfo(this, world); + IslandWorldChunkGenerator islandWorldChunkGenerator = new IslandWorldChunkGenerator(worldInfo); + return islandWorldChunkGenerator; + } return retrieve(world).generator; } @@ -55,4 +58,8 @@ public class WorldInfoManager implements Listener { retrieve(event.getWorld()).generator.updateChunkLoadedCache(chunk.getX(), chunk.getZ()); } } + + protected void register(World world, WorldInfo worldInfo) { + worldInformation.put(world.getUID(), worldInfo); + } } \ 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 e263147..0e3bafe 100644 --- a/src/main/java/ca/recrown/islandsurvivalcraft/world/generation/IslandWorldChunkGenerator.java +++ b/src/main/java/ca/recrown/islandsurvivalcraft/world/generation/IslandWorldChunkGenerator.java @@ -21,28 +21,33 @@ import ca.recrown.islandsurvivalcraft.datatypes.Point2; import ca.recrown.islandsurvivalcraft.world.BiomeMap; import ca.recrown.islandsurvivalcraft.world.IslandWorldMap; import ca.recrown.islandsurvivalcraft.world.TemperatureMap; +import ca.recrown.islandsurvivalcraft.world.WorldInfo; import ca.recrown.islandsurvivalcraft.world.generation.biomes.BiomeGenerator; import ca.recrown.islandsurvivalcraft.world.generation.biomes.UniqueBiomeGenerator; import ca.recrown.islandsurvivalcraft.world.generation.shaders.WorldHeightShader; import ca.recrown.islandsurvivalcraft.world.generation.shaders.WorldLayerShader; public class IslandWorldChunkGenerator extends ChunkGenerator implements Listener { + private volatile boolean initialized = false; + private volatile WorldInfo worldInfo; private final int BEDROCK_HEIGHT = 5; - private final IslandWorldMap islandMap; - private final TemperatureMap temperatureMap; - private final BiomeMap biomeMap; - private final BiomeGenerator biomeGenerator; - private final WorldHeightShader heightShader; - private final WorldLayerShader layerShader; - private final Cache biomeCache = new Cache<>(131072); - private final Cache chunkLoadedCache = new Cache<>(4096); - private final ExecutorService exAlpha = Utilities.ISC_EXECUTOR_ALPHA; - private final ExecutorService exBeta = Utilities.ISC_EXECUTOR_BETA; + private volatile IslandWorldMap islandMap; + private volatile TemperatureMap temperatureMap; + private volatile BiomeMap biomeMap; + private volatile BiomeGenerator biomeGenerator; + private volatile WorldHeightShader heightShader; + private volatile WorldLayerShader layerShader; + private volatile Cache biomeCache = new Cache<>(131072); + private volatile Cache chunkLoadedCache = new Cache<>(4096); + private volatile ExecutorService exAlpha = Utilities.ISC_EXECUTOR_ALPHA; + private volatile ExecutorService exBeta = Utilities.ISC_EXECUTOR_BETA; - public IslandWorldChunkGenerator(Random random, IslandWorldMap islandMap, TemperatureMap temperatureMap, BiomeMap biomeMap, boolean uniqueBiome, int seaLevel, int worldHeight) { - this.islandMap = islandMap; - this.temperatureMap = temperatureMap; - this.biomeMap = biomeMap; + public void initialize(Random random, boolean uniqueBiome, int seaLevel, int worldHeight) { + if (initialized) throw new IllegalStateException("This generator has already been initialized"); + initialized = true; + this.islandMap = worldInfo.islandMap; + this.temperatureMap = worldInfo.tempMap; + this.biomeMap = worldInfo.biomeMap; this.heightShader = new WorldHeightShader(random, islandMap, seaLevel, worldHeight, BEDROCK_HEIGHT + 1); this.layerShader = new WorldLayerShader(random, seaLevel, worldHeight, islandMap); @@ -51,11 +56,19 @@ public class IslandWorldChunkGenerator extends ChunkGenerator implements Listene } else { throw new NotImplementedException(); } + } + public IslandWorldChunkGenerator(WorldInfo worldInfo) { + this.worldInfo = worldInfo; } @Override public ChunkData generateChunkData(World world, Random random, int chunkX, int chunkZ, BiomeGrid biomeGrid) { + if (!worldInfo.isInitialized()) { + worldInfo.initialize(world, this); + } + if (!initialized) throw new IllegalStateException("This generator has not been initialized."); + long seed = world.getSeed(); int maxHeight = world.getMaxHeight(); int seaLevel = world.getSeaLevel(); @@ -130,9 +143,16 @@ public class IslandWorldChunkGenerator extends ChunkGenerator implements Listene return chunkData; } + /** + * @return if this generator has been initialized. + */ + public boolean isInitialized() { + return initialized; + } + @Override public boolean canSpawn(World world, int x, int z) { - return islandMap.isLand(x, z); + return super.canSpawn(world, x, z); } @Override @@ -142,22 +162,22 @@ public class IslandWorldChunkGenerator extends ChunkGenerator implements Listene @Override public boolean shouldGenerateCaves() { - return false; + return true; } @Override public boolean shouldGenerateDecorations() { - return false; + return true; } @Override public boolean shouldGenerateStructures() { - return false; + return true; } @Override public boolean shouldGenerateMobs() { - return false; + return true; } @Override diff --git a/src/main/java/ca/recrown/islandsurvivalcraft/world/generation/PluginDefaultWorldGenerator.java b/src/main/java/ca/recrown/islandsurvivalcraft/world/generation/PluginDefaultWorldGenerator.java deleted file mode 100644 index 6a9ad47..0000000 --- a/src/main/java/ca/recrown/islandsurvivalcraft/world/generation/PluginDefaultWorldGenerator.java +++ /dev/null @@ -1,25 +0,0 @@ -package ca.recrown.islandsurvivalcraft.world.generation; - -import java.util.Random; - -import org.bukkit.World; -import org.bukkit.generator.ChunkGenerator; - -import ca.recrown.islandsurvivalcraft.world.WorldInfoManager; - -public class PluginDefaultWorldGenerator extends ChunkGenerator { - private final WorldInfoManager worldInfos; - - /** - * Creates a default world generator given a world info manager to associate the new world info with. - * @param worldInfoManager The manager to associate the newly created world info with. - */ - public PluginDefaultWorldGenerator(WorldInfoManager worldInfoManager) { - this.worldInfos = worldInfoManager; - } - - @Override - public ChunkData generateChunkData(World world,Random random, int x, int z, BiomeGrid biome) { - return worldInfos.retrieve(world).generator.generateChunkData(world, random, x, z, biome); - } -} \ No newline at end of file