This commit is contained in:
dags- 2020-01-16 21:33:41 +00:00
parent baeba9c98a
commit 93b7abff62
23 changed files with 120 additions and 136 deletions

3
.gitmodules vendored
View File

@ -4,3 +4,6 @@
[submodule "Noise2D"] [submodule "Noise2D"]
path = Noise2D path = Noise2D
url = https://github.com/TerraForged/Noise2D.git url = https://github.com/TerraForged/Noise2D.git
[submodule "TerraForgedMod"]
path = TerraForgedMod
url = https://github.com/dags-/TerraForgedMod.git

@ -1 +1 @@
Subproject commit 1fd2cd9f133c861c613edfb2d49fe1a801fe3366 Subproject commit 4083d609c0023744eef091e3f74ac871806b5565

View File

@ -1,7 +1,3 @@
plugins {
id "java"
}
repositories { repositories {
mavenCentral() mavenCentral()
jcenter() jcenter()
@ -15,4 +11,5 @@ dependencies {
jar { jar {
manifest { attributes "Main-Class": "com.terraforged.app.Main" } manifest { attributes "Main-Class": "com.terraforged.app.Main" }
from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
} }

View File

@ -1,5 +1,3 @@
apply plugin: "java"
dependencies { dependencies {
compile project(":Noise2D") compile project(":Noise2D")
} }

View File

@ -4,7 +4,5 @@ import com.terraforged.core.world.terrain.Terrain;
public interface Extent { public interface Extent {
Cell<Terrain> getCell(int x, int z);
void visit(int minX, int minZ, int maxX, int maxZ, Cell.Visitor<Terrain> visitor); void visit(int minX, int minZ, int maxX, int maxZ, Cell.Visitor<Terrain> visitor);
} }

View File

@ -1,8 +1,8 @@
package com.terraforged.core.cell; package com.terraforged.core.cell;
import me.dags.noise.Module;
import com.terraforged.core.util.concurrent.ObjectPool; import com.terraforged.core.util.concurrent.ObjectPool;
import com.terraforged.core.world.terrain.Terrain; import com.terraforged.core.world.terrain.Terrain;
import me.dags.noise.Module;
public interface Populator extends Module { public interface Populator extends Module {
@ -10,14 +10,11 @@ public interface Populator extends Module {
void tag(Cell<Terrain> cell, float x, float y); void tag(Cell<Terrain> cell, float x, float y);
@Override
default float getValue(float x, float z) { default float getValue(float x, float z) {
try (ObjectPool.Item<Cell<Terrain>> cell = Cell.pooled()) { try (ObjectPool.Item<Cell<Terrain>> cell = Cell.pooled()) {
return getValue(cell.getValue(), x, z); apply(cell.getValue(), x, z);
return cell.getValue().value;
} }
} }
default float getValue(Cell<Terrain> cell, float x, float z) {
apply(cell, x, z);
return cell.value;
}
} }

View File

@ -1,21 +1,29 @@
package com.terraforged.core.module; package com.terraforged.core.module;
import me.dags.noise.Module; import com.terraforged.core.cell.Cell;
import com.terraforged.core.cell.Populator;
import com.terraforged.core.world.heightmap.Heightmap;
import com.terraforged.core.world.terrain.Terrain;
public class CellLookup implements Module { public class CellLookup implements Populator {
private final int scale; private final int scale;
private final Module module; private final Heightmap heightmap;
public CellLookup(Module module, int scale) { public CellLookup(Heightmap heightmap, int scale) {
this.module = module; this.heightmap = heightmap;
this.scale = scale; this.scale = scale;
} }
@Override @Override
public float getValue(float x, float y) { public void apply(Cell<Terrain> cell, float x, float y) {
float px = x * scale; float px = x * scale;
float pz = y * scale; float pz = y * scale;
return module.getValue(px, pz); heightmap.getValue(px, pz);
}
@Override
public void tag(Cell<Terrain> cell, float x, float y) {
} }
} }

View File

@ -1,30 +1,39 @@
package com.terraforged.core.module; package com.terraforged.core.module;
import com.terraforged.core.cell.Cell;
import com.terraforged.core.cell.Populator;
import com.terraforged.core.world.heightmap.Heightmap;
import com.terraforged.core.world.terrain.Terrain;
import me.dags.noise.Module; import me.dags.noise.Module;
import me.dags.noise.util.NoiseUtil; import me.dags.noise.util.NoiseUtil;
public class CellLookupOffset implements Module { public class CellLookupOffset implements Populator {
private final int scale; private final int scale;
private final Module lookup;
private final Module direction; private final Module direction;
private final Module strength; private final Module strength;
private final Heightmap heightmap;
public CellLookupOffset(Module lookup, Module direction, Module strength, int scale) { public CellLookupOffset(Heightmap heightmap, Module direction, Module strength, int scale) {
this.scale = scale; this.scale = scale;
this.lookup = lookup; this.heightmap = heightmap;
this.direction = direction; this.direction = direction;
this.strength = strength; this.strength = strength;
} }
@Override @Override
public float getValue(float x, float y) { public void apply(Cell<Terrain> cell, float x, float y) {
float px = x * scale; float px = x * scale;
float pz = y * scale; float pz = y * scale;
float str = strength.getValue(x, y); float str = strength.getValue(x, y);
float dir = direction.getValue(x, y) * NoiseUtil.PI2; float dir = direction.getValue(x, y) * NoiseUtil.PI2;
float dx = NoiseUtil.sin(dir) * str; float dx = NoiseUtil.sin(dir) * str;
float dz = NoiseUtil.cos(dir) * str; float dz = NoiseUtil.cos(dir) * str;
return lookup.getValue(px + dx, pz + dz); heightmap.visit(cell, px + dx, pz + dz);
}
@Override
public void tag(Cell<Terrain> cell, float x, float y) {
} }
} }

View File

@ -77,7 +77,6 @@ public class Region implements Extent {
return new FilterRegion(); return new FilterRegion();
} }
@Override
public Cell<Terrain> getCell(int blockX, int blockZ) { public Cell<Terrain> getCell(int blockX, int blockZ) {
int relBlockX = blockSize.border + blockSize.mask(blockX); int relBlockX = blockSize.border + blockSize.mask(blockX);
int relBlockZ = blockSize.border + blockSize.mask(blockZ); int relBlockZ = blockSize.border + blockSize.mask(blockZ);
@ -131,6 +130,26 @@ public class Region implements Extent {
} }
} }
public void check() {
for (int dz = 0; dz < chunkSize.total; dz++) {
for (int dx = 0; dx < chunkSize.total; dx++) {
int index = chunkSize.indexOf(dx, dz);
if (chunks[index] == null) {
throw new NullPointerException("Null chunk " + dx + ":" + dz);
}
}
}
for (int dz = 0; dz < blockSize.total; dz++) {
for (int dx = 0; dx < blockSize.total; dx++) {
int index = blockSize.indexOf(dx, dz);
if (blocks[index] == null) {
throw new NullPointerException("Null block " + dx + ":" + dz);
}
}
}
}
public void decorate(Collection<Decorator> decorators) { public void decorate(Collection<Decorator> decorators) {
for (int dz = 0; dz < blockSize.total; dz++) { for (int dz = 0; dz < blockSize.total; dz++) {
for (int dx = 0; dx < blockSize.total; dx++) { for (int dx = 0; dx < blockSize.total; dx++) {
@ -233,14 +252,18 @@ public class Region implements Extent {
private final int chunkZ; private final int chunkZ;
private final int blockX; private final int blockX;
private final int blockZ; private final int blockZ;
private final int relBlockX; private final int regionBlockX;
private final int relBlockZ; private final int regionBlockZ;
private GenChunk(int relChunkX, int relChunkZ) { // the coordinate of the chunk within this region (relative to 0,0)
this.relBlockX = relChunkX << 4; private GenChunk(int regionChunkX, int regionChunkZ) {
this.relBlockZ = relChunkZ << 4; // the block coordinate of this chunk within this region (relative 0,0)
this.chunkX = Region.this.chunkX + relChunkX; this.regionBlockX = regionChunkX << 4;
this.chunkZ = Region.this.chunkZ + relChunkZ; this.regionBlockZ = regionChunkZ << 4;
// the real coordinate of this chunk within the world
this.chunkX = Region.this.chunkX + regionChunkX;
this.chunkZ = Region.this.chunkZ + regionChunkZ;
// the real block coordinate of this chunk within the world
this.blockX = chunkX << 4; this.blockX = chunkX << 4;
this.blockZ = chunkZ << 4; this.blockZ = chunkZ << 4;
} }
@ -267,16 +290,16 @@ public class Region implements Extent {
@Override @Override
public Cell<Terrain> getCell(int blockX, int blockZ) { public Cell<Terrain> getCell(int blockX, int blockZ) {
int relX = relBlockX + (blockX & 15); int relX = regionBlockX + (blockX & 15);
int relZ = relBlockZ + (blockZ & 15); int relZ = regionBlockZ + (blockZ & 15);
int index = blockSize.indexOf(relX, relZ); int index = blockSize.indexOf(relX, relZ);
return blocks[index]; return blocks[index];
} }
@Override @Override
public Cell<Terrain> genCell(int blockX, int blockZ) { public Cell<Terrain> genCell(int blockX, int blockZ) {
int relX = relBlockX + (blockX & 15); int relX = regionBlockX + (blockX & 15);
int relZ = relBlockZ + (blockZ & 15); int relZ = regionBlockZ + (blockZ & 15);
int index = blockSize.indexOf(relX, relZ); int index = blockSize.indexOf(relX, relZ);
return computeCell(index); return computeCell(index);
} }

View File

@ -84,13 +84,13 @@ public class RegionGenerator implements RegionExtent {
try (ThreadPool.Batcher batcher = threadPool.batcher(region.getChunkCount())) { try (ThreadPool.Batcher batcher = threadPool.batcher(region.getChunkCount())) {
region.generateZoom(generator.getHeightmap(), centerX, centerZ, zoom, batcher); region.generateZoom(generator.getHeightmap(), centerX, centerZ, zoom, batcher);
} }
region.check();
postProcess(region, generator, centerX, centerZ, zoom, filter); postProcess(region, generator, centerX, centerZ, zoom, filter);
return region; return region;
} }
} }
private void postProcess(Region region, WorldGenerator generator, float centerX, float centerZ, float zoom, private void postProcess(Region region, WorldGenerator generator, float centerX, float centerZ, float zoom, boolean filter) {
boolean filter) {
Filterable<Terrain> filterable = region.filterable(); Filterable<Terrain> filterable = region.filterable();
if (filter) { if (filter) {
generator.getFilters().setRegion(region.getRegionX(), region.getRegionZ()); generator.getFilters().setRegion(region.getRegionX(), region.getRegionZ());

View File

@ -19,7 +19,7 @@ public class Size {
} }
public int indexOf(int x, int z) { public int indexOf(int x, int z) {
return z * total + x; return (z * total) + x;
} }
public static int chunkToBlock(int i) { public static int chunkToBlock(int i) {

View File

@ -5,7 +5,6 @@ import com.terraforged.core.world.terrain.Terrain;
public interface ChunkReader extends ChunkHolder { public interface ChunkReader extends ChunkHolder {
@Override
Cell<Terrain> getCell(int dx, int dz); Cell<Terrain> getCell(int dx, int dz);
@Override @Override

View File

@ -66,7 +66,6 @@ public class ThreadPool {
for (Future<?> future : tasks) { for (Future<?> future : tasks) {
if (!future.isDone()) { if (!future.isDone()) {
hasMore = true; hasMore = true;
break;
} }
} }
} }

View File

@ -25,8 +25,6 @@ public class Climate {
private final Rand rand; private final Rand rand;
private final Module treeLine; private final Module treeLine;
private final Module heightMap;
private final Module offsetHeightMap;
private final Module offsetX; private final Module offsetX;
private final Module offsetY; private final Module offsetY;
@ -40,31 +38,9 @@ public class Climate {
this.biomeNoise = new ClimateModule(context.seed, context.settings.generator); this.biomeNoise = new ClimateModule(context.seed, context.settings.generator);
Module warpX = Source.perlin(context.seed.next(), warpScale, 2);
Module warpZ = Source.perlin(context.seed.next(), warpScale, 2);
Module windDirection = Source.cubic(context.seed.next(), cellSize, 1);
Module windStrength = Source.perlin(context.seed.next(), cellSize, 1)
.scale(cellSize * 1.5)
.bias(cellSize * 0.5);
this.treeLine = Source.perlin(context.seed.next(), context.settings.generator.biome.biomeSize * 2, 1) this.treeLine = Source.perlin(context.seed.next(), context.settings.generator.biome.biomeSize * 2, 1)
.scale(0.1).bias(0.4); .scale(0.1).bias(0.4);
this.heightMap = Source.build(cellSeed, cellSize, 1)
.distFunc(DistanceFunc.NATURAL)
.cellFunc(CellFunc.NOISE_LOOKUP)
.source(new CellLookup(heightmap::getValue, cellSize))
.cell()
.warp(warpX, warpZ, warpStrength);
this.offsetHeightMap = Source.build(cellSeed, cellSize, 1)
.distFunc(DistanceFunc.NATURAL)
.cellFunc(CellFunc.NOISE_LOOKUP)
.source(new CellLookupOffset(heightmap::getValue, windDirection, windStrength, cellSize))
.cell()
.warp(warpX, warpZ, warpStrength);
this.rand = new Rand(Source.builder().seed(context.seed.next())); this.rand = new Rand(Source.builder().seed(context.seed.next()));
this.offsetX = context.settings.generator.biomeEdgeNoise.build(context.seed.next()); this.offsetX = context.settings.generator.biomeEdgeNoise.build(context.seed.next());
this.offsetY = context.settings.generator.biomeEdgeNoise.build(context.seed.next()); this.offsetY = context.settings.generator.biomeEdgeNoise.build(context.seed.next());
@ -76,14 +52,6 @@ public class Climate {
return rand; return rand;
} }
public float getCellHeight(float x, float z) {
return heightMap.getValue(x, z);
}
public float getOffsetCellHeight(float x, float z) {
return offsetHeightMap.getValue(x, z);
}
public float getOffsetX(float x, float z, int distance) { public float getOffsetX(float x, float z, int distance) {
return offsetX.getValue(x, z) * distance; return offsetX.getValue(x, z) * distance;
} }
@ -98,26 +66,12 @@ public class Climate {
public void apply(Cell<Terrain> cell, float x, float z, boolean mask) { public void apply(Cell<Terrain> cell, float x, float z, boolean mask) {
biomeNoise.apply(cell, x, z, mask); biomeNoise.apply(cell, x, z, mask);
modify(cell, x, z);
modifyTemp(cell, x, z);
} }
private void modify(Cell<Terrain> cell, float x, float z) { private void modifyTemp(Cell<Terrain> cell, float x, float z) {
float height = getCellHeight(x, z); float height = cell.value;
float height1 = getOffsetCellHeight(x, z);
float moistDelta = 0F;
if (height > seaLevel) {
if (height1 < seaLevel) {
moistDelta = 0.7F;
} else if (height - height1 > 0.2) {
moistDelta = height - height1;
} else if (height1 - height > 0.1) {
moistDelta = Math.max(-0.5F, height - height1) * 2F;
}
}
float moistChange = moistureModifier * moistDelta;
cell.moisture = NoiseUtil.clamp(cell.moisture + moistChange, 0, 1);
if (height > upperHeight) { if (height > upperHeight) {
cell.temperature = Math.max(0, cell.temperature - temperatureModifier); cell.temperature = Math.max(0, cell.temperature - temperatureModifier);
return; return;

View File

@ -15,7 +15,7 @@ public class ContinentBlender extends Blender {
} }
@Override @Override
public float getValue(Cell<Terrain> cell, float x, float z) { public float getSelect(Cell<Terrain> cell, float x, float z) {
return cell.continentEdge; return cell.continentEdge;
} }
} }

View File

@ -16,7 +16,7 @@ public class ContinentMultiBlender extends MultiBlender {
} }
@Override @Override
public float getValue(Cell<Terrain> cell, float x, float z) { public float getSelect(Cell<Terrain> cell, float x, float z) {
return cell.continentEdge; return cell.continentEdge;
} }
} }

View File

@ -52,11 +52,14 @@ public class VoronoiContinentModule implements Populator {
@Override @Override
public float getValue(float x, float y) { public float getValue(float x, float y) {
if (true) {
throw new RuntimeException("no pls!");
} else {
Cell<Terrain> cell = new Cell<>(); Cell<Terrain> cell = new Cell<>();
apply(cell, x, y); apply(cell, x, y);
return cell.continentEdge; return cell.continentEdge;
} }
}
@Override @Override
public void apply(Cell<Terrain> cell, final float x, final float y) { public void apply(Cell<Terrain> cell, final float x, final float y) {

View File

@ -1,26 +1,18 @@
package com.terraforged.core.world.heightmap; package com.terraforged.core.world.heightmap;
import com.terraforged.core.cell.Cell; import com.terraforged.core.cell.Cell;
import com.terraforged.core.cell.Populator;
import com.terraforged.core.cell.Extent; import com.terraforged.core.cell.Extent;
import com.terraforged.core.cell.Populator;
import com.terraforged.core.region.Size; import com.terraforged.core.region.Size;
import com.terraforged.core.util.concurrent.ObjectPool; import com.terraforged.core.util.concurrent.ObjectPool;
import com.terraforged.core.world.climate.Climate; import com.terraforged.core.world.climate.Climate;
import com.terraforged.core.world.river.RiverManager;
import com.terraforged.core.world.terrain.Terrain; import com.terraforged.core.world.terrain.Terrain;
import java.rmi.UnexpectedException;
public interface Heightmap extends Populator, Extent { public interface Heightmap extends Populator, Extent {
Climate getClimate(); Climate getClimate();
RiverManager getRiverManager(); void visit(Cell<Terrain> cell, float x, float z);
@Override
default Cell<Terrain> getCell(int x, int z) {
throw new RuntimeException("Don't use this pls");
}
@Override @Override
default void visit(int minX, int minZ, int maxX, int maxZ, Cell.Visitor<Terrain> visitor) { default void visit(int minX, int minZ, int maxX, int maxZ, Cell.Visitor<Terrain> visitor) {

View File

@ -37,14 +37,6 @@ public interface RegionExtent extends Extent {
return regions; return regions;
} }
@Override
default Cell<Terrain> getCell(int x, int z) {
int regionX = chunkToRegion(Size.blockToChunk(x));
int regionZ = chunkToRegion(Size.blockToChunk(z));
Region region = getRegion(regionX, regionZ);
return region.getCell(x, z);
}
@Override @Override
default void visit(int minX, int minZ, int maxX, int maxZ, Cell.Visitor<Terrain> visitor) { default void visit(int minX, int minZ, int maxX, int maxZ, Cell.Visitor<Terrain> visitor) {
int minRegionX = chunkToRegion(Size.blockToChunk(minX)); int minRegionX = chunkToRegion(Size.blockToChunk(minX));

View File

@ -1,9 +1,5 @@
package com.terraforged.core.world.heightmap; package com.terraforged.core.world.heightmap;
import me.dags.noise.Module;
import me.dags.noise.Source;
import me.dags.noise.func.EdgeFunc;
import me.dags.noise.func.Interpolation;
import com.terraforged.core.cell.Cell; import com.terraforged.core.cell.Cell;
import com.terraforged.core.cell.Populator; import com.terraforged.core.cell.Populator;
import com.terraforged.core.module.Blender; import com.terraforged.core.module.Blender;
@ -23,6 +19,10 @@ import com.terraforged.core.world.terrain.Terrain;
import com.terraforged.core.world.terrain.TerrainPopulator; import com.terraforged.core.world.terrain.TerrainPopulator;
import com.terraforged.core.world.terrain.Terrains; import com.terraforged.core.world.terrain.Terrains;
import com.terraforged.core.world.terrain.provider.TerrainProvider; import com.terraforged.core.world.terrain.provider.TerrainProvider;
import me.dags.noise.Module;
import me.dags.noise.Source;
import me.dags.noise.func.EdgeFunc;
import me.dags.noise.func.Interpolation;
public class WorldHeightmap implements Heightmap { public class WorldHeightmap implements Heightmap {
@ -144,8 +144,10 @@ public class WorldHeightmap implements Heightmap {
this.riverManager = new RiverManager(this, context); this.riverManager = new RiverManager(this, context);
} }
public RiverManager getRiverManager() { @Override
return riverManager; public void visit(Cell<Terrain> cell, float x, float z) {
continent.apply(cell, x, z);
root.apply(cell, x, z);
} }
@Override @Override

View File

@ -67,8 +67,8 @@ public class PosGenerator {
int pz = z + dz; int pz = z + dz;
int wx = (int) domain.getX(px, pz); int wx = (int) domain.getX(px, pz);
int wz = (int) domain.getY(px, pz); int wz = (int) domain.getY(px, pz);
float value1 = heightmap.getValue(lookup, px, pz); float value1 = getHeight(px, pz);
float value2 = heightmap.getValue(lookup, wx, wz); float value2 = getHeight(wx, wz);
RiverNode.Type type1 = RiverNode.getType(value1); RiverNode.Type type1 = RiverNode.getType(value1);
RiverNode.Type type2 = RiverNode.getType(value2); RiverNode.Type type2 = RiverNode.getType(value2);
if (type1 == type2 && type1 != RiverNode.Type.NONE) { if (type1 == type2 && type1 != RiverNode.Type.NONE) {
@ -91,8 +91,8 @@ public class PosGenerator {
} }
int wx = (int) domain.getX(px, pz); int wx = (int) domain.getX(px, pz);
int wz = (int) domain.getY(px, pz); int wz = (int) domain.getY(px, pz);
float value1 = heightmap.getValue(lookup, px, pz); float value1 = getHeight(px, pz);
float value2 = heightmap.getValue(lookup, wx, wz); float value2 = getHeight(wx, wz);
RiverNode.Type type1 = RiverNode.getType(value1); RiverNode.Type type1 = RiverNode.getType(value1);
RiverNode.Type type2 = RiverNode.getType(value2); RiverNode.Type type2 = RiverNode.getType(value2);
if (type1 == type2 && type1 == point.type.opposite()) { if (type1 == type2 && type1 == point.type.opposite()) {
@ -112,8 +112,8 @@ public class PosGenerator {
int pz = z + dz; int pz = z + dz;
int wx = (int) domain.getX(px, pz); int wx = (int) domain.getX(px, pz);
int wz = (int) domain.getY(px, pz); int wz = (int) domain.getY(px, pz);
float value1 = heightmap.getValue(lookup, px, pz); float value1 = getHeight(px, pz);
float value2 = heightmap.getValue(lookup, wx, wz); float value2 = getHeight(wx, wz);
RiverNode.Type type1 = RiverNode.getType(value1); RiverNode.Type type1 = RiverNode.getType(value1);
RiverNode.Type type2 = RiverNode.getType(value2); RiverNode.Type type2 = RiverNode.getType(value2);
if (type1 == type2 && type1 == match) { if (type1 == type2 && type1 == match) {
@ -130,8 +130,8 @@ public class PosGenerator {
int pz = z + dz; int pz = z + dz;
int wx = (int) domain.getX(px, pz); int wx = (int) domain.getX(px, pz);
int wz = (int) domain.getY(px, pz); int wz = (int) domain.getY(px, pz);
float value1 = heightmap.getValue(lookup, px, pz); float value1 = getHeight(px, pz);
float value2 = heightmap.getValue(lookup, wx, wz); float value2 = getHeight(wx, wz);
if (value1 > minHeight && value2 > minHeight) { if (value1 > minHeight && value2 > minHeight) {
return new RiverNode(px, pz, RiverNode.Type.START); return new RiverNode(px, pz, RiverNode.Type.START);
} }
@ -139,6 +139,11 @@ public class PosGenerator {
return null; return null;
} }
private float getHeight(int x, int z) {
heightmap.visit(lookup, x, z);
return lookup.value;
}
private static int index(int x, int z) { private static int index(int x, int z) {
return z * 2 + x; return z * 2 + x;
} }

1
TerraForgedMod Submodule

@ -0,0 +1 @@
Subproject commit 576c491d5a156d48b1bf1e17f95d1b8272f2e5b5

View File

@ -1,2 +1,6 @@
rootProject.name = "TerraForged" rootProject.name = "TerraForged"
include ":Noise2D", ":FeatureManager", ":TerraForgedCore", ":TerraForgedApp" include ":Noise2D"
include ":FeatureManager"
include ":TerraForgedCore"
include ":TerraForgedApp"
include ":TerraForgedMod"