Refactoring with different heavy changes to biome generator.

Attempt at making it my async compatible.
This commit is contained in:
Harrison Deng 2020-04-26 23:07:25 -05:00
parent 0886412cfb
commit 6ac686b86c
7 changed files with 103 additions and 103 deletions

View File

@ -3,15 +3,15 @@ package ca.recrown.islandsurvivalcraft;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.plugin.java.JavaPlugin;
import ca.recrown.islandsurvivalcraft.world.IslandSurvivalCraftChunkGenerator;
import ca.recrown.islandsurvivalcraft.world.generation.BiomePerIslandGenerator;
import ca.recrown.islandsurvivalcraft.world.generation.alternation.AlternatingChunkGenerator;
public class IslandSurvivalCraft extends JavaPlugin {
IslandSurvivalCraftChunkGenerator generator;
AlternatingChunkGenerator generator;
@Override
public void onEnable() {
generator = new IslandSurvivalCraftChunkGenerator(this, new BiomePerIslandGenerator());
generator = new AlternatingChunkGenerator(this, new BiomePerIslandGenerator());
super.onEnable();
}

View File

@ -1,32 +0,0 @@
package ca.recrown.islandsurvivalcraft.world;
import java.util.Random;
import org.bukkit.World;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.plugin.java.JavaPlugin;
import ca.recrown.islandsurvivalcraft.world.generation.IslandBiomeGenerator;
import ca.recrown.islandsurvivalcraft.world.generation.IslandWorldGenerator;
public class IslandSurvivalCraftChunkGenerator extends ChunkGenerator {
private final IslandWorldGeneratorAlternator alternator;
public IslandSurvivalCraftChunkGenerator(JavaPlugin plugin, IslandBiomeGenerator biomeGenerator) {
alternator = new IslandWorldGeneratorAlternator(plugin, biomeGenerator);
}
@Override
public ChunkData generateChunkData(World world, Random random, int chunkX, int chunkZ, BiomeGrid biome) {
IslandWorldGenerator worldGenerator = alternator.getIslandChunkGeneratorSystem(world, random);
ChunkData chunk = createChunkData(world);
for (int localX = 0; localX < 16; localX++) {
for (int localZ = 0; localZ < 16; localZ++) {
worldGenerator.GenerateChunk(chunkX, chunkZ, localX, localZ, chunk, biome);
}
}
return chunk;
}
}

View File

@ -7,8 +7,8 @@ import org.bukkit.event.Listener;
import ca.recrown.islandsurvivalcraft.world.BiomeSelector;
import ca.recrown.islandsurvivalcraft.world.IslandWorldMapper;
public interface IslandBiomeGenerator extends Listener {
public interface BiomeGenerator extends Listener {
public void initialize(World world, IslandWorldMapper mapGenerator, BiomeSelector biomeSelector);
public Biome GenerateBiome(int chunkX, int chunkZ, int localX, int localZ);
public IslandBiomeGenerator getInstance();
public BiomeGenerator getInstance();
}

View File

@ -17,7 +17,7 @@ import ca.recrown.islandsurvivalcraft.world.BiomeSelector;
import ca.recrown.islandsurvivalcraft.world.IslandWorldMapper;
//Note: technically, the validators have to be run on land, and so, some condition checks may not be nessecary.
public class BiomePerIslandGenerator implements IslandBiomeGenerator {
public class BiomePerIslandGenerator implements BiomeGenerator {
private volatile boolean initialized;
private final TemperatureMapGenerator temperatureMapGenerator;
private final Cache<Point2, Biome> chunkBiomesCache;
@ -25,16 +25,11 @@ public class BiomePerIslandGenerator implements IslandBiomeGenerator {
private volatile IslandWorldMapper worldIslandMap;
private volatile BiomeSelector biomeSelector;
private volatile World world;
private volatile Point2 currChunkCoords;
private volatile Biome[][] localChunkCache;
float temperature;
public BiomePerIslandGenerator() {
this.temperatureMapGenerator = new TemperatureMapGenerator();
chunkBiomesCache = new Cache<>(65536);
chunkGenStatusCache = new Cache<>(16384);
localChunkCache = new Biome[16][16];
chunkGenStatusCache = new Cache<>(65536);
}
@Override
@ -47,7 +42,7 @@ public class BiomePerIslandGenerator implements IslandBiomeGenerator {
this.temperatureMapGenerator.setSeed(world.getSeed());
}
@EventHandler(priority = EventPriority.HIGH)
@EventHandler(priority = EventPriority.MONITOR)
public void onChunkLoaded(ChunkLoadEvent event) {
if (event.isNewChunk()) {
Chunk chunk = event.getChunk();
@ -58,25 +53,23 @@ public class BiomePerIslandGenerator implements IslandBiomeGenerator {
}
@Override
public IslandBiomeGenerator getInstance() {
public BiomeGenerator getInstance() {
return new BiomePerIslandGenerator();
}
@Override
public Biome GenerateBiome(int chunkX, int chunkZ, int localX, int localZ) {
if (currChunkCoords == null || chunkX != currChunkCoords.x || chunkZ != currChunkCoords.y) {
currChunkCoords = new Point2(chunkX, chunkZ);
localChunkCache = new Biome[16][16];
}
int worldX = Utilities.addMagnitude(16 * chunkX, localX);
int worldZ = Utilities.addMagnitude(16 * chunkZ, localZ);
Point2 currChunkCoords = new Point2(chunkX, chunkZ);
int worldX = 16 * chunkX + localX;
int worldZ = 16 * chunkZ + localZ;
Point2 worldCoords = new Point2(worldX, worldZ);
Biome cachedBiome = getBiome(worldCoords);
Biome cachedBiome = getStoredBiome(worldCoords);
if (cachedBiome != null) return cachedBiome;
temperature = temperatureMapGenerator.getTemperature(worldX, worldZ);
float temperature = temperatureMapGenerator.getTemperature(worldX, worldZ);
if (!worldIslandMap.isIsland(worldX, worldZ)) {
return biomeSelector.getOceanBiome(temperature);
}
@ -89,28 +82,30 @@ public class BiomePerIslandGenerator implements IslandBiomeGenerator {
if (biomeInfo.shore == null) biomeInfo.shore = biomeSelector.getShoreBiome(biomeInfo.main, temperature);
if (biomeInfo.shallow == null) biomeInfo.shallow = biomeSelector.getOceanBiome(temperature);
}
FreshCachePropagationInfo propInfo = new FreshCachePropagationInfo(biomeInfo.main, biomeInfo.shore, biomeInfo.shallow);
PropagatorInfo propInfo = new PropagatorInfo(biomeInfo.main, biomeInfo.shore, biomeInfo.shallow, currChunkCoords);
DepthFirstSearch prop = new DepthFirstSearch(propInfo);
prop.setStartPosition(worldX, worldZ);
prop.findTarget(propInfo);
return getBiome(worldCoords);
if (worldIslandMap.isLand(worldX, worldZ)) {
if (worldIslandMap.isShore(worldX, worldZ)) {
return biomeInfo.shore;
} else {
return biomeInfo.main;
}
} else {
return biomeInfo.shallow;
}
}
private Biome getBiome(Point2 worldCoords) {
int localX = Math.abs(worldCoords.x % 16);
int localZ = Math.abs(worldCoords.y % 16);
Point2 chunkCoords = new Point2(worldCoords.x / 16, worldCoords.y / 16);
private Biome getStoredBiome(Point2 worldCoords) {
Point2 chunkCoords = Utilities.worldToChunkCoordinates(worldCoords);
//chunk local
if (chunkCoords.fastEquals(this.currChunkCoords) && localChunkCache[localX][localZ] != null) {
return localChunkCache[localX][localZ];
}
//cache local
//Search our cache first.
Biome biome = chunkBiomesCache.getValue(worldCoords);
if (biome != null) return biome;
//files local
//Check to see if bukkit has anything to say about it.
Boolean chunkGenStat = chunkGenStatusCache.getValue(chunkCoords);
if (chunkGenStat == null) {
chunkGenStat = world.isChunkGenerated(chunkCoords.x, chunkCoords.y);
@ -122,49 +117,52 @@ public class BiomePerIslandGenerator implements IslandBiomeGenerator {
chunkBiomesCache.setValue(worldCoords, biome);
return biome;
}
//Guess it's not cached or created.
return null;
}
private void setCacheBiome(Point2 worldCoords, Biome biome) {
int localX = Math.abs(worldCoords.x % 16);
int localZ = Math.abs(worldCoords.y % 16);
Point2 chunkCoords = new Point2(worldCoords.x / 16, worldCoords.y / 16);
//If local, set it locally.
if (chunkCoords.fastEquals(this.currChunkCoords)) localChunkCache[localX][localZ] = biome;
//Set it cache wide.
//Set it in cache.
chunkBiomesCache.setValue(worldCoords, biome);
}
private class FreshCachePropagationInfo implements CoordinateTargetValidatable, CoordinateValidatable {
private class PropagatorInfo implements CoordinateTargetValidatable, CoordinateValidatable {
public final Biome main, shore, shallow;
private final Point2 currentChunkCoords;
private boolean hasSet;
@Override
public boolean isCoordinateTarget(int x, int y) {
hasSet = false;
Point2 worldCoords = new Point2(x, y);
if (worldIslandMap.isLand(x, y)) {
if (worldIslandMap.isShore(x, y)) {
setCacheBiome(worldCoords, shore);
hasSet = true;
} else {
setCacheBiome(worldCoords, main);
hasSet = true;
}
} else {
setCacheBiome(worldCoords, shallow);
hasSet = true;
}
if (!hasSet) throw new IllegalStateException();
return false;
}
@Override
public boolean validate(int x, int y) {
Point2 chunkCoords = new Point2(x / 16, y / 16);
return chunkCoords.fastEquals(currChunkCoords) && worldIslandMap.isIsland(x, y);
Point2 chunkCoords = Utilities.worldToChunkCoordinates(x, y);
return chunkCoords.fastEquals(currentChunkCoords) && worldIslandMap.isIsland(x, y);
}
public FreshCachePropagationInfo(Biome main, Biome shore, Biome shallow) {
public PropagatorInfo(Biome main, Biome shore, Biome shallow, Point2 currentChunkCoords) {
this.main = main;
this.shore = shore;
this.shallow = shallow;
this.currentChunkCoords = currentChunkCoords;
}
}
@ -191,13 +189,13 @@ public class BiomePerIslandGenerator implements IslandBiomeGenerator {
}
if (main == null && isLand && !isShore) {
main = getBiome(worldCoords);
main = getStoredBiome(worldCoords);
} else
if (shore == null && isShore) {
shore = getBiome(worldCoords);
shore = getStoredBiome(worldCoords);
} else
if (shallow == null && isShallow) {
shallow = getBiome(worldCoords);
shallow = getStoredBiome(worldCoords);
}
return allBiomesAcquired();
}

View File

@ -10,7 +10,6 @@ import org.bukkit.generator.ChunkGenerator.BiomeGrid;
import org.bukkit.generator.ChunkGenerator.ChunkData;
import org.bukkit.plugin.java.JavaPlugin;
import ca.recrown.islandsurvivalcraft.Utilities;
import ca.recrown.islandsurvivalcraft.world.BiomeSelector;
import ca.recrown.islandsurvivalcraft.world.IslandWorldMapper;
import ca.recrown.islandsurvivalcraft.world.shaders.WorldHeightShader;
@ -18,17 +17,17 @@ import ca.recrown.islandsurvivalcraft.world.shaders.WorldHeightShader;
/**
* A world generator.
*/
public class IslandWorldGenerator {
public class WorldGenerator {
private final int maxHeight;
private final BedrockGenerator bedrockGenerator;
private final BiomeSelector biomeSelector;
private final IslandBiomeGenerator biomeGenerator;
private final BiomeGenerator biomeGenerator;
private final WorldHeightShader heightShader;
public final World world;
public final IslandWorldMapper islandMapGenerator;
public final Random random;
public IslandWorldGenerator(JavaPlugin plugin, World world, IslandBiomeGenerator islandBiomeGenerator, Random random) {
public WorldGenerator(JavaPlugin plugin, World world, BiomeGenerator islandBiomeGenerator, Random random) {
this.world = world;
this.maxHeight = world.getMaxHeight();
this.random = random;
@ -46,19 +45,18 @@ public class IslandWorldGenerator {
}
public void GenerateChunk(int chunkX, int chunkZ, int localX, int localZ, ChunkData chunk, BiomeGrid biomeGrid) {
int worldX = Utilities.addMagnitude(16 * chunkX, localX);
int worldZ = Utilities.addMagnitude(16 * chunkZ, localZ);
int worldX = 16 * chunkX + localX;
int worldZ = 16 * chunkZ + localZ;
// gets the bedrock.
int bedrockHeight = bedrockGenerator.getBedrockHeight(worldX, worldZ);
//Sets the biome.
Biome currentBiome = biomeGenerator.GenerateBiome(chunkX, chunkZ, localX, localZ);
if (currentBiome == null) throw new IllegalStateException("Biome generated was null!");
for (int y = 0; y < maxHeight; y++) {
biomeGrid.setBiome(localX, y, localZ, currentBiome);
}
//get height shader.
int height = 0;
try {
@ -69,8 +67,12 @@ public class IslandWorldGenerator {
}
if (height == 0) throw new IllegalStateException("Height generated was null!");
// gets the bedrock height.
int bedrockHeight = bedrockGenerator.getBedrockHeight(worldX, worldZ);
//set general shape
chunk.setRegion(localX, 0, localZ, localX + 1, height, localZ + 1, Material.STONE);
chunk.setRegion(localX, bedrockHeight, localZ, localX + 1, height, localZ + 1, Material.STONE);
//set bedrock last
chunk.setRegion(localX, 0, localZ, localX + 1, bedrockHeight, localZ + 1, Material.BEDROCK);

View File

@ -0,0 +1,32 @@
package ca.recrown.islandsurvivalcraft.world.generation.alternation;
import java.util.Random;
import org.bukkit.World;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.plugin.java.JavaPlugin;
import ca.recrown.islandsurvivalcraft.world.generation.BiomeGenerator;
import ca.recrown.islandsurvivalcraft.world.generation.WorldGenerator;
public class AlternatingChunkGenerator extends ChunkGenerator {
private final WorldGeneratorAlternator alternator;
public AlternatingChunkGenerator(JavaPlugin plugin, BiomeGenerator biomeGenerator) {
alternator = new WorldGeneratorAlternator(plugin, biomeGenerator);
}
@Override
public ChunkData generateChunkData(World world, Random random, int chunkX, int chunkZ, BiomeGrid biome) {
WorldGenerator worldGenerator = alternator.getGenerator(world, random);
ChunkData chunk = createChunkData(world);
for (int localX = 0; localX < 16; localX++) {
for (int localZ = 0; localZ < 16; localZ++) {
worldGenerator.GenerateChunk(chunkX, chunkZ, localX, localZ, chunk, biome);
}
}
return chunk;
}
}

View File

@ -1,4 +1,4 @@
package ca.recrown.islandsurvivalcraft.world;
package ca.recrown.islandsurvivalcraft.world.generation.alternation;
import java.util.HashMap;
import java.util.Random;
@ -10,30 +10,30 @@ import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
import org.bukkit.World;
import org.bukkit.plugin.java.JavaPlugin;
import ca.recrown.islandsurvivalcraft.world.generation.IslandBiomeGenerator;
import ca.recrown.islandsurvivalcraft.world.generation.IslandWorldGenerator;
import ca.recrown.islandsurvivalcraft.world.generation.BiomeGenerator;
import ca.recrown.islandsurvivalcraft.world.generation.WorldGenerator;
/**
* Alternates the data used on a per world basis.
* Uses IslandWorldGenerator as the container for each world.
*/
public class IslandWorldGeneratorAlternator {
private final HashMap<UUID, IslandWorldGenerator> chunkGenerators;
private volatile IslandWorldGenerator lastGenerator;
public class WorldGeneratorAlternator {
private final HashMap<UUID, WorldGenerator> chunkGenerators;
private volatile WorldGenerator lastGenerator;
private volatile UUID lastUUID;
private final IslandBiomeGenerator islandBiomeGenerator;
private final BiomeGenerator islandBiomeGenerator;
private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true);
private final ReadLock readLock = lock.readLock();
private final WriteLock writeLock = lock.writeLock();
private final JavaPlugin plugin;
public IslandWorldGeneratorAlternator(JavaPlugin plugin, IslandBiomeGenerator biomeGenerator) {
public WorldGeneratorAlternator(JavaPlugin plugin, BiomeGenerator biomeGenerator) {
this.chunkGenerators = new HashMap<>();
this.islandBiomeGenerator = biomeGenerator;
this.plugin = plugin;
}
public IslandWorldGenerator getIslandChunkGeneratorSystem(World world, Random random) {
public WorldGenerator getGenerator(World world, Random random) {
if (lastUUID == null || (lastUUID.hashCode() != world.getUID().hashCode() && lastUUID.equals(world.getUID()))) {
System.out.println("Alternating generator for world: " + world.getName());
lastUUID = world.getUID();
@ -44,7 +44,7 @@ public class IslandWorldGeneratorAlternator {
readLock.unlock();
}
if (lastGenerator == null) {
lastGenerator = new IslandWorldGenerator(plugin, world, islandBiomeGenerator, random);
lastGenerator = new WorldGenerator(plugin, world, islandBiomeGenerator, random);
writeLock.lock();
try {
chunkGenerators.put(lastUUID, lastGenerator);