much
This commit is contained in:
parent
baeba9c98a
commit
93b7abff62
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -4,3 +4,6 @@
|
||||
[submodule "Noise2D"]
|
||||
path = Noise2D
|
||||
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
|
@ -1,7 +1,3 @@
|
||||
plugins {
|
||||
id "java"
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
@ -15,4 +11,5 @@ dependencies {
|
||||
|
||||
jar {
|
||||
manifest { attributes "Main-Class": "com.terraforged.app.Main" }
|
||||
from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
|
||||
}
|
@ -1,5 +1,3 @@
|
||||
apply plugin: "java"
|
||||
|
||||
dependencies {
|
||||
compile project(":Noise2D")
|
||||
}
|
@ -4,7 +4,5 @@ import com.terraforged.core.world.terrain.Terrain;
|
||||
|
||||
public interface Extent {
|
||||
|
||||
Cell<Terrain> getCell(int x, int z);
|
||||
|
||||
void visit(int minX, int minZ, int maxX, int maxZ, Cell.Visitor<Terrain> visitor);
|
||||
}
|
||||
|
@ -1,23 +1,20 @@
|
||||
package com.terraforged.core.cell;
|
||||
|
||||
import me.dags.noise.Module;
|
||||
import com.terraforged.core.util.concurrent.ObjectPool;
|
||||
import com.terraforged.core.world.terrain.Terrain;
|
||||
import me.dags.noise.Module;
|
||||
|
||||
public interface Populator extends Module {
|
||||
public interface Populator extends Module {
|
||||
|
||||
void apply(Cell<Terrain> cell, float x, float y);
|
||||
|
||||
void tag(Cell<Terrain> cell, float x, float y);
|
||||
|
||||
@Override
|
||||
default float getValue(float x, float z) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -1,21 +1,29 @@
|
||||
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 Module module;
|
||||
private final Heightmap heightmap;
|
||||
|
||||
public CellLookup(Module module, int scale) {
|
||||
this.module = module;
|
||||
public CellLookup(Heightmap heightmap, int scale) {
|
||||
this.heightmap = heightmap;
|
||||
this.scale = scale;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getValue(float x, float y) {
|
||||
public void apply(Cell<Terrain> cell, float x, float y) {
|
||||
float px = x * 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) {
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,30 +1,39 @@
|
||||
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.util.NoiseUtil;
|
||||
|
||||
public class CellLookupOffset implements Module {
|
||||
public class CellLookupOffset implements Populator {
|
||||
|
||||
private final int scale;
|
||||
private final Module lookup;
|
||||
private final Module direction;
|
||||
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.lookup = lookup;
|
||||
this.heightmap = heightmap;
|
||||
this.direction = direction;
|
||||
this.strength = strength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getValue(float x, float y) {
|
||||
public void apply(Cell<Terrain> cell, float x, float y) {
|
||||
float px = x * scale;
|
||||
float pz = y * scale;
|
||||
float str = strength.getValue(x, y);
|
||||
float dir = direction.getValue(x, y) * NoiseUtil.PI2;
|
||||
float dx = NoiseUtil.sin(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) {
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -77,7 +77,6 @@ public class Region implements Extent {
|
||||
return new FilterRegion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cell<Terrain> getCell(int blockX, int blockZ) {
|
||||
int relBlockX = blockSize.border + blockSize.mask(blockX);
|
||||
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) {
|
||||
for (int dz = 0; dz < blockSize.total; dz++) {
|
||||
for (int dx = 0; dx < blockSize.total; dx++) {
|
||||
@ -233,14 +252,18 @@ public class Region implements Extent {
|
||||
private final int chunkZ;
|
||||
private final int blockX;
|
||||
private final int blockZ;
|
||||
private final int relBlockX;
|
||||
private final int relBlockZ;
|
||||
private final int regionBlockX;
|
||||
private final int regionBlockZ;
|
||||
|
||||
private GenChunk(int relChunkX, int relChunkZ) {
|
||||
this.relBlockX = relChunkX << 4;
|
||||
this.relBlockZ = relChunkZ << 4;
|
||||
this.chunkX = Region.this.chunkX + relChunkX;
|
||||
this.chunkZ = Region.this.chunkZ + relChunkZ;
|
||||
// the coordinate of the chunk within this region (relative to 0,0)
|
||||
private GenChunk(int regionChunkX, int regionChunkZ) {
|
||||
// the block coordinate of this chunk within this region (relative 0,0)
|
||||
this.regionBlockX = regionChunkX << 4;
|
||||
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.blockZ = chunkZ << 4;
|
||||
}
|
||||
@ -267,16 +290,16 @@ public class Region implements Extent {
|
||||
|
||||
@Override
|
||||
public Cell<Terrain> getCell(int blockX, int blockZ) {
|
||||
int relX = relBlockX + (blockX & 15);
|
||||
int relZ = relBlockZ + (blockZ & 15);
|
||||
int relX = regionBlockX + (blockX & 15);
|
||||
int relZ = regionBlockZ + (blockZ & 15);
|
||||
int index = blockSize.indexOf(relX, relZ);
|
||||
return blocks[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cell<Terrain> genCell(int blockX, int blockZ) {
|
||||
int relX = relBlockX + (blockX & 15);
|
||||
int relZ = relBlockZ + (blockZ & 15);
|
||||
int relX = regionBlockX + (blockX & 15);
|
||||
int relZ = regionBlockZ + (blockZ & 15);
|
||||
int index = blockSize.indexOf(relX, relZ);
|
||||
return computeCell(index);
|
||||
}
|
||||
|
@ -84,13 +84,13 @@ public class RegionGenerator implements RegionExtent {
|
||||
try (ThreadPool.Batcher batcher = threadPool.batcher(region.getChunkCount())) {
|
||||
region.generateZoom(generator.getHeightmap(), centerX, centerZ, zoom, batcher);
|
||||
}
|
||||
region.check();
|
||||
postProcess(region, generator, centerX, centerZ, zoom, filter);
|
||||
return region;
|
||||
}
|
||||
}
|
||||
|
||||
private void postProcess(Region region, WorldGenerator generator, float centerX, float centerZ, float zoom,
|
||||
boolean filter) {
|
||||
private void postProcess(Region region, WorldGenerator generator, float centerX, float centerZ, float zoom, boolean filter) {
|
||||
Filterable<Terrain> filterable = region.filterable();
|
||||
if (filter) {
|
||||
generator.getFilters().setRegion(region.getRegionX(), region.getRegionZ());
|
||||
|
@ -19,7 +19,7 @@ public class Size {
|
||||
}
|
||||
|
||||
public int indexOf(int x, int z) {
|
||||
return z * total + x;
|
||||
return (z * total) + x;
|
||||
}
|
||||
|
||||
public static int chunkToBlock(int i) {
|
||||
|
@ -5,7 +5,6 @@ import com.terraforged.core.world.terrain.Terrain;
|
||||
|
||||
public interface ChunkReader extends ChunkHolder {
|
||||
|
||||
@Override
|
||||
Cell<Terrain> getCell(int dx, int dz);
|
||||
|
||||
@Override
|
||||
|
@ -66,7 +66,6 @@ public class ThreadPool {
|
||||
for (Future<?> future : tasks) {
|
||||
if (!future.isDone()) {
|
||||
hasMore = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,8 +25,6 @@ public class Climate {
|
||||
|
||||
private final Rand rand;
|
||||
private final Module treeLine;
|
||||
private final Module heightMap;
|
||||
private final Module offsetHeightMap;
|
||||
private final Module offsetX;
|
||||
private final Module offsetY;
|
||||
|
||||
@ -40,31 +38,9 @@ public class Climate {
|
||||
|
||||
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)
|
||||
.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.offsetX = 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;
|
||||
}
|
||||
|
||||
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) {
|
||||
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) {
|
||||
biomeNoise.apply(cell, x, z, mask);
|
||||
modify(cell, x, z);
|
||||
|
||||
modifyTemp(cell, x, z);
|
||||
}
|
||||
|
||||
private void modify(Cell<Terrain> cell, float x, float z) {
|
||||
float height = getCellHeight(x, z);
|
||||
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);
|
||||
|
||||
private void modifyTemp(Cell<Terrain> cell, float x, float z) {
|
||||
float height = cell.value;
|
||||
if (height > upperHeight) {
|
||||
cell.temperature = Math.max(0, cell.temperature - temperatureModifier);
|
||||
return;
|
||||
|
@ -15,7 +15,7 @@ public class ContinentBlender extends Blender {
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getValue(Cell<Terrain> cell, float x, float z) {
|
||||
public float getSelect(Cell<Terrain> cell, float x, float z) {
|
||||
return cell.continentEdge;
|
||||
}
|
||||
}
|
||||
|
@ -16,7 +16,7 @@ public class ContinentMultiBlender extends MultiBlender {
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getValue(Cell<Terrain> cell, float x, float z) {
|
||||
public float getSelect(Cell<Terrain> cell, float x, float z) {
|
||||
return cell.continentEdge;
|
||||
}
|
||||
}
|
||||
|
@ -52,12 +52,15 @@ public class VoronoiContinentModule implements Populator {
|
||||
|
||||
@Override
|
||||
public float getValue(float x, float y) {
|
||||
Cell<Terrain> cell = new Cell<>();
|
||||
apply(cell, x, y);
|
||||
return cell.continentEdge;
|
||||
if (true) {
|
||||
throw new RuntimeException("no pls!");
|
||||
} else {
|
||||
Cell<Terrain> cell = new Cell<>();
|
||||
apply(cell, x, y);
|
||||
return cell.continentEdge;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void apply(Cell<Terrain> cell, final float x, final float y) {
|
||||
float ox = warp.getOffsetX(x, y);
|
||||
|
@ -1,26 +1,18 @@
|
||||
package com.terraforged.core.world.heightmap;
|
||||
|
||||
import com.terraforged.core.cell.Cell;
|
||||
import com.terraforged.core.cell.Populator;
|
||||
import com.terraforged.core.cell.Extent;
|
||||
import com.terraforged.core.cell.Populator;
|
||||
import com.terraforged.core.region.Size;
|
||||
import com.terraforged.core.util.concurrent.ObjectPool;
|
||||
import com.terraforged.core.world.climate.Climate;
|
||||
import com.terraforged.core.world.river.RiverManager;
|
||||
import com.terraforged.core.world.terrain.Terrain;
|
||||
|
||||
import java.rmi.UnexpectedException;
|
||||
|
||||
public interface Heightmap extends Populator, Extent {
|
||||
|
||||
Climate getClimate();
|
||||
|
||||
RiverManager getRiverManager();
|
||||
|
||||
@Override
|
||||
default Cell<Terrain> getCell(int x, int z) {
|
||||
throw new RuntimeException("Don't use this pls");
|
||||
}
|
||||
void visit(Cell<Terrain> cell, float x, float z);
|
||||
|
||||
@Override
|
||||
default void visit(int minX, int minZ, int maxX, int maxZ, Cell.Visitor<Terrain> visitor) {
|
||||
|
@ -37,14 +37,6 @@ public interface RegionExtent extends Extent {
|
||||
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
|
||||
default void visit(int minX, int minZ, int maxX, int maxZ, Cell.Visitor<Terrain> visitor) {
|
||||
int minRegionX = chunkToRegion(Size.blockToChunk(minX));
|
||||
|
@ -1,9 +1,5 @@
|
||||
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.Populator;
|
||||
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.Terrains;
|
||||
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 {
|
||||
|
||||
@ -144,8 +144,10 @@ public class WorldHeightmap implements Heightmap {
|
||||
this.riverManager = new RiverManager(this, context);
|
||||
}
|
||||
|
||||
public RiverManager getRiverManager() {
|
||||
return riverManager;
|
||||
@Override
|
||||
public void visit(Cell<Terrain> cell, float x, float z) {
|
||||
continent.apply(cell, x, z);
|
||||
root.apply(cell, x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -67,8 +67,8 @@ public class PosGenerator {
|
||||
int pz = z + dz;
|
||||
int wx = (int) domain.getX(px, pz);
|
||||
int wz = (int) domain.getY(px, pz);
|
||||
float value1 = heightmap.getValue(lookup, px, pz);
|
||||
float value2 = heightmap.getValue(lookup, wx, wz);
|
||||
float value1 = getHeight(px, pz);
|
||||
float value2 = getHeight(wx, wz);
|
||||
RiverNode.Type type1 = RiverNode.getType(value1);
|
||||
RiverNode.Type type2 = RiverNode.getType(value2);
|
||||
if (type1 == type2 && type1 != RiverNode.Type.NONE) {
|
||||
@ -91,8 +91,8 @@ public class PosGenerator {
|
||||
}
|
||||
int wx = (int) domain.getX(px, pz);
|
||||
int wz = (int) domain.getY(px, pz);
|
||||
float value1 = heightmap.getValue(lookup, px, pz);
|
||||
float value2 = heightmap.getValue(lookup, wx, wz);
|
||||
float value1 = getHeight(px, pz);
|
||||
float value2 = getHeight(wx, wz);
|
||||
RiverNode.Type type1 = RiverNode.getType(value1);
|
||||
RiverNode.Type type2 = RiverNode.getType(value2);
|
||||
if (type1 == type2 && type1 == point.type.opposite()) {
|
||||
@ -112,8 +112,8 @@ public class PosGenerator {
|
||||
int pz = z + dz;
|
||||
int wx = (int) domain.getX(px, pz);
|
||||
int wz = (int) domain.getY(px, pz);
|
||||
float value1 = heightmap.getValue(lookup, px, pz);
|
||||
float value2 = heightmap.getValue(lookup, wx, wz);
|
||||
float value1 = getHeight(px, pz);
|
||||
float value2 = getHeight(wx, wz);
|
||||
RiverNode.Type type1 = RiverNode.getType(value1);
|
||||
RiverNode.Type type2 = RiverNode.getType(value2);
|
||||
if (type1 == type2 && type1 == match) {
|
||||
@ -130,8 +130,8 @@ public class PosGenerator {
|
||||
int pz = z + dz;
|
||||
int wx = (int) domain.getX(px, pz);
|
||||
int wz = (int) domain.getY(px, pz);
|
||||
float value1 = heightmap.getValue(lookup, px, pz);
|
||||
float value2 = heightmap.getValue(lookup, wx, wz);
|
||||
float value1 = getHeight(px, pz);
|
||||
float value2 = getHeight(wx, wz);
|
||||
if (value1 > minHeight && value2 > minHeight) {
|
||||
return new RiverNode(px, pz, RiverNode.Type.START);
|
||||
}
|
||||
@ -139,6 +139,11 @@ public class PosGenerator {
|
||||
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) {
|
||||
return z * 2 + x;
|
||||
}
|
||||
|
1
TerraForgedMod
Submodule
1
TerraForgedMod
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 576c491d5a156d48b1bf1e17f95d1b8272f2e5b5
|
@ -1,2 +1,6 @@
|
||||
rootProject.name = "TerraForged"
|
||||
include ":Noise2D", ":FeatureManager", ":TerraForgedCore", ":TerraForgedApp"
|
||||
include ":Noise2D"
|
||||
include ":FeatureManager"
|
||||
include ":TerraForgedCore"
|
||||
include ":TerraForgedApp"
|
||||
include ":TerraForgedMod"
|
Loading…
Reference in New Issue
Block a user