New iteration of biome generator.
Untested.
This commit is contained in:
parent
e93f61c055
commit
a412986044
@ -1,13 +1,13 @@
|
|||||||
package ca.recrown.islandsurvivalcraft.world.generation;
|
package ca.recrown.islandsurvivalcraft.world.generation;
|
||||||
|
|
||||||
|
|
||||||
|
import org.bukkit.Chunk;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.block.Biome;
|
import org.bukkit.block.Biome;
|
||||||
|
|
||||||
import ca.recrown.islandsurvivalcraft.caching.Cache;
|
import ca.recrown.islandsurvivalcraft.caching.Cache;
|
||||||
import ca.recrown.islandsurvivalcraft.caching.CacheValue;
|
import ca.recrown.islandsurvivalcraft.caching.CacheValue;
|
||||||
import ca.recrown.islandsurvivalcraft.caching.CoordinateIdentifier;
|
import ca.recrown.islandsurvivalcraft.caching.CoordinateIdentifier;
|
||||||
import ca.recrown.islandsurvivalcraft.caching.Identifier;
|
|
||||||
import ca.recrown.islandsurvivalcraft.pathfinding.CoordinateTargetValidatable;
|
import ca.recrown.islandsurvivalcraft.pathfinding.CoordinateTargetValidatable;
|
||||||
import ca.recrown.islandsurvivalcraft.pathfinding.CoordinateValidatable;
|
import ca.recrown.islandsurvivalcraft.pathfinding.CoordinateValidatable;
|
||||||
import ca.recrown.islandsurvivalcraft.pathfinding.DepthFirstSearch;
|
import ca.recrown.islandsurvivalcraft.pathfinding.DepthFirstSearch;
|
||||||
@ -15,19 +15,19 @@ import ca.recrown.islandsurvivalcraft.world.BiomeSelector;
|
|||||||
import ca.recrown.islandsurvivalcraft.world.IslandWorldMapper;
|
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.
|
//Note: technically, the validators have to be run on land, and so, some condition checks may not be nessecary.
|
||||||
public class BiomePerIslandGenerator implements IslandBiomeGenerator, CoordinateValidatable, CoordinateTargetValidatable {
|
public class BiomePerIslandGenerator implements IslandBiomeGenerator {
|
||||||
private final Cache<ChunkBiomes> chunkBiomesCache;
|
|
||||||
private final Cache<Boolean> chunkGenStatusCache;
|
|
||||||
private final TemperatureMapGenerator temperatureMapGenerator;
|
|
||||||
private boolean initialized;
|
private boolean initialized;
|
||||||
|
private final TemperatureMapGenerator temperatureMapGenerator;
|
||||||
|
private final Cache<Biome[][]> chunkBiomesCache;
|
||||||
|
private final Cache<Boolean> chunkGenStatusCache;
|
||||||
private IslandWorldMapper worldIslandMap;
|
private IslandWorldMapper worldIslandMap;
|
||||||
private BiomeSelector biomeSelector;
|
private BiomeSelector biomeSelector;
|
||||||
private World world;
|
private World world;
|
||||||
private DepthFirstSearch mapWideDFS;
|
private final DepthFirstSearch freshCachePropagator;
|
||||||
private DepthFirstSearch propagator;
|
private final DepthFirstSearch existenceChecker;
|
||||||
private LocalIslandPropagator propagatorInfo;
|
private FreshCachePropagationInfo freshCachePropInfo;
|
||||||
CoordinateIdentifier chunkCoords;
|
private PreviousGenerationInfo existenceInfo;
|
||||||
ChunkBiomes localChunkBiomes;
|
CoordinateIdentifier currChunkCoords;
|
||||||
|
|
||||||
float temperature;
|
float temperature;
|
||||||
|
|
||||||
@ -35,20 +35,20 @@ public class BiomePerIslandGenerator implements IslandBiomeGenerator, Coordinate
|
|||||||
this.temperatureMapGenerator = new TemperatureMapGenerator();
|
this.temperatureMapGenerator = new TemperatureMapGenerator();
|
||||||
chunkBiomesCache = new Cache<>(1024);
|
chunkBiomesCache = new Cache<>(1024);
|
||||||
chunkGenStatusCache = new Cache<>(1024);
|
chunkGenStatusCache = new Cache<>(1024);
|
||||||
propagatorInfo = new LocalIslandPropagator();
|
freshCachePropInfo = new FreshCachePropagationInfo();
|
||||||
|
freshCachePropagator = new DepthFirstSearch(freshCachePropInfo);
|
||||||
|
existenceInfo = new PreviousGenerationInfo();
|
||||||
|
existenceChecker = new DepthFirstSearch(existenceInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void initialize(final World world, final IslandWorldMapper mapGenerator, final BiomeSelector biomeSelector) {
|
public void initialize(final World world, final IslandWorldMapper mapGenerator, final BiomeSelector biomeSelector) {
|
||||||
if (initialized) throw new IllegalStateException("Biome generator already initialized.");
|
if (initialized) throw new IllegalStateException("Biome generator already initialized.");
|
||||||
initialized = true;
|
initialized = true;
|
||||||
|
this.world = world;
|
||||||
this.worldIslandMap = mapGenerator;
|
this.worldIslandMap = mapGenerator;
|
||||||
this.biomeSelector = biomeSelector;
|
this.biomeSelector = biomeSelector;
|
||||||
this.world = world;
|
|
||||||
this.temperatureMapGenerator.setSeed(world.getSeed());
|
this.temperatureMapGenerator.setSeed(world.getSeed());
|
||||||
mapWideDFS = new DepthFirstSearch(worldIslandMap);
|
|
||||||
mapWideDFS.setEndPosition(0, 0);
|
|
||||||
propagator = new DepthFirstSearch(256, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -57,102 +57,121 @@ public class BiomePerIslandGenerator implements IslandBiomeGenerator, Coordinate
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Biome GenerateBiome(final int chunkX, final int chunkZ, final int localX, final int localZ) {
|
public Biome GenerateBiome(int chunkX, int chunkZ, int localX, int localZ) {
|
||||||
if (chunkCoords == null || chunkCoords.getX() != chunkX || chunkCoords.getY() != chunkZ) {
|
if (currChunkCoords == null || chunkX != currChunkCoords.getX() || chunkZ != currChunkCoords.getY()) {
|
||||||
chunkCoords = new CoordinateIdentifier(chunkX, chunkZ);
|
currChunkCoords = new CoordinateIdentifier(chunkX, chunkZ);
|
||||||
chunkGenStatusCache.retrieveCache(chunkCoords).setValue(true);
|
|
||||||
localChunkBiomes = new ChunkBiomes();
|
|
||||||
chunkBiomesCache.retrieveCache(chunkCoords).setValue(localChunkBiomes);
|
|
||||||
}
|
}
|
||||||
int worldX = 16 * chunkX + localX;
|
int worldX = localX + 16 * chunkX;
|
||||||
int worldZ = 16 * chunkZ + localZ;
|
int worldZ = localZ + 16 * chunkZ;
|
||||||
|
|
||||||
this.temperature = temperatureMapGenerator.getTemperature(worldX, worldZ);
|
Biome cachedBiome = getBiome(worldX, worldZ);
|
||||||
if (worldIslandMap.isIsland(worldX, worldZ) && localChunkBiomes.biomes[localX][localZ] == null) {
|
if (cachedBiome != null) return cachedBiome;
|
||||||
mapWideDFS.setStartPosition(worldX, worldZ);
|
temperature = temperatureMapGenerator.getTemperature(worldX, worldZ);
|
||||||
if (!mapWideDFS.findTarget(this)) {
|
|
||||||
if (propagatorInfo.mainBiome == null) propagatorInfo.mainBiome = biomeSelector.getLandBiome(temperature);
|
if (!worldIslandMap.isIsland(worldX, worldZ)) {
|
||||||
if (propagatorInfo.shoreBiome == null) propagatorInfo.shoreBiome = biomeSelector.getShoreBiome(propagatorInfo.mainBiome, temperature);
|
return biomeSelector.getOceanBiome(temperature);
|
||||||
if (propagatorInfo.shallowBiome == null) propagatorInfo.shallowBiome = biomeSelector.getOceanBiome(temperature);
|
|
||||||
}
|
|
||||||
propagator.setStartPosition(worldX, worldZ);
|
|
||||||
propagator.findTarget(propagatorInfo);
|
|
||||||
}
|
}
|
||||||
if (localChunkBiomes.biomes[localX][localZ] == null) {
|
|
||||||
localChunkBiomes.biomes[localX][localZ] = biomeSelector.getOceanBiome(temperature);
|
freshCachePropInfo.clear();
|
||||||
|
existenceChecker.setStartPosition(worldX, worldZ);
|
||||||
|
if (!existenceChecker.findTarget(existenceInfo)) {
|
||||||
|
if (freshCachePropInfo.main == null) freshCachePropInfo.main = biomeSelector.getLandBiome(temperature);
|
||||||
|
if (freshCachePropInfo.shore == null) freshCachePropInfo.shore = biomeSelector.getShoreBiome(freshCachePropInfo.main, temperature);
|
||||||
|
if (freshCachePropInfo.shallow == null) freshCachePropInfo.shallow = biomeSelector.getOceanBiome(temperature);
|
||||||
}
|
}
|
||||||
return localChunkBiomes.biomes[localX][localZ];
|
freshCachePropagator.setStartPosition(worldX, worldZ);
|
||||||
|
freshCachePropagator.findTarget(freshCachePropInfo);
|
||||||
|
return getBiome(worldX, worldZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private Biome getBiome(int worldX, int worldZ) {
|
||||||
public boolean validate(int x, int y) {
|
|
||||||
return (x / 16) == chunkCoords.getX() && (y / 16) == chunkCoords.getY() && worldIslandMap.isIsland(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isCoordinateTarget(int x, int y) {
|
|
||||||
if ((propagatorInfo.shoreBiome == null || propagatorInfo.mainBiome == null) && worldIslandMap.isLand(x, y)) {
|
|
||||||
if (propagatorInfo.shoreBiome == null && worldIslandMap.isShore(x, y)) {
|
|
||||||
propagatorInfo.shoreBiome = getBiomeAt(x, y);
|
|
||||||
} else if (propagatorInfo.mainBiome != null) {
|
|
||||||
propagatorInfo.mainBiome = getBiomeAt(x, y);
|
|
||||||
}
|
|
||||||
} else if (propagatorInfo.shallowBiome == null) {
|
|
||||||
propagatorInfo.shallowBiome = getBiomeAt(x, y);
|
|
||||||
}
|
|
||||||
return (propagatorInfo.shallowBiome != null && propagatorInfo.mainBiome != null && propagatorInfo.shoreBiome != null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Biome getBiomeAt(int worldX, int worldZ) {
|
|
||||||
int chunkX = worldX / 16;
|
|
||||||
int chunkZ = worldZ / 16;
|
|
||||||
int localX = Math.abs(worldX % 16);
|
int localX = Math.abs(worldX % 16);
|
||||||
int localZ = Math.abs(worldZ % 16);
|
int localZ = Math.abs(worldZ % 16);
|
||||||
|
CoordinateIdentifier chunkCoords = new CoordinateIdentifier(worldX / 16, worldZ / 16);
|
||||||
|
|
||||||
Identifier chunkBiomeID = new CoordinateIdentifier(chunkX, chunkZ);
|
CacheValue<Biome[][]> chunkBiomes = chunkBiomesCache.retrieveCache(chunkCoords);
|
||||||
Identifier chunkGenID = new CoordinateIdentifier(chunkX, chunkZ);
|
if (!chunkBiomes.isEmpty()) {
|
||||||
|
Biome biome = chunkBiomes.getValue()[localX][localZ];
|
||||||
|
if (biome != null) return biome;
|
||||||
|
}
|
||||||
|
|
||||||
CacheValue<ChunkBiomes> chunkBiomeVal = chunkBiomesCache.retrieveCache(chunkBiomeID);
|
CacheValue<Boolean> chunkGenStatus = chunkGenStatusCache.retrieveCache(chunkCoords);
|
||||||
CacheValue<Boolean> chunkGenVal = chunkGenStatusCache.retrieveCache(chunkGenID);
|
if (chunkGenStatus.isEmpty())
|
||||||
|
chunkGenStatus.setValue(world.isChunkGenerated(chunkCoords.getX(), chunkCoords.getY()));
|
||||||
if (chunkGenVal.isEmpty()) chunkGenVal.setValue(world.isChunkGenerated(worldX / 16, worldZ / 16));
|
|
||||||
|
if (chunkGenStatus.getValue()) {
|
||||||
if (chunkGenVal.getValue()) {
|
if (chunkBiomes.isEmpty()) chunkBiomes.setValue(new Biome[16][16]);
|
||||||
if (chunkBiomeVal.isEmpty()) {
|
chunkBiomes.getValue()[localX][localZ] = world.getBiome(worldX, 0, worldZ);
|
||||||
chunkBiomeVal.setValue(new ChunkBiomes());
|
return chunkBiomes.getValue()[localX][localZ];
|
||||||
}
|
|
||||||
|
|
||||||
if (chunkBiomeVal.getValue().biomes[localX][localZ] == null) {
|
|
||||||
chunkBiomeVal.getValue().biomes[localX][localZ] = world.getBiome(worldX, 0, worldZ);
|
|
||||||
}
|
|
||||||
return chunkBiomeVal.getValue().biomes[localX][localZ] = world.getBiome(worldX, 0, worldZ);
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ChunkBiomes {
|
private void setCacheBiome(int worldX, int worldZ, Biome biome) {
|
||||||
public final Biome[][] biomes = new Biome[16][16];
|
int localX = Math.abs(worldX % 16);
|
||||||
|
int localZ = Math.abs(worldZ % 16);
|
||||||
|
CoordinateIdentifier chunkCoords = new CoordinateIdentifier(worldX / 16, worldZ / 16);
|
||||||
|
|
||||||
|
CacheValue<Biome[][]> chunkBiomes = chunkBiomesCache.retrieveCache(chunkCoords);
|
||||||
|
if (chunkBiomes.isEmpty()) chunkBiomes.setValue(new Biome[16][16]);
|
||||||
|
chunkBiomes.getValue()[localX][localZ] = biome;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class LocalIslandPropagator implements CoordinateTargetValidatable {
|
private class FreshCachePropagationInfo implements CoordinateTargetValidatable, CoordinateValidatable {
|
||||||
public Biome mainBiome = null;
|
public Biome shore;
|
||||||
public Biome shoreBiome = null;
|
public Biome main;
|
||||||
public Biome shallowBiome = null;
|
public Biome shallow;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCoordinateTarget(int x, int y) {
|
public boolean isCoordinateTarget(int x, int y) {
|
||||||
int localX = Math.abs(x % 16);
|
|
||||||
int localZ = Math.abs(y % 16);
|
|
||||||
if (worldIslandMap.isLand(x, y)) {
|
if (worldIslandMap.isLand(x, y)) {
|
||||||
if (worldIslandMap.isShore(x, y)) {
|
if (worldIslandMap.isShore(x, y)) {
|
||||||
localChunkBiomes.biomes[localX][localZ] = shoreBiome;
|
setCacheBiome(x, y, shore);
|
||||||
} else {
|
} else {
|
||||||
localChunkBiomes.biomes[localX][localZ] = mainBiome;
|
setCacheBiome(x, y, main);
|
||||||
}
|
}
|
||||||
} else if (worldIslandMap.isShallowPortion(x, y)) {
|
} else {
|
||||||
localChunkBiomes.biomes[localX][localZ] = shallowBiome;
|
setCacheBiome(x, y, shallow);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean validate(int x, int y) {
|
||||||
|
return x / 16 == currChunkCoords.getX() && y / 16 == currChunkCoords.getY() && worldIslandMap.isIsland(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean allBiomesAcquired() {
|
||||||
|
return shore != null && main != null && shallow != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
main = null;
|
||||||
|
shore = null;
|
||||||
|
shallow = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class PreviousGenerationInfo implements CoordinateTargetValidatable, CoordinateValidatable {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean validate(int x, int y) {
|
||||||
|
return worldIslandMap.isIsland(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCoordinateTarget(int x, int y) {
|
||||||
|
if (freshCachePropInfo.main == null && worldIslandMap.isLand(x, y) && !worldIslandMap.isShore(x, y)) {
|
||||||
|
freshCachePropInfo.main = getBiome(x, y);
|
||||||
|
}
|
||||||
|
if (freshCachePropInfo.shore == null && worldIslandMap.isShore(x, y)) {
|
||||||
|
freshCachePropInfo.shore = getBiome(x, y);
|
||||||
|
}
|
||||||
|
if (freshCachePropInfo.shallow == null && worldIslandMap.isShallowPortion(x, y)) {
|
||||||
|
freshCachePropInfo.shallow = getBiome(x, y);
|
||||||
|
}
|
||||||
|
return freshCachePropInfo.allBiomesAcquired();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user