Reworked biome generation and used DFS for continuity.
Also made changes to structure to better support Bukkit's structure.
This commit is contained in:
parent
4fc824f94f
commit
67a93fff5b
@ -1,9 +1,9 @@
|
||||
package ca.recrown.islandsurvivalcraft;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import ca.recrown.islandsurvivalcraft.worldgeneration.BiomePerIslandGenerator;
|
||||
import ca.recrown.islandsurvivalcraft.worldgeneration.IslandSurvivalCraftWorldGenerator;
|
||||
|
||||
public class IslandSurvivalCraft extends JavaPlugin {
|
||||
@ -11,6 +11,8 @@ public class IslandSurvivalCraft extends JavaPlugin {
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
generator = new IslandSurvivalCraftWorldGenerator(new BiomePerIslandGenerator());
|
||||
generator.initialize();
|
||||
super.onEnable();
|
||||
}
|
||||
|
||||
@ -21,10 +23,6 @@ public class IslandSurvivalCraft extends JavaPlugin {
|
||||
|
||||
@Override
|
||||
public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) {
|
||||
if (generator == null) {
|
||||
World world = getServer().getWorld(worldName);
|
||||
generator = new IslandSurvivalCraftWorldGenerator(this, world, true);
|
||||
}
|
||||
return generator;
|
||||
}
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ public class DepthFirstSearch {
|
||||
* @param targetValidator
|
||||
* @return
|
||||
*/
|
||||
public boolean findEndNode(CoordinateTargetValidatable targetValidator) {
|
||||
public boolean findTarget(CoordinateTargetValidatable targetValidator) {
|
||||
queue = new LinkedList<>();
|
||||
checkedNodes.clear();
|
||||
Node begin = startNode;
|
||||
|
@ -5,10 +5,14 @@ import java.util.Random;
|
||||
import org.bukkit.util.noise.SimplexOctaveGenerator;
|
||||
|
||||
public class BedrockGenerator {
|
||||
private Random random;
|
||||
private SimplexOctaveGenerator noiseGenerator;
|
||||
private final int maxBedrockHeight = 5;
|
||||
private final int minBedrockHeight = 1;
|
||||
public BedrockGenerator(Random random) {
|
||||
|
||||
public void setRandom(Random random) {
|
||||
if (random.equals(this.random)) return;
|
||||
this.random = random;
|
||||
noiseGenerator = new SimplexOctaveGenerator(random, 8);
|
||||
noiseGenerator.setScale(0.1D);
|
||||
}
|
||||
|
@ -1,157 +1,85 @@
|
||||
package ca.recrown.islandsurvivalcraft.worldgeneration;
|
||||
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Biome;
|
||||
import org.bukkit.generator.ChunkGenerator.BiomeGrid;
|
||||
|
||||
import ca.recrown.islandsurvivalcraft.islandbedrockmetadata.IslandMetadataType;
|
||||
import ca.recrown.islandsurvivalcraft.islandbedrockmetadata.IslandOwnerMetadata;
|
||||
import ca.recrown.islandsurvivalcraft.islandbedrockmetadata.IslandShoreBiomeMetadata;
|
||||
import ca.recrown.islandsurvivalcraft.islandbedrockmetadata.IslandTUIDMetadata;
|
||||
import ca.recrown.islandsurvivalcraft.islandbedrockmetadata.IslandTemperatureMetadata;
|
||||
import ca.recrown.islandsurvivalcraft.pathfinding.CoordinateTargetValidatable;
|
||||
import ca.recrown.islandsurvivalcraft.IslandSurvivalCraft;
|
||||
import ca.recrown.islandsurvivalcraft.islandbedrockmetadata.IslandBedrockMetadataHelper;
|
||||
import ca.recrown.islandsurvivalcraft.islandbedrockmetadata.IslandMainBiomeMetadata;
|
||||
import ca.recrown.islandsurvivalcraft.islandbedrockmetadata.IslandMetadataPack;
|
||||
import ca.recrown.islandsurvivalcraft.pathfinding.DepthFirstSearch;
|
||||
|
||||
public class BiomePerIslandGenerator implements IslandBiomeGenerator, CoordinateTargetValidatable {
|
||||
private IslandMapGenerator mapGenerator;
|
||||
private Biome currentIslandBiome;
|
||||
private float currentIslandTemperature;
|
||||
private Biome currentIslandShoreBiome;
|
||||
private IslandMapGenerator islandMapGenerator;
|
||||
private BiomeSelector biomeSelector;
|
||||
private int worldHeight;
|
||||
private World world;
|
||||
private IslandBedrockMetadataHelper metadataHelper;
|
||||
private TemperatureMapGenerator temperatureMapGenerator;
|
||||
private String currentTUID;
|
||||
private IslandSurvivalCraft plugin;
|
||||
private int buildHeight;
|
||||
private World world;
|
||||
private DepthFirstSearch dfs;
|
||||
private Biome mainBiome;
|
||||
private Biome shoreBiome;
|
||||
private float temperature;
|
||||
|
||||
public BiomePerIslandGenerator(IslandSurvivalCraft plugin, World world, IslandMapGenerator mapGenerator, BiomeSelector biomeSelector, TemperatureMapGenerator temperatureMapGenerator) {
|
||||
this.plugin = plugin;
|
||||
this.temperatureMapGenerator = temperatureMapGenerator;
|
||||
this.worldHeight = world.getMaxHeight();
|
||||
this.mapGenerator = mapGenerator;
|
||||
public BiomePerIslandGenerator() {
|
||||
this.temperatureMapGenerator = new TemperatureMapGenerator();
|
||||
dfs = new DepthFirstSearch(islandMapGenerator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(IslandMapGenerator mapGenerator, BiomeSelector biomeSelector) {
|
||||
this.islandMapGenerator = mapGenerator;
|
||||
this.biomeSelector = biomeSelector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWorld(World world) {
|
||||
if (world.equals(this.world)) return;
|
||||
this.world = world;
|
||||
this.metadataHelper = new IslandBedrockMetadataHelper(plugin, world);
|
||||
}
|
||||
|
||||
public void GenerateBiome(int chunkX, int chunkZ, int localX, int localZ, BiomeGrid biome) {
|
||||
int worldX = chunkX * 16 + localX;
|
||||
int worldZ = chunkZ * 16 + localZ;
|
||||
|
||||
if (mapGenerator.isIsland(worldX, worldZ)) {
|
||||
IslandMetadataPack sameIslandPack = getSurroundingIslandData(worldX, worldZ);
|
||||
if (sameIslandPack != null) {
|
||||
//Old island
|
||||
currentIslandBiome = sameIslandPack.mainBiomeMetadata.getMainBiome();
|
||||
currentIslandShoreBiome = sameIslandPack.shoreBiomeMetadata.getShoreBiome();
|
||||
currentIslandTemperature = sameIslandPack.temperatureMetadata.getTemperature();
|
||||
currentTUID = sameIslandPack.islandTIUDMetadata.getIUID();
|
||||
} else {
|
||||
|
||||
|
||||
//New island
|
||||
currentIslandTemperature = temperatureMapGenerator.getTemperature(worldX, worldZ);
|
||||
currentIslandBiome = biomeSelector.getLandBiome(currentIslandTemperature);
|
||||
currentIslandShoreBiome = biomeSelector.getShoreBiome(currentIslandBiome, currentIslandTemperature);
|
||||
if (currentIslandShoreBiome == null) {
|
||||
currentIslandShoreBiome = currentIslandBiome;
|
||||
}
|
||||
currentTUID = String.valueOf(worldX) + String.valueOf(worldZ);
|
||||
}
|
||||
//saving information
|
||||
IslandMetadataPack current = new IslandMetadataPack();
|
||||
current.setMainBiome(currentIslandBiome, plugin);
|
||||
current.setTemperature(currentIslandTemperature, plugin);
|
||||
current.setShoreBiome(currentIslandShoreBiome, plugin);
|
||||
current.setTUID(currentTUID, plugin);
|
||||
metadataHelper.setIslandBedrockMetadataPack(worldX, worldZ, current);
|
||||
|
||||
//Set the biome information for the chunk
|
||||
if (mapGenerator.isShore(worldX, worldZ)) {
|
||||
setBiome(localX, localZ, biome, currentIslandShoreBiome);
|
||||
} else {
|
||||
setBiome(localX, localZ, biome, currentIslandBiome);
|
||||
}
|
||||
|
||||
//Check if island besides this one need to be generated.
|
||||
if (localX == 0 && mapGenerator.isSameIsland(worldX, worldZ, worldX - 1, worldZ)) {
|
||||
if (!world.isChunkGenerated(chunkX - 1, chunkZ)) {
|
||||
Chunk chunk = world.getChunkAt(chunkX - 1, chunkZ);
|
||||
chunk.load(true);
|
||||
chunk.unload(true);
|
||||
}
|
||||
} else if (localX == 15 && mapGenerator.isSameIsland(worldX, worldZ, worldX + 1, worldZ)) {
|
||||
if (!world.isChunkGenerated(chunkX + 1, chunkZ)) {
|
||||
Chunk chunk = world.getChunkAt(chunkX + 1, chunkZ);
|
||||
chunk.load(true);
|
||||
chunk.unload(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (localZ == 0 && mapGenerator.isSameIsland(worldX, worldZ, worldX, worldZ - 1)) {
|
||||
if (!world.isChunkGenerated(chunkX, chunkZ - 1)) {
|
||||
Chunk chunk = world.getChunkAt(chunkX, chunkZ - 1);
|
||||
chunk.load(true);
|
||||
chunk.unload(true);
|
||||
}
|
||||
} else if (localZ == 15 && mapGenerator.isSameIsland(worldX, worldZ, worldX, worldZ + 1)) {
|
||||
if (!world.isChunkGenerated(chunkX, chunkZ + 1)) {
|
||||
Chunk chunk = world.getChunkAt(chunkX, chunkZ + 1);
|
||||
chunk.load(true);
|
||||
chunk.unload(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private IslandMetadataPack getSurroundingIslandData(int worldX, int worldZ) {
|
||||
IslandMetadataPack data = null;
|
||||
if (mapGenerator.isSameIsland(worldX, worldZ, worldX + 1, worldZ)) {
|
||||
data = getMetadataPackAt(worldX + 1, worldZ, world);
|
||||
|
||||
} else if (mapGenerator.isSameIsland(worldX, worldZ, worldX - 1, worldZ)) {
|
||||
data = getMetadataPackAt(worldX - 1, worldZ, world);
|
||||
|
||||
} else if (mapGenerator.isSameIsland(worldX, worldZ, worldX, worldZ + 1)) {
|
||||
data = getMetadataPackAt(worldX, worldZ + 1, world);
|
||||
|
||||
} else if (mapGenerator.isSameIsland(worldX, worldZ, worldX, worldZ - 1)) {
|
||||
data = getMetadataPackAt(worldX, worldZ - 1, world);
|
||||
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
private IslandMetadataPack getMetadataPackAt(int worldX, int worldZ, World world) {
|
||||
IslandMetadataPack data = new IslandMetadataPack();
|
||||
data.mainBiomeMetadata = (IslandMainBiomeMetadata) metadataHelper.getIslandBedrockMetadata(worldX, worldZ,
|
||||
IslandMetadataType.mainBiome);
|
||||
data.shoreBiomeMetadata = (IslandShoreBiomeMetadata) metadataHelper.getIslandBedrockMetadata(worldX, worldZ,
|
||||
IslandMetadataType.shoreBiome);
|
||||
data.temperatureMetadata = (IslandTemperatureMetadata) metadataHelper.getIslandBedrockMetadata(worldX, worldZ,
|
||||
IslandMetadataType.temperature);
|
||||
data.ownerMetadata = (IslandOwnerMetadata) metadataHelper.getIslandBedrockMetadata(worldX, worldZ,
|
||||
IslandMetadataType.ownerUUID);
|
||||
data.islandTIUDMetadata = (IslandTUIDMetadata) metadataHelper.getIslandBedrockMetadata(worldX, worldZ,
|
||||
IslandMetadataType.TIUD);
|
||||
return data;
|
||||
}
|
||||
|
||||
private void setBiome(int localX, int localZ, BiomeGrid biomeGrid, Biome biome) {
|
||||
for (int y = 0; y < worldHeight; y++) {
|
||||
biomeGrid.setBiome(localX, y, localZ, biome);
|
||||
}
|
||||
this.temperatureMapGenerator.setSeed(world.getSeed());
|
||||
this.buildHeight = world.getMaxHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCoordinateTarget(int x, int y) {
|
||||
|
||||
if (world.isChunkGenerated(x/16, y/16)) {
|
||||
Biome foundBiome = world.getBiome(x, 0, y);
|
||||
if (islandMapGenerator.isShore(x, y)) {
|
||||
shoreBiome = foundBiome;
|
||||
} else {
|
||||
mainBiome = foundBiome;
|
||||
}
|
||||
if (mainBiome != null && shoreBiome != null) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void GenerateBiome(int chunkX, int chunkZ, int localX, int localZ, BiomeGrid biome) {
|
||||
int worldX = chunkX * 16 + localX;
|
||||
int worldZ = chunkZ * 16 + localZ;
|
||||
|
||||
if (islandMapGenerator.isIsland(worldX, worldZ)) {
|
||||
if (mainBiome == null && shoreBiome == null) {
|
||||
if (!dfs.findTarget(this)) {
|
||||
temperature = temperatureMapGenerator.getTemperature(worldX, worldZ);
|
||||
mainBiome = biomeSelector.getLandBiome(temperature);
|
||||
shoreBiome = biomeSelector.getShoreBiome(mainBiome, temperature);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
mainBiome = null;
|
||||
shoreBiome = null;
|
||||
}
|
||||
for (int y = 0; y < buildHeight; y++) {
|
||||
Biome designatedBiome = mainBiome;
|
||||
if (mainBiome == null) {
|
||||
designatedBiome = Biome.OCEAN;
|
||||
} else if (islandMapGenerator.isShore(worldX, worldZ)) {
|
||||
designatedBiome = shoreBiome;
|
||||
}
|
||||
|
||||
biome.setBiome(localX, y, localZ, designatedBiome);
|
||||
}
|
||||
}
|
||||
}
|
@ -11,7 +11,7 @@ import ca.recrown.islandsurvivalcraft.Utilities;
|
||||
|
||||
public class BiomeSelector {
|
||||
private boolean initialized = false;
|
||||
private final Random random;
|
||||
private Random random;
|
||||
private final HashMap<Biome, Float> lands;
|
||||
private HashMap<Float, ArrayList<Biome>> temperaturesForLand;
|
||||
private final HashMap<Float, ArrayList<Biome>> temperaturePartitionedLandBiomes;
|
||||
@ -20,9 +20,7 @@ public class BiomeSelector {
|
||||
private final HashMap<Float, ArrayList<Biome>> temperaturePartitionedOceanBiomes;
|
||||
|
||||
|
||||
public BiomeSelector(Random random) {
|
||||
this.random = random;
|
||||
|
||||
public BiomeSelector() {
|
||||
lands = new HashMap<>();
|
||||
oceans = new HashMap<>();
|
||||
temperaturePartitionedLandBiomes = new HashMap<>();
|
||||
@ -35,6 +33,10 @@ public class BiomeSelector {
|
||||
temperaturePartitionedOceanBiomes.put(0.5f, new ArrayList<>());
|
||||
}
|
||||
|
||||
public void setRandom(Random random) {
|
||||
this.random = random;
|
||||
}
|
||||
|
||||
public void initialize() {
|
||||
if (initialized) throw new IllegalStateException("Biome selector is already initialized.");
|
||||
|
||||
|
@ -1,8 +1,10 @@
|
||||
package ca.recrown.islandsurvivalcraft.worldgeneration;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.generator.ChunkGenerator.BiomeGrid;
|
||||
|
||||
public interface IslandBiomeGenerator {
|
||||
|
||||
public void initialize(IslandMapGenerator mapGenerator, BiomeSelector biome);
|
||||
public void setWorld(World world);
|
||||
public void GenerateBiome(int chunkX, int chunkZ, int localX, int localZ, BiomeGrid biome);
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import ca.recrown.islandsurvivalcraft.pathfinding.CoordinateValidatable;
|
||||
import ca.recrown.islandsurvivalcraft.pathfinding.DepthFirstSearch;
|
||||
|
||||
public class IslandMapGenerator implements CoordinateValidatable {
|
||||
private Random random;
|
||||
private SimplexOctaveGenerator noiseGenerator;
|
||||
private final int noiseOctaves = 8;
|
||||
private final int islandGenerationPercent = 47;
|
||||
@ -17,16 +18,23 @@ public class IslandMapGenerator implements CoordinateValidatable {
|
||||
private final float shoreFactor = 0.065f;
|
||||
private final int maxHeightAboveSea = 8;
|
||||
private final int lowestSeaFloor = 16;
|
||||
private final int seaLevel;
|
||||
private final int shallowDepth;
|
||||
private int seaLevel;
|
||||
private int shallowDepth;
|
||||
private final DepthFirstSearch dfs;
|
||||
|
||||
public IslandMapGenerator(Random random, int seaLevel, int shallowDepth) {
|
||||
public IslandMapGenerator() {
|
||||
dfs = new DepthFirstSearch(this);
|
||||
}
|
||||
|
||||
this.noiseGenerator = new SimplexOctaveGenerator(random, noiseOctaves);
|
||||
public void updateParameters(Random random, int seaLevel, int shallowDepth) {
|
||||
this.seaLevel = seaLevel;
|
||||
this.shallowDepth = shallowDepth;
|
||||
if (!random.equals(this.random)) {
|
||||
this.random = random;
|
||||
this.noiseGenerator = new SimplexOctaveGenerator(random, noiseOctaves);
|
||||
}
|
||||
this.seaLevel = seaLevel;
|
||||
this.shallowDepth = shallowDepth;
|
||||
dfs = new DepthFirstSearch(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -59,7 +67,7 @@ public class IslandMapGenerator implements CoordinateValidatable {
|
||||
/**
|
||||
* These coordinates are considered to be the shore if:
|
||||
* It is a part of an island,
|
||||
* within a square radius of shoreSize, there is an edge of the island.
|
||||
* the island value is less than the shore factor.
|
||||
* @param worldX the X coordinate of location in world.
|
||||
* @param worldZ the Z coordinate of location in world.
|
||||
* @return
|
||||
|
@ -2,37 +2,35 @@ package ca.recrown.islandsurvivalcraft.worldgeneration;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import org.apache.commons.lang.NotImplementedException;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
|
||||
import ca.recrown.islandsurvivalcraft.IslandSurvivalCraft;
|
||||
|
||||
public class IslandSurvivalCraftWorldGenerator extends ChunkGenerator {
|
||||
private final BedrockGenerator bedrockGenerator;
|
||||
private final BiomeSelector biomeSelector;
|
||||
private final IslandBiomeGenerator biomeGenerator;
|
||||
private final IslandMapGenerator islandMapGenerator;
|
||||
private final TemperatureMapGenerator temperatureMapGenerator;
|
||||
private final BedrockGenerator bedrockGenerator;
|
||||
private final Random random;
|
||||
|
||||
public IslandSurvivalCraftWorldGenerator(IslandSurvivalCraft plugin, World world, boolean biomePerIsland) {
|
||||
random = new Random(world.getSeed());
|
||||
this.biomeSelector = new BiomeSelector(random);
|
||||
this.bedrockGenerator = new BedrockGenerator(random);
|
||||
this.islandMapGenerator = new IslandMapGenerator(random, world.getSeaLevel(), 3);
|
||||
this.temperatureMapGenerator = new TemperatureMapGenerator(world.getSeed());
|
||||
if (biomePerIsland) {
|
||||
this.biomeGenerator = new BiomePerIslandGenerator(plugin, world, islandMapGenerator, biomeSelector, temperatureMapGenerator);
|
||||
} else {
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
public IslandSurvivalCraftWorldGenerator(IslandBiomeGenerator generator) {
|
||||
this.biomeSelector = new BiomeSelector();
|
||||
this.bedrockGenerator = new BedrockGenerator();
|
||||
this.islandMapGenerator = new IslandMapGenerator();
|
||||
this.biomeGenerator = generator;
|
||||
}
|
||||
|
||||
public void initialize() {
|
||||
biomeSelector.initialize();
|
||||
biomeGenerator.initialize(islandMapGenerator, biomeSelector);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkData generateChunkData(World world, Random random, int x, int z, BiomeGrid biome) {
|
||||
bedrockGenerator.setRandom(random);
|
||||
biomeSelector.setRandom(random);
|
||||
biomeGenerator.setWorld(world);
|
||||
islandMapGenerator.updateParameters(random, world.getSeaLevel(), 4);
|
||||
|
||||
ChunkData chunk = createChunkData(world);
|
||||
for (int localX = 0; localX < 16; localX++) {
|
||||
for (int localZ = 0; localZ < 16; localZ++) {
|
||||
|
@ -9,7 +9,8 @@ class TemperatureMapGenerator {
|
||||
private final double amplitude = 0.22D;
|
||||
|
||||
private SimplexOctaveGenerator noiseGenerator;
|
||||
public TemperatureMapGenerator(long seed) {
|
||||
|
||||
public void setSeed(long seed) {
|
||||
noiseGenerator = new SimplexOctaveGenerator(new Random(seed), 4);
|
||||
noiseGenerator.setScale(0.0008D);
|
||||
}
|
||||
|
@ -131,7 +131,7 @@ public class DepthFirstSearchTest {
|
||||
dfs.setValidatable(validator);
|
||||
dfs.setStartPosition(3, 0);
|
||||
|
||||
assertTrue(dfs.findEndNode(validator));
|
||||
assertTrue(dfs.findTarget(validator));
|
||||
assertEquals(1, dfs.getEndX());
|
||||
assertEquals(2, dfs.getEndY());
|
||||
}
|
||||
@ -142,7 +142,7 @@ public class DepthFirstSearchTest {
|
||||
dfs.setValidatable(validator);
|
||||
dfs.setStartPosition(0, 0);
|
||||
|
||||
assertTrue(dfs.findEndNode(validator));
|
||||
assertTrue(dfs.findTarget(validator));
|
||||
assertEquals(0, dfs.getEndX());
|
||||
assertEquals(3, dfs.getEndY());
|
||||
}
|
||||
@ -153,6 +153,6 @@ public class DepthFirstSearchTest {
|
||||
dfs.setValidatable(validator);
|
||||
dfs.setStartPosition(0, 0);
|
||||
|
||||
assertFalse(dfs.findEndNode(validator));
|
||||
assertFalse(dfs.findTarget(validator));
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,8 @@ public class BiomeSelectorTest {
|
||||
@BeforeAll
|
||||
public void setUp() {
|
||||
|
||||
biomeSelector = new BiomeSelector(new Random());
|
||||
biomeSelector = new BiomeSelector();
|
||||
biomeSelector.setRandom(new Random());
|
||||
biomeSelector.initialize();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user