Chunk generation now generates sea and island.

Adjusted values for the island mapper.
Island world mapper now takes a seed instead of a random object.
Refactoring of method names.

Reduced cache sizes used by terrain generation.

Reworked height shader to not use it's own noise generator.

Updated tests implementing changes respectively.
This commit is contained in:
Harrison Deng 2020-04-30 21:42:03 -05:00
parent d0701ce63d
commit e4597538b2
5 changed files with 173 additions and 84 deletions

View File

@ -13,20 +13,20 @@ public class IslandWorldMapper implements CoordinateValidatable {
private final Cache<Point2, Double> blockValueCache; private final Cache<Point2, Double> blockValueCache;
private final SimplexOctaveGenerator noiseGenerator; private final SimplexOctaveGenerator noiseGenerator;
private final int noiseOctaves = 4; private final int noiseOctaves = 8;
private final float islandBlockGenerationPercent = 16; private final float islandBlockGenerationPercent = 10;
private final float exaggerationFactor = 1.2f; private final float exaggerationFactor = 1f;
private final float islandValueExaggerationFactor = 0.2f; private final float islandExaggeration = 1.6f;
private final double noiseFrequency = 1.95D; private final double noiseFrequency = 1.8D;
private final double noiseAmplitude = 0.5D; private final double noiseAmplitude = 0.5D;
private final double scale = 0.03D; private final double scale = 0.01D;
private final float shoreFactor = 0.035f; private final float shoreFactor = 0.035f;
private final float shallowPortion = 0.015f; private final float shallowPortion = 0.015f;
private final DepthFirstSearch dfs; private final DepthFirstSearch dfs;
public IslandWorldMapper(Random random, Cache<Point2, Double> blockValueCache) { public IslandWorldMapper(long seed, Cache<Point2, Double> blockValueCache) {
dfs = new DepthFirstSearch(this); dfs = new DepthFirstSearch(this);
this.noiseGenerator = new SimplexOctaveGenerator(random, noiseOctaves); this.noiseGenerator = new SimplexOctaveGenerator(new Random(seed), noiseOctaves);
noiseGenerator.setScale(scale); noiseGenerator.setScale(scale);
this.blockValueCache = blockValueCache; this.blockValueCache = blockValueCache;
} }
@ -38,7 +38,7 @@ public class IslandWorldMapper implements CoordinateValidatable {
* @return * @return
*/ */
public boolean isLand(int worldX, int worldZ) { public boolean isLand(int worldX, int worldZ) {
if (getWorldBlockValue(worldX, worldZ) >= 0) { if (getWorldValue(worldX, worldZ) >= 0) {
return true; return true;
} }
return false; return false;
@ -68,7 +68,7 @@ public class IslandWorldMapper implements CoordinateValidatable {
*/ */
public boolean isShore(int worldX, int worldZ) { public boolean isShore(int worldX, int worldZ) {
if (!isIsland(worldX, worldZ)) return false; if (!isIsland(worldX, worldZ)) return false;
if (isLand(worldX, worldZ) && getWorldBlockValue(worldX, worldZ) <= shoreFactor) { if (isLand(worldX, worldZ) && getWorldValue(worldX, worldZ) <= shoreFactor) {
return true; return true;
} }
return false; return false;
@ -95,7 +95,7 @@ public class IslandWorldMapper implements CoordinateValidatable {
* @return true if it is considered the shallow portion. * @return true if it is considered the shallow portion.
*/ */
public boolean isShallowPortion(int worldX, int worldZ) { public boolean isShallowPortion(int worldX, int worldZ) {
if (!isLand(worldX, worldZ) && getWorldBlockValue(worldX, worldZ) >= -shallowPortion) { if (!isLand(worldX, worldZ) && getWorldValue(worldX, worldZ) >= -shallowPortion) {
return true; return true;
} }
return false; return false;
@ -106,24 +106,24 @@ public class IslandWorldMapper implements CoordinateValidatable {
* World block value will be 0 or positive if it is a part of an island. * World block value will be 0 or positive if it is a part of an island.
* If less than, it is considered under the sea. * If less than, it is considered under the sea.
* Does not factor in a shallow depth. * Does not factor in a shallow depth.
* The value is normalized to [0, 1]. * The value is normalized to [-1, 1].
* @param worldX the x world coordinate to obtain this value for. * @param worldX the x world coordinate to obtain this value for.
* @param worldZ the z world coordinate to obtain this value for. * @param worldZ the z world coordinate to obtain this value for.
* @return a value representing the island at the given point. * @return a value representing the island at the given point.
*/ */
public double getWorldBlockValue(int worldX, int worldZ) { public double getWorldValue(int worldX, int worldZ) {
Point2 p = new Point2(worldX, worldZ); Point2 p = new Point2(worldX, worldZ);
Double res = blockValueCache.get(p); Double res = blockValueCache.get(p);
if (res == null) { if (res == null) {
double portionSea = 1f - (this.islandBlockGenerationPercent / 100f); double portionSea = 1f - (this.islandBlockGenerationPercent / 100f);
double shift = 1f - 2 * portionSea; double shift = (portionSea - 1d) / 2d;
double rawNoise = noiseGenerator.noise(worldX, worldZ, noiseFrequency, noiseAmplitude, true); double rawNoise = noiseGenerator.noise(worldX, worldZ, noiseFrequency, noiseAmplitude, true);
double noise = 0; double noise = 0;
if (rawNoise < 0) { if (rawNoise < 0) {
noise = ( - Math.pow(- rawNoise, exaggerationFactor) + shift); noise = ( - Math.pow(- rawNoise, exaggerationFactor) + shift);
} else { } else {
noise = Math.pow(rawNoise, islandValueExaggerationFactor) + shift; noise = Math.pow(rawNoise, islandExaggeration) + shift;
} }
double maxNeg = -1 + shift; double maxNeg = -1 + shift;
double maxPos = 1 + shift; double maxPos = 1 + shift;

View File

@ -7,6 +7,7 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
@ -24,9 +25,9 @@ import ca.recrown.islandsurvivalcraft.world.IslandWorldMapper;
import ca.recrown.islandsurvivalcraft.world.shaders.WorldHeightShader; import ca.recrown.islandsurvivalcraft.world.shaders.WorldHeightShader;
public class IslandWorldChunkGenerator extends ChunkGenerator implements Listener { public class IslandWorldChunkGenerator extends ChunkGenerator implements Listener {
private final Cache<Point2, Double> blockValueCache = new Cache<>(262144); private final Cache<Point2, Double> blockValueCache = new Cache<>(131072);
private final Cache<Point2, Biome[]> biomeCache = new Cache<>(262144); private final Cache<Point2, Biome[]> biomeCache = new Cache<>(131072);
private final Cache<Point2, Boolean> chunkExistenceCache = new Cache<>(32768); private final Cache<Point2, Boolean> chunkExistenceCache = new Cache<>(131072);
private final BiomeSelector biomeSelector = new BiomeSelector(); private final BiomeSelector biomeSelector = new BiomeSelector();
private final ExecutorService exAlpha = Utilities.ISC_EXECUTOR_ALPHA; private final ExecutorService exAlpha = Utilities.ISC_EXECUTOR_ALPHA;
private final ExecutorService exBeta = Utilities.ISC_EXECUTOR_BETA; private final ExecutorService exBeta = Utilities.ISC_EXECUTOR_BETA;
@ -39,19 +40,21 @@ public class IslandWorldChunkGenerator extends ChunkGenerator implements Listene
@Override @Override
public ChunkData generateChunkData(World world, Random random, int chunkX, int chunkZ, BiomeGrid biomeGrid) { public ChunkData generateChunkData(World world, Random random, int chunkX, int chunkZ, BiomeGrid biomeGrid) {
this.currentWorld = world; this.currentWorld = world;
IslandWorldMapper mapper = new IslandWorldMapper(random, blockValueCache); long seed = world.getSeed();
TemperatureMapGenerator temperatureMapGenerator = new TemperatureMapGenerator(world.getSeed()); IslandWorldMapper mapper = new IslandWorldMapper(seed, blockValueCache);
WorldHeightShader heightShader = new WorldHeightShader(random, mapper, world.getSeaLevel(), world.getMaxHeight(), 3); TemperatureMapGenerator temperatureMapGenerator = new TemperatureMapGenerator(seed);
WorldHeightShader heightShader = new WorldHeightShader(mapper, world.getSeaLevel(), world.getMaxHeight(), 3);
BiomeGenerator biomeGenerator = new UniBiomeIslandGenerator(); BiomeGenerator biomeGenerator = new UniBiomeIslandGenerator();
int maxHeight = world.getMaxHeight(); int maxHeight = world.getMaxHeight();
int seaLevel = world.getSeaLevel();
LinkedList<Future<Boolean>> tasks = new LinkedList<>(); LinkedList<Future<Boolean>> tasks = new LinkedList<>();
ChunkData chunkData = createChunkData(world); ChunkData chunkData = createChunkData(world);
Future<Boolean> preLoader = exAlpha.submit(() -> { Future<Boolean> preLoader = exAlpha.submit(() -> {
for (int x = Utilities.CHUNK_SIZE - 1; x >= 0; x--) { for (int x = Utilities.CHUNK_SIZE - 1; x >= 0; x--) {
for (int z = Utilities.CHUNK_SIZE - 1; z >= 0; z--) { for (int z = Utilities.CHUNK_SIZE - 1; z >= 0; z--) {
if (Thread.currentThread().isInterrupted()) return false; if (Thread.currentThread().isInterrupted()) return false;
mapper.getWorldBlockValue(Utilities.CHUNK_SIZE * chunkX + x, Utilities.CHUNK_SIZE * chunkZ + z); mapper.getWorldValue(Utilities.CHUNK_SIZE * chunkX + x, Utilities.CHUNK_SIZE * chunkZ + z);
} }
} }
return true; return true;
@ -76,11 +79,15 @@ public class IslandWorldChunkGenerator extends ChunkGenerator implements Listene
final int worldX = Utilities.CHUNK_SIZE * chunkX + localX; final int worldX = Utilities.CHUNK_SIZE * chunkX + localX;
final int worldZ = Utilities.CHUNK_SIZE * chunkZ + localZ; final int worldZ = Utilities.CHUNK_SIZE * chunkZ + localZ;
int height = heightShader.getAltitude(worldX, worldZ, biomes[localX][localZ]); int terrainHeight = heightShader.getTerrainHeight(worldX, worldZ, biomes[localX][localZ]);
chunkData.setRegion(localX, 1, localZ, localX + 1, height, localZ + 1, Material.DIAMOND_BLOCK); int bedrockHeight = random.nextInt(5);
chunkData.setRegion(localX, bedrockHeight, localZ, localX + 1, terrainHeight, localZ + 1, Material.STONE);
if (terrainHeight < seaLevel) {
chunkData.setRegion(localX, terrainHeight, localZ, localX + 1, seaLevel, localZ + 1, Material.WATER);
}
chunkData.setRegion(localX, 0, localZ, localX + 1, bedrockHeight, localZ + 1, Material.BEDROCK);
} }
} }
chunkData.setRegion(0, 0, 0, 16, 1, 16, Material.BEDROCK);
preLoader.cancel(false); preLoader.cancel(false);
try { try {
@ -93,12 +100,14 @@ public class IslandWorldChunkGenerator extends ChunkGenerator implements Listene
} }
return chunkData; return chunkData;
} }
@Override @Override
public boolean canSpawn(World world, int x, int z) { public Location getFixedSpawnLocation(World world, Random random) {
return super.canSpawn(world, x, z); Location location = new Location(world, 0, 128, 0);
return location;
} }
@Override @Override
public boolean isParallelCapable() { public boolean isParallelCapable() {
return true; return true;

View File

@ -1,79 +1,52 @@
package ca.recrown.islandsurvivalcraft.world.shaders; package ca.recrown.islandsurvivalcraft.world.shaders;
import java.util.Random;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import org.bukkit.util.noise.SimplexOctaveGenerator;
import ca.recrown.islandsurvivalcraft.world.IslandWorldMapper; import ca.recrown.islandsurvivalcraft.world.IslandWorldMapper;
public class WorldHeightShader { public class WorldHeightShader {
private final SimplexOctaveGenerator noiseGenerator;
private final IslandWorldMapper islandLocator; private final IslandWorldMapper islandLocator;
private final int seaLevel; private final int seaLevel;
private final int worldHeight; private final int worldHeight;
private final int minimumHeight; private final int minimumHeight;
private final float probabilityOfAdditive = 0.75f;
public WorldHeightShader(Random random, IslandWorldMapper islandLocator, int seaLevel, int worldHeight, int minimumHeight) { public WorldHeightShader(IslandWorldMapper islandLocator, int seaLevel, int worldHeight, int minimumHeight) {
noiseGenerator = new SimplexOctaveGenerator(random, 2);
noiseGenerator.setScale(0.075D);
this.islandLocator = islandLocator; this.islandLocator = islandLocator;
this.seaLevel = seaLevel; this.seaLevel = seaLevel;
this.worldHeight = worldHeight; this.worldHeight = worldHeight;
this.minimumHeight = minimumHeight; this.minimumHeight = minimumHeight;
} }
public int getAltitude(int worldX, int worldZ, Biome biome) { public int getTerrainHeight(int worldX, int worldZ, Biome biome) {
double modifier = getHeightModifier(worldX, worldZ);
int baseValue = calculateTerrainHeight(worldX, worldZ);
int height = 0; int height = 0;
String biomeName = biome.name().toLowerCase(); String biomeName = biome.name().toLowerCase();
if (biomeName.contains("hills")) { if (biomeName.contains("hills")) {
height = (int) (modifier * 20D + baseValue); height = calculateTerrainHeight(worldX, worldZ, 15);
} else if (biomeName.contains("mountains")) { } else if (biomeName.contains("mountains")) {
height = (int) (modifier * 45D + baseValue); height = calculateTerrainHeight(worldX, worldZ, 30);
} else if (biomeName.contains("plateau")) { } else if (biomeName.contains("plateau")) {
height = (int) (Math.min(60, Math.max(2, modifier * 80D)) + baseValue); height = Math.min(calculateTerrainHeight(worldX, worldZ, 70), 40);
} else if (biomeName.contains("modified")) { } else if (biomeName.contains("modified")) {
height = (int) (modifier * 25D + baseValue); height = calculateTerrainHeight(worldX, worldZ, 45);
} else if (biomeName.contains("shattered")) { } else if (biomeName.contains("shattered")) {
height = (int) (modifier * 35D + baseValue); height = calculateTerrainHeight(worldX, worldZ, 60);
} else if (biomeName.contains("tall")) { } else if (biomeName.contains("tall")) {
height = (int) (modifier * 30D + baseValue); height = calculateTerrainHeight(worldX, worldZ, 45);
} else if (!biomeName.contains("ocean")) { } else if (!biomeName.contains("ocean")) {
height = (int) (getNormalizedHeightModifier(worldX, worldZ) * 15D + baseValue); height = calculateTerrainHeight(worldX, worldZ, 15);
} else { } else {
height = (int) (getNormalizedHeightModifier(worldX, worldZ) * 5D + baseValue); height = calculateTerrainHeight(worldX, worldZ, seaLevel);
} }
if (height > worldHeight) throw new IllegalStateException("Resulting height is greater than world height! Biome this occurred on: " + biomeName); if (height > worldHeight) throw new IllegalStateException("Resulting height is greater than world height! Biome this occurred on: " + biomeName);
height = Math.max(minimumHeight, height);
return height; return height;
} }
private int calculateTerrainHeight(int worldX, int worldZ) { private int calculateTerrainHeight(int worldX, int worldZ, int multiplier) {
double islandValue = islandLocator.getWorldBlockValue(worldX, worldZ) + 1D; int blockHeight = seaLevel;
islandValue *= worldHeight/4; double islandValue = islandLocator.getWorldValue(worldX, worldZ);
return (int) Math.max(Math.min(seaLevel, islandValue), minimumHeight); blockHeight += islandValue * multiplier;
} return blockHeight;
private double getHeightModifier(int worldX, int worldZ) {
return (2 * probabilityOfAdditive - noiseGenerator.noise(worldX, worldZ, 0.5D, 0.5D, true));
}
private double maxHeightModifier() {
return 2 * probabilityOfAdditive + 1;
}
private double minHeightModifier() {
return 2 * probabilityOfAdditive - 1;
}
private double getNormalizedHeightModifier(int worldX, int worldZ) {
double heightModifier = getHeightModifier(worldX, worldZ);
if (heightModifier > 0) {
return heightModifier / maxHeightModifier();
}
return - heightModifier / minHeightModifier();
} }
} }

View File

@ -19,14 +19,14 @@ public class IslandWorldMapperTest {
public final Cache<Point2, Double> blockValCache = new Cache<>(2048); public final Cache<Point2, Double> blockValCache = new Cache<>(2048);
public final int SEED = 102385923; public final int SEED = 102385923;
public Random random = new Random(SEED); public Random random = new Random(SEED);
public IslandWorldMapper mapper = new IslandWorldMapper(random, blockValCache); public IslandWorldMapper mapper = new IslandWorldMapper(SEED, blockValCache);
public final double[][] answers = new double[2048][2048]; public final double[][] answers = new double[2048][2048];
@BeforeAll @BeforeAll
public void setUp() { public void setUp() {
for (int x = 0; x < answers.length; x++) { for (int x = 0; x < answers.length; x++) {
for (int y = 0; y < answers[x].length; y++) { for (int y = 0; y < answers[x].length; y++) {
answers[x][y] = mapper.getWorldBlockValue(x, y); answers[x][y] = mapper.getWorldValue(x, y);
} }
} }
blockValCache.clearCache(); blockValCache.clearCache();
@ -40,14 +40,14 @@ public class IslandWorldMapperTest {
@BeforeEach @BeforeEach
public void individualSetUp() { public void individualSetUp() {
random = new Random(SEED); random = new Random(SEED);
mapper = new IslandWorldMapper(random, blockValCache); mapper = new IslandWorldMapper(SEED, blockValCache);
} }
@Test @Test
public void testBlockValueConsistency() { public void testBlockValueConsistency() {
for (int x = 0; x < answers.length; x++) { for (int x = 0; x < answers.length; x++) {
for (int y = 0; y < answers[x].length; y++) { for (int y = 0; y < answers[x].length; y++) {
assertEquals(answers[x][y], mapper.getWorldBlockValue(x, y), String.format("Occurred at (%d, %d)", x, y)); assertEquals(answers[x][y], mapper.getWorldValue(x, y), String.format("Occurred at (%d, %d)", x, y));
} }
} }
} }
@ -57,7 +57,7 @@ public class IslandWorldMapperTest {
for (int amount = 0; amount < 1024; amount++) { for (int amount = 0; amount < 1024; amount++) {
int x = random.nextInt(answers.length); int x = random.nextInt(answers.length);
int y = random.nextInt(answers[x].length); int y = random.nextInt(answers[x].length);
assertEquals(answers[x][y], mapper.getWorldBlockValue(x, y), String.format("Occurred at (%d, %d)", x, y)); assertEquals(answers[x][y], mapper.getWorldValue(x, y), String.format("Occurred at (%d, %d)", x, y));
} }
} }
} }

View File

@ -3,7 +3,6 @@ package ca.recrown.islandsurvivalcraft.world.generation;
import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertFalse;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.Random;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
@ -12,6 +11,7 @@ import java.util.concurrent.TimeUnit;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance; import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.Timeout; import org.junit.jupiter.api.Timeout;
@ -27,9 +27,9 @@ import ca.recrown.islandsurvivalcraft.world.IslandWorldMapper;
public class UniBiomeIslandGeneratorTest { public class UniBiomeIslandGeneratorTest {
private final int SEED = 249398015; private final int SEED = 249398015;
private final DummyWorld dummyWorld = new DummyWorld(); private final DummyWorld dummyWorld = new DummyWorld();
private final Cache<Point2, Double> blockValueCache = new Cache<>(524288); private volatile Cache<Point2, Double> blockValueCache;
private final Cache<Point2, Biome[]> biomeCache = new Cache<>(524288); private volatile Cache<Point2, Biome[]> biomeCache;
private final Cache<Point2, Boolean> chunkExistenceCache = new Cache<>(16384); private volatile Cache<Point2, Boolean> chunkExistenceCache;
private class BiomeGenTask implements Runnable { private class BiomeGenTask implements Runnable {
private final int amount; private final int amount;
@ -49,8 +49,7 @@ public class UniBiomeIslandGeneratorTest {
} }
public void generateBiome(int chunkX, int chunkZ) { public void generateBiome(int chunkX, int chunkZ) {
Random rand = new Random(SEED); IslandWorldMapper mapper = new IslandWorldMapper(SEED, blockValueCache);
IslandWorldMapper mapper = new IslandWorldMapper(rand, blockValueCache);
TemperatureMapGenerator temperatureMapGenerator = new TemperatureMapGenerator(SEED); TemperatureMapGenerator temperatureMapGenerator = new TemperatureMapGenerator(SEED);
BiomeSelector biomeSelector = new BiomeSelector(); BiomeSelector biomeSelector = new BiomeSelector();
biomeSelector.initialize(); biomeSelector.initialize();
@ -70,6 +69,13 @@ public class UniBiomeIslandGeneratorTest {
} }
} }
@BeforeEach
public void individualSetup() {
blockValueCache = new Cache<>(524288);
biomeCache = new Cache<>(524288);
chunkExistenceCache = new Cache<>(16384);
}
@AfterEach @AfterEach
public void individualCleanup() { public void individualCleanup() {
blockValueCache.clearCache(); blockValueCache.clearCache();
@ -107,6 +113,40 @@ public class UniBiomeIslandGeneratorTest {
} }
} }
@Test
@Timeout(value = 1, unit = TimeUnit.MINUTES)
public void testBiomeGenerationMultithread1608ChunksSmallCache() {
this.blockValueCache = new Cache<>(1024);
this.biomeCache = new Cache<>(1024);
this.chunkExistenceCache = new Cache<>(1024);
int chunksToDoEach = 268;
Runnable g1 = new BiomeGenTask(chunksToDoEach, 0);
Runnable g2 = new BiomeGenTask(chunksToDoEach, 1);
Runnable g3 = new BiomeGenTask(chunksToDoEach, 2);
Runnable g4 = new BiomeGenTask(chunksToDoEach, 3);
Runnable g5 = new BiomeGenTask(chunksToDoEach, 4);
Runnable g6 = new BiomeGenTask(chunksToDoEach, 5);
ExecutorService ex = Executors.newFixedThreadPool(6);
LinkedList<Future<?>> tasks = new LinkedList<>();
tasks.add(ex.submit(g1));
tasks.add(ex.submit(g2));
tasks.add(ex.submit(g3));
tasks.add(ex.submit(g4));
tasks.add(ex.submit(g5));
tasks.add(ex.submit(g6));
while (!tasks.isEmpty()) {
try {
tasks.pop().get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
assertFalse(false, e.getCause().getMessage());
}
}
}
@Test @Test
@Timeout(value = 1, unit = TimeUnit.MINUTES) @Timeout(value = 1, unit = TimeUnit.MINUTES)
public void testBiomeGenerationSingleThread1608Chunks() { public void testBiomeGenerationSingleThread1608Chunks() {
@ -146,8 +186,11 @@ public class UniBiomeIslandGeneratorTest {
@Test @Test
@Timeout(value = 1, unit = TimeUnit.MINUTES) @Timeout(value = 1, unit = TimeUnit.MINUTES)
public void testBiomeGenerationMultithread6000ChunksScatteredColumns() { public void testBiomeGenerationMultithread1608ChunksScatteredColumnsSmallCache() {
int chunksToDoEach = 1000; this.blockValueCache = new Cache<>(1024);
this.biomeCache = new Cache<>(1024);
this.chunkExistenceCache = new Cache<>(1024);
int chunksToDoEach = 268;
Runnable g1 = new BiomeGenTask(chunksToDoEach, 0); Runnable g1 = new BiomeGenTask(chunksToDoEach, 0);
Runnable g2 = new BiomeGenTask(chunksToDoEach, 2); Runnable g2 = new BiomeGenTask(chunksToDoEach, 2);
Runnable g3 = new BiomeGenTask(chunksToDoEach, 4); Runnable g3 = new BiomeGenTask(chunksToDoEach, 4);
@ -173,4 +216,68 @@ public class UniBiomeIslandGeneratorTest {
} }
} }
} }
@Test
@Timeout(value = 1, unit = TimeUnit.MINUTES)
public void testBiomeGenerationMultithread6000ChunksScatteredColumns() {
int chunksToDoEach = 1000;
Runnable g1 = new BiomeGenTask(chunksToDoEach, 0);
Runnable g2 = new BiomeGenTask(chunksToDoEach, 3);
Runnable g3 = new BiomeGenTask(chunksToDoEach, 6);
Runnable g4 = new BiomeGenTask(chunksToDoEach, 9);
Runnable g5 = new BiomeGenTask(chunksToDoEach, 12);
Runnable g6 = new BiomeGenTask(chunksToDoEach, 15);
ExecutorService ex = Executors.newFixedThreadPool(6);
LinkedList<Future<?>> tasks = new LinkedList<>();
tasks.add(ex.submit(g1));
tasks.add(ex.submit(g2));
tasks.add(ex.submit(g3));
tasks.add(ex.submit(g4));
tasks.add(ex.submit(g5));
tasks.add(ex.submit(g6));
while (!tasks.isEmpty()) {
try {
tasks.pop().get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
assertFalse(false, e.getCause().getMessage());
}
}
}
@Test
@Timeout(value = 1, unit = TimeUnit.MINUTES)
public void testBiomeGenerationMultithread6000ChunksScatteredColumnsSmallCache() {
this.blockValueCache = new Cache<>(1024);
this.biomeCache = new Cache<>(1024);
this.chunkExistenceCache = new Cache<>(1024);
int chunksToDoEach = 1000;
Runnable g1 = new BiomeGenTask(chunksToDoEach, 0);
Runnable g2 = new BiomeGenTask(chunksToDoEach, 3);
Runnable g3 = new BiomeGenTask(chunksToDoEach, 6);
Runnable g4 = new BiomeGenTask(chunksToDoEach, 9);
Runnable g5 = new BiomeGenTask(chunksToDoEach, 12);
Runnable g6 = new BiomeGenTask(chunksToDoEach, 15);
ExecutorService ex = Executors.newFixedThreadPool(6);
LinkedList<Future<?>> tasks = new LinkedList<>();
tasks.add(ex.submit(g1));
tasks.add(ex.submit(g2));
tasks.add(ex.submit(g3));
tasks.add(ex.submit(g4));
tasks.add(ex.submit(g5));
tasks.add(ex.submit(g6));
while (!tasks.isEmpty()) {
try {
tasks.pop().get();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
assertFalse(false, e.getCause().getMessage());
}
}
}
} }