Implemented concept of island origin coords.

Useful for hashing an island potentially.
This commit is contained in:
2020-05-05 16:49:21 -05:00
parent 46f393c30e
commit 778b334ceb
9 changed files with 120 additions and 67 deletions

View File

@@ -25,6 +25,10 @@ public class Point2 {
return point.hashCode() == this.hash && x == point.x && y == point.y;
}
public double distance(Point2 point) {
return Math.hypot(point.x - this.x, point.y - this.y);
}
@Override
public int hashCode() {
return hash;

View File

@@ -0,0 +1,5 @@
package ca.recrown.islandsurvivalcraft.utilities.datatypes;
public class Reference<T> {
public T value;
}

View File

@@ -6,10 +6,12 @@ import org.bukkit.util.noise.SimplexOctaveGenerator;
import ca.recrown.islandsurvivalcraft.utilities.caching.Cache;
import ca.recrown.islandsurvivalcraft.utilities.datatypes.Point2;
import ca.recrown.islandsurvivalcraft.utilities.datatypes.Reference;
import ca.recrown.islandsurvivalcraft.utilities.pathfinding.CoordinateTargetValidatable;
import ca.recrown.islandsurvivalcraft.utilities.pathfinding.CoordinateValidatable;
import ca.recrown.islandsurvivalcraft.utilities.pathfinding.DepthFirstSearch;
public class IslandWorldMap implements CoordinateValidatable {
public class IslandWorldMap {
private final Cache<Point2, Double> blockValueCache;
private final SimplexOctaveGenerator noiseGenerator;
@@ -24,7 +26,13 @@ public class IslandWorldMap implements CoordinateValidatable {
private final DepthFirstSearch dfs;
public IslandWorldMap(Random random) {
dfs = new DepthFirstSearch(this);
dfs = new DepthFirstSearch(new CoordinateValidatable(){
@Override
public boolean validate(int x, int y) {
return isIsland(x, y);
}
});
this.noiseGenerator = new SimplexOctaveGenerator(random, NOISE_OCTAVES);
noiseGenerator.setScale(SCALE);
this.blockValueCache = new Cache<>(131072);
@@ -155,8 +163,41 @@ public class IslandWorldMap implements CoordinateValidatable {
return getWorldValue(worldX, worldZ) <= -DEEP_OCEAN_PORTION;
}
@Override
public boolean validate(int x, int y) {
return isIsland(x, y);
/**
* Find the island's origin block. Will call the coordinate target validatable to end early if nessecary.
* @param worldX The x coordinate of the island block in question.
* @param worldZ The y coordinate of the island block in question.
* @param coordinateTargetValidatable The coordinate target validator to use. Optional and is null.
* @return The island origin point.
*/
public Point2 findIslandOrigin(int worldX, int worldZ, CoordinateTargetValidatable coordinateTargetValidatable) {
if (!isIsland(worldX, worldZ)) throw new IllegalArgumentException("The given coordinates are not part is an island.");
dfs.setStartPosition(worldX, worldZ);
final Point2 goal = new Point2(0, 0);
dfs.setEndPosition(goal);
Reference<Point2> closest = new Reference<>();
dfs.findTarget(new CoordinateTargetValidatable(){
Double closestDistance = null;
@Override
public boolean isCoordinateTarget(int x, int y) {
Point2 current = new Point2(x, y);
double currentDistance = current.distance(goal);
if (closestDistance == null || (currentDistance) < closestDistance) {
closestDistance = currentDistance;
closest.value = current;
if (coordinateTargetValidatable != null) {
return coordinateTargetValidatable.isCoordinateTarget(x, y);
}
}
return false;
}
});
return closest.value;
}
public Point2 findIslandOrigin(int worldX, int worldZ) {
return findIslandOrigin(worldX, worldZ, null);
}
}

View File

@@ -28,5 +28,5 @@ public interface BiomeGenerator {
* @param biomeCache Cache for biomes.
* @param chunkGenCache Cache for whether or not the chunk is generated.
*/
public void generateBiomeColumn(Biome[][][] chunkBiomeSets, World world, int chunkX, int chunkZ, int localX, int localZ, IslandWorldMap mapper, BiomeMap biomeSelector, TemperatureMap tempGenerator, Cache<Point2, Biome[]> biomeCache, Cache<Point2, Boolean> chunkGenCache);
public void generateBiomeColumn(Biome[][][] chunkBiomeSets, World world, int chunkX, int chunkZ, int localX, int localZ, IslandWorldMap mapper, BiomeMap biomeSelector, TemperatureMap tempGenerator, Cache<Point2, Biome[]> biomeCache);
}

View File

@@ -9,21 +9,19 @@ import ca.recrown.islandsurvivalcraft.utilities.datatypes.Point2;
import ca.recrown.islandsurvivalcraft.utilities.floodfill.Floodable;
import ca.recrown.islandsurvivalcraft.utilities.floodfill.Flooder;
import ca.recrown.islandsurvivalcraft.utilities.pathfinding.CoordinateTargetValidatable;
import ca.recrown.islandsurvivalcraft.utilities.pathfinding.DepthFirstSearch;
import ca.recrown.islandsurvivalcraft.utilities.pathfinding.CoordinateValidatable;
import ca.recrown.islandsurvivalcraft.world.BiomeMap;
import ca.recrown.islandsurvivalcraft.world.IslandWorldMap;
import ca.recrown.islandsurvivalcraft.world.TemperatureMap;
public class UniqueBiomeGenerator implements BiomeGenerator {
@Override
public void generateBiomeColumn(Biome[][][] chunkBiomeSets, World world, int chunkX, int chunkZ, int localX, int localZ, IslandWorldMap islandMap, BiomeMap biomeSelector, TemperatureMap tempGen, Cache<Point2, Biome[]> biomeCache, Cache<Point2, Boolean> chunkGenCache) {
public void generateBiomeColumn(Biome[][][] chunkBiomeSets, World world, int chunkX, int chunkZ, int localX, int localZ, IslandWorldMap islandMap, BiomeMap biomeSelector, TemperatureMap tempGen, Cache<Point2, Biome[]> biomeCache) {
int worldX = 16 * chunkX + localX;
int worldZ = 16 * chunkZ + localZ;
Point2 chunkCoords = GeneralUtilities.worldToChunkCoordinates(new Point2(worldX, worldZ));
chunkGenCache.set(chunkCoords, false);
//Check if we can just give it something in cache.
Biome[] biomeSet = attemptGetBiomeSet(world, worldX, worldZ, biomeCache, chunkGenCache, null);
Biome[] biomeSet = attemptGetBiomeSet(world, worldX, worldZ, biomeCache, null);
if (biomeSet != null) {
chunkBiomeSets[localX][localZ] = biomeSet;
return;
@@ -38,16 +36,13 @@ public class UniqueBiomeGenerator implements BiomeGenerator {
}
//Shoot, looks like it's actually an island.
DepthFirstSearch search = new DepthFirstSearch();
search.setValidatable(islandMap);
IslandInfo islandInfo = new IslandInfo(islandMap, world, biomeCache, chunkGenCache);
search.setStartPosition(worldX, worldZ);
if (!search.findTarget(islandInfo)) {
IslandInfo islandInfo = new IslandInfo(islandMap, world, biomeCache);
Point2 islandOrigin = islandMap.findIslandOrigin(worldX, worldZ, islandInfo);
if (!islandInfo.isComplete()) {
float temp = tempGen.getTemperature(worldX, worldZ);
if (islandInfo.main == null) islandInfo.main = biomeSelector.getLandBiome(temp, worldX, worldZ);
if (islandInfo.main == null) islandInfo.main = biomeSelector.getLandBiome(temp, islandOrigin.x, islandOrigin.y);
if (islandInfo.shore == null) islandInfo.shore = biomeSelector.getShoreBiome(islandInfo.main, temp);
if (islandInfo.shallow == null) islandInfo.shallow = biomeSelector.getOceanBiome(temp, islandMap.isDeepOcean(worldX, worldZ), worldX, worldZ);
if (islandInfo.shallow == null) islandInfo.shallow = biomeSelector.getOceanBiome(temp, islandMap.isDeepOcean(islandOrigin.x, islandOrigin.y), islandOrigin.x, islandOrigin.y);
}
PropagatorInfo propInfo = new PropagatorInfo(islandInfo, chunkBiomeSets, new Point2(chunkX, chunkZ), islandMap, biomeCache);
@@ -55,7 +50,7 @@ public class UniqueBiomeGenerator implements BiomeGenerator {
flooder.start();
}
private Biome[] attemptGetBiomeSet(World world, int worldX, int worldZ, Cache<Point2, Biome[]> biomeCache, Cache<Point2, Boolean> existenceCache, Biome[][][] chunkBiomeSets) {
private Biome[] attemptGetBiomeSet(World world, int worldX, int worldZ, Cache<Point2, Biome[]> biomeCache, Biome[][][] chunkBiomeSets) {
Point2 worldCoords = new Point2(worldX, worldZ);
Biome[] res = null;
@@ -65,20 +60,6 @@ public class UniqueBiomeGenerator implements BiomeGenerator {
}
res = biomeCache.get(worldCoords);
if (res != null) return res;
Point2 chunkCoords = GeneralUtilities.worldToChunkCoordinates(worldCoords);
Boolean chunkExists = existenceCache.get(chunkCoords);
if (chunkExists == null) {
chunkExists = world.isChunkGenerated(worldX, worldZ);
existenceCache.set(chunkCoords, chunkExists);
}
if (chunkExists) {
res = new Biome[4];
res[0] = world.getBiome(worldX, 0, worldZ);
biomeCache.set(worldCoords, res);
}
return res;
}
@@ -91,23 +72,21 @@ public class UniqueBiomeGenerator implements BiomeGenerator {
biomeCache.set(worldCoords, biomeSet);
}
private class IslandInfo implements CoordinateTargetValidatable {
private class IslandInfo implements CoordinateTargetValidatable, CoordinateValidatable {
public final IslandWorldMap mapper;
public final World world;
private final Cache<Point2, Biome[]> biomeCache;
private final Cache<Point2, Boolean> chunkGenCache;
public Biome main, shore, shallow;
public IslandInfo(IslandWorldMap mapper, World world, Cache<Point2, Biome[]> biomeCache, Cache<Point2, Boolean> chunkGenCache) {
public IslandInfo(IslandWorldMap mapper, World world, Cache<Point2, Biome[]> biomeCache) {
this.mapper = mapper;
this.world = world;
this.biomeCache = biomeCache;
this.chunkGenCache = chunkGenCache;
}
@Override
public boolean isCoordinateTarget(int x, int y) {
Biome[] biomeSet = attemptGetBiomeSet(world, x, y, biomeCache, chunkGenCache, null);
Biome[] biomeSet = attemptGetBiomeSet(world, x, y, biomeCache, null);
if (biomeSet != null) {
main = biomeSet[1];
shore = biomeSet[2];
@@ -122,6 +101,15 @@ public class UniqueBiomeGenerator implements BiomeGenerator {
shallow = biomeSet[0];
}
}
return isComplete();
}
@Override
public boolean validate(int x, int y) {
return mapper.isIsland(x, y);
}
public boolean isComplete() {
return main != null && shore != null && shallow != null;
}
}
@@ -146,7 +134,7 @@ public class UniqueBiomeGenerator implements BiomeGenerator {
@Override
public boolean flood(Point2 point) {
Point2 chunkCoords = GeneralUtilities.worldToChunkCoordinates(point);
if (!this.chunkCoords.fastEquals(chunkCoords) || !mapper.validate(point.x, point.y)) return false;
if (!this.chunkCoords.fastEquals(chunkCoords) || !mapper.isIsland(point.x, point.y)) return false;
int x = point.x;
int y = point.y;
Biome[] biomeSet = new Biome[4];

View File

@@ -40,7 +40,6 @@ public class IslandWorldChunkGenerator extends ChunkGenerator implements Listene
private volatile WorldHeightShader heightShader;
private volatile WorldLayerShader layerShader;
private volatile Cache<Point2, Biome[]> biomeCache = new Cache<>(131072);
private volatile Cache<Point2, Boolean> chunkLoadedCache = new Cache<>(4096);
private volatile ExecutorService exAlpha = GeneralUtilities.ISC_EXECUTOR_ALPHA;
private volatile ExecutorService exBeta = GeneralUtilities.ISC_EXECUTOR_BETA;
@@ -100,7 +99,7 @@ public class IslandWorldChunkGenerator extends ChunkGenerator implements Listene
final int worldZ = GeneralUtilities.CHUNK_SIZE * chunkZ + localZ;
if (biomeArraySet[localX][localZ][0] == null) {
biomeGenerator.generateBiomeColumn(biomeArraySet, world, chunkX, chunkZ, localX, localZ, islandMap, biomeMap,
temperatureMap, biomeCache, chunkLoadedCache);
temperatureMap, biomeCache);
}
if (biomeArraySet[localX][localZ][0] == null) throw new IllegalStateException("Biome was null.");
tasks.add(exBeta.submit(() -> {
@@ -146,7 +145,6 @@ public class IslandWorldChunkGenerator extends ChunkGenerator implements Listene
e.printStackTrace();
throw new IllegalStateException(e.getCause().getMessage());
}
chunkLoadedCache.set(new Point2(chunkX, chunkZ), true);
return chunkData;
}