break everything part 2

This commit is contained in:
dags- 2020-05-13 17:22:34 +01:00
parent ef7a94e51f
commit e81b7612d7
647 changed files with 3936 additions and 17120 deletions

2
Engine

@ -1 +1 @@
Subproject commit 6babefb3017d33a78c914eda21fd1fa3b53dc9e3
Subproject commit 7cda523891ce81b36dd5f09f5573e1f258f92923

@ -1 +1 @@
Subproject commit 0da0d13c3dc8426b18a55107b42986e9d66387f1
Subproject commit fceeea1cac7174f873834fa12b5d78952710a516

@ -1 +0,0 @@
Subproject commit c36977964d2f203fe9a940df908d1b7c2fac264b

View File

@ -1,23 +0,0 @@
# TerraForgedAPI
### Dependency
```groovy
repositories {
maven {
url "https://io.terraforged.com/repository/maven/"
}
}
dependencies {
implementation "com.terraforged:TerraForgedAPI:1.15.2-0.0.1"
}
```
### Usage
TerraForged fires a number of setup events each time its chunk generator is created. These events expose certain
components of the generator allowing for world-gen content to be configured, modified, or added to.
See the `com.terraforged.api.TerraEvent` class for the available events.
All events are fired on the `FORGE` event bus.

View File

@ -1,70 +0,0 @@
buildscript {
repositories {
maven { url "https://files.minecraftforge.net/maven" }
jcenter()
mavenCentral()
}
dependencies {
classpath group: "net.minecraftforge.gradle", name: "ForgeGradle", version: "3.+", changing: true
}
}
apply plugin: "net.minecraftforge.gradle"
apply plugin: "maven-publish"
apply plugin: "eclipse"
version = "${mc_version}-${mod_version}"
archivesBaseName = "TerraForgedAPI"
repositories {
jcenter()
mavenCentral()
}
dependencies {
minecraft "net.minecraftforge:forge:${mc_version}-${forge_version}"
compile project(":FeatureManager")
compile project(":TerraForgedCore")
}
minecraft {
mappings channel: mcp_channel, version: mcp_version
}
task sourceJar(type: Jar) {
classifier = "sources"
from("$projectDir/src/main/java")
from(project(":Noise2D").projectDir.getPath() + "/src/main/java")
from(project(":FeatureManager").projectDir.getPath() + "/src/main/java")
from(project(":TerraForgedCore").projectDir.getPath() + "/src/main/java")
}
jar {
dependsOn(sourceJar)
from("$buildDir/classes/java/main")
from(project(":Noise2D").buildDir.getPath() + "/classes/java/main")
from(project(":FeatureManager").buildDir.getPath() + "/classes/java/main")
from(project(":TerraForgedCore").buildDir.getPath() + "/classes/java/main")
}
publishing {
publications {
mavenJava(MavenPublication) {
artifact jar
artifact sourceJar
}
}
if (System.getenv("MAVEN_USER") != null && System.getenv("MAVEN_PASS") != null) {
repositories {
maven {
credentials {
username System.getenv("MAVEN_USER")
password System.getenv("MAVEN_PASS")
}
name = "nexus"
url = "https://io.terraforged.com/repository/maven/"
}
}
}
}

View File

@ -1,21 +0,0 @@
package com.terraforged.api.material.state;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.tags.Tag;
import java.util.function.Predicate;
public class StateTagPredicate implements Predicate<BlockState> {
private final Tag<Block> tag;
public StateTagPredicate(Tag<Block> tag) {
this.tag = tag;
}
@Override
public boolean test(BlockState state) {
return tag.contains(state.getBlock());
}
}

View File

@ -1,23 +0,0 @@
apply plugin: "maven-publish"
apply plugin: "java"
repositories {
mavenCentral()
jcenter()
}
dependencies {
compile "com.google.code.gson:gson:2.8.0"
compile "org.processing:core:3.3.7"
compile "it.unimi.dsi:fastutil:8.2.1"
compile project(":TerraForgedCore")
}
jar {
manifest { attributes "Main-Class": "com.terraforged.app.Main" }
from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
}
publish {
dependsOn(jar)
}

View File

@ -1,161 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.app;
import com.terraforged.app.renderer.MeshRenderer;
import com.terraforged.app.renderer.Renderer;
import com.terraforged.app.renderer.VoxelRenderer;
import com.terraforged.core.cell.Cell;
import com.terraforged.core.world.terrain.Terrain;
import processing.core.PApplet;
import processing.event.KeyEvent;
import processing.event.MouseEvent;
public abstract class Applet extends PApplet {
public static final int ELEVATION = 1;
public static final int BIOME_TYPE = 2;
public static final int TEMPERATURE = 3;
public static final int MOISTURE = 4;
public static final int BIOME = 5;
public static final int STEEPNESS = 6;
public static final int TERRAIN_TYPE = 7;
public static final int EROSION = 8;
public static final int CONTINENT = 9;
protected Renderer mesh = new MeshRenderer(this);
protected Renderer voxel = new VoxelRenderer(this);
public final Controller controller = new Controller();
public abstract Cache getCache();
public abstract float color(Cell<Terrain> cell);
@Override
public void settings() {
size(800, 800, P3D);
}
@Override
public void mousePressed(MouseEvent event) {
controller.mousePress(event);
}
@Override
public void mouseReleased(MouseEvent event) {
controller.mouseRelease(event);
}
@Override
public void mouseDragged(MouseEvent event) {
controller.mouseDrag(event);
}
@Override
public void mouseWheel(MouseEvent event) {
controller.mouseWheel(event);
}
@Override
public void keyPressed(KeyEvent event) {
controller.keyPress(event);
}
@Override
public void keyReleased(KeyEvent event) {
controller.keyRelease(event);
}
public void leftAlignText(int margin, int top, int lineHeight, String... lines) {
noLights();
fill(0, 0, 100);
for (int i = 0; i < lines.length; i++) {
int y = top + (i * lineHeight);
text(lines[i], margin, y);
}
}
public void drawTerrain(float zoom) {
if (controller.getRenderMode() == 0) {
voxel.render(zoom);
} else {
mesh.render(zoom);
}
}
public String colorModeName() {
switch (controller.getColorMode()) {
case STEEPNESS:
return "GRADIENT";
case TEMPERATURE:
return "TEMPERATURE";
case MOISTURE:
return "MOISTURE";
case TERRAIN_TYPE:
return "TERRAIN TYPE";
case ELEVATION:
return "ELEVATION";
case BIOME_TYPE:
return "BIOME TYPE";
case BIOME:
return "BIOME";
case EROSION:
return "EROSION";
case CONTINENT:
return "CONTINENT";
default:
return "-";
}
}
public static float hue(float value, int steps, int max) {
value = Math.round(value * (steps - 1));
value /= (steps - 1);
return value * max;
}
public void drawCompass() {
pushStyle();
pushMatrix();
textSize(200);
fill(100, 0, 100);
char[] chars = {'N', 'E', 'S', 'W'};
for (int r = 0; r < 4; r++) {
char c = chars[r];
float x = -textWidth(c) / 2;
float y = -width * 1.2F;
text(c, x, y);
rotateZ(0.5F * PI);
}
popMatrix();
popStyle();
textSize(16);
}
}

View File

@ -1,123 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.app;
import com.terraforged.core.cell.Cell;
import com.terraforged.core.region.Region;
import com.terraforged.core.region.gen.RegionGenerator;
import com.terraforged.core.settings.Settings;
import com.terraforged.core.util.concurrent.ThreadPool;
import com.terraforged.core.world.GeneratorContext;
import com.terraforged.core.world.WorldGeneratorFactory;
import com.terraforged.core.world.biome.BiomeType;
import com.terraforged.core.world.terrain.Terrain;
import com.terraforged.core.world.terrain.Terrains;
public class Cache {
private float offsetX = 0;
private float offsetZ = 0;
private float zoom = 0F;
private boolean filter = true;
private Terrains terrain;
private Settings settings;
private GeneratorContext context;
private Region region;
private RegionGenerator renderer;
public Cache(int seed) {
Settings settings = new Settings();
settings.generator.seed = seed;
this.settings = settings;
this.terrain = Terrains.create(settings);
this.context = new GeneratorContext(terrain, settings);
this.renderer = RegionGenerator.builder()
.factory(new WorldGeneratorFactory(context))
.pool(ThreadPool.getPool())
.size(3, 2)
.build();
}
public Settings getSettings() {
return settings;
}
public Terrains getTerrain() {
return terrain;
}
public Terrain getCenterTerrain() {
Terrain tag = getCenterCell().tag;
return tag == null ? terrain.ocean : tag;
}
public BiomeType getCenterBiomeType() {
return getCenterCell().biomeType;
}
public int getCenterHeight() {
return (int) (context.levels.worldHeight * getCenterCell().value);
}
public Cell<Terrain> getCenterCell() {
int center = region.getBlockSize().size / 2;
return region.getCell(center, center);
}
public Region getRegion() {
return region;
}
public void update(float offsetX, float offsetZ, float zoom, boolean filters) {
if (region == null) {
record(offsetX, offsetZ, zoom, filters);
return;
}
if (this.offsetX != offsetX || this.offsetZ != offsetZ) {
record(offsetX, offsetZ, zoom, filters);
return;
}
if (this.zoom != zoom) {
record(offsetX, offsetZ, zoom, filters);
return;
}
if (this.filter != filters) {
record(offsetX, offsetZ, zoom, filters);
}
}
private void record(float offsetX, float offsetZ, float zoom, boolean filters) {
this.zoom = zoom;
this.filter = filters;
this.offsetX = offsetX;
this.offsetZ = offsetZ;
try {
this.region = renderer.generateRegion(offsetX, offsetZ, zoom, filters);
} catch (Throwable t) {
t.printStackTrace();
}
}
}

View File

@ -1,236 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.app;
import processing.core.PApplet;
import processing.event.KeyEvent;
import processing.event.MouseEvent;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.event.ActionEvent;
public class Controller {
private static final int BUTTON_NONE = -1;
private static final int BUTTON_1 = 37;
private static final int BUTTON_2 = 39;
private static final int BUTTON_3 = 3;
private static final float cameraSpeed = 100F;
private static final float zoomSpeed = 0.01F;
private static final float rotateSpeed = 0.002F;
private static final float translateSpeed = 2F;
private static final float moveSpeed = 10F;
private int mouseButton = BUTTON_NONE;
private int lastX = 0;
private int lastY = 0;
private float yaw = -0.2F;
private float pitch = 0.85F;
private float translateX = 0F;
private float translateY = 0F;
private float translateZ = -800;
private float velocityX = 0F;
private float velocityY = 0F;
private int colorMode = 1;
private int renderMode = 0;
private int newSeed = 0;
private int left = 0;
private int right = 0;
private int up = 0;
private int down = 0;
private float zoom = 16;
private boolean filters = true;
public void apply(PApplet applet) {
applet.translate(translateX, translateY, translateZ);
applet.translate(applet.width / 2, applet.height / 2, 0);
applet.rotateX(pitch);
applet.rotateZ(yaw);
update();
}
public void update() {
float forward = up + down;
float strafe = left + right;
velocityX = forward * (float) Math.sin(yaw);
velocityY = forward * (float) Math.cos(yaw);
velocityX += strafe * (float) Math.sin(yaw + Math.toRadians(90));
velocityY += strafe * (float) Math.cos(yaw + Math.toRadians(90));
if (velocityX != 0 || velocityY != 0) {
float magnitude = (float) Math.sqrt(velocityX * velocityX + velocityY * velocityY);
velocityX /= magnitude;
velocityY /= magnitude;
}
}
public int getColorMode() {
return colorMode;
}
public int getRenderMode() {
return renderMode;
}
public float velocityX() {
return velocityX * moveSpeed / zoom;
}
public float velocityY() {
return velocityY * moveSpeed / zoom;
}
public float zoomLevel() {
return zoom;
}
public boolean filters() {
return filters;
}
public int getNewSeed() {
if (newSeed == 1) {
newSeed = 0;
return 1;
}
if (newSeed != 0) {
int val = newSeed;
newSeed = 0;
return val;
}
return 0;
}
public void keyPress(KeyEvent event) {
switch (event.getKey()) {
case 'w':
up = -1;
break;
case 'a':
left = -1;
break;
case 's':
down = 1;
break;
case 'd':
right = 1;
break;
}
}
public void keyRelease(KeyEvent event) {
switch (event.getKey()) {
case 'w':
up = 0;
return;
case 'a':
left = 0;
return;
case 's':
down = 0;
return;
case 'd':
right = 0;
return;
case 'r':
renderMode = renderMode == 0 ? 1 : 0;
return;
case 'n':
newSeed = 1;
return;
case 'm':
newSeed = Main.seed;
return;
case 'f':
filters = !filters;
return;
case 'c':
StringSelection selection = new StringSelection("" + Main.seed);
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(selection, null);
return;
case 'v':
try {
Object data = Toolkit.getDefaultToolkit().getSystemClipboard().getData(DataFlavor.stringFlavor);
newSeed = (int) Long.parseLong(data.toString());
} catch (Throwable t) {
t.printStackTrace();
}
}
if (event.getKey() >= '1' && event.getKey() <= '9') {
colorMode = event.getKey() - '0';
return;
}
}
public void mousePress(MouseEvent event) {
if (mouseButton == BUTTON_NONE) {
lastX = event.getX();
lastY = event.getY();
mouseButton = event.getButton();
}
}
public void mouseRelease(MouseEvent event) {
mouseButton = BUTTON_NONE;
}
public void mouseWheel(MouseEvent event) {
translateZ -= event.getCount() * cameraSpeed;
}
public void mouseDrag(MouseEvent event) {
int dx = event.getX() - lastX;
int dy = event.getY() - lastY;
boolean ctrl = (event.getModifiers() & ActionEvent.CTRL_MASK) == ActionEvent.CTRL_MASK;
lastX = event.getX();
lastY = event.getY();
if (mouseButton == BUTTON_1) {
yaw -= dx * rotateSpeed;
pitch -= dy * rotateSpeed;
}
if (mouseButton == BUTTON_2) {
translateX += dx * translateSpeed;
translateY += dy * translateSpeed;
}
if (mouseButton == BUTTON_3) {
if (ctrl) {
zoom += (dy - dx) * zoom * zoomSpeed;
zoom = Math.max(1F, zoom);
} else {
translateZ -= (dy - dx) * cameraSpeed * 0.1F;
}
}
}
}

View File

@ -1,264 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.app;
import com.terraforged.app.biome.BiomeProvider;
import com.terraforged.core.cell.Cell;
import com.terraforged.core.world.biome.BiomeData;
import com.terraforged.core.world.biome.BiomeType;
import com.terraforged.core.world.terrain.Terrain;
import me.dags.noise.util.NoiseUtil;
import java.awt.*;
import java.util.Random;
public class Main extends Applet {
public static void main(String[] args) {
Main.start(-1);
}
public static void start(long seed) {
Main.seed = (int) seed;
Main.random = seed == -1;
main(Main.class.getName());
}
private static boolean random = false;
public static int seed = -1;
private Cache cache;
private float offsetX = 0;
private float offsetZ = 0;
private final String bits = System.getProperty("sun.arch.data.model");
private final BiomeProvider biomeProvider = new BiomeProvider();
@Override
public Cache getCache() {
return cache;
}
@Override
public void setup() {
super.setup();
if (random) {
setSeed(new Random(System.currentTimeMillis()).nextInt());
offsetX = 0;
offsetZ = 0;
}
setSeed(seed);
}
public void setSeed(int seed) {
Main.seed = seed;
cache = new Cache(seed);
System.out.println(seed);
}
@Override
public float color(Cell<Terrain> cell) {
switch (controller.getColorMode()) {
case STEEPNESS:
return hue(1 - cell.steepness, 64, 70);
case TEMPERATURE:
return hue(1 - cell.temperature, 64, 70);
case MOISTURE:
return hue(cell.moisture, 64, 70);
case TERRAIN_TYPE:
if (cell.tag == getCache().getTerrain().volcano) {
return 0F;
}
return 20 + (cell.tag.getHue() * 80);
case ELEVATION:
float value = (cell.value - 0.245F) / 0.65F;
return (1 - value) * 30;
case BIOME:
BiomeData biome = biomeProvider.getBiome(cell);
if (biome == null) {
return 0F;
}
return cell.biome * 70;
case CONTINENT:
return cell.continent * 70;
default:
return 50;
}
}
@Override
public void draw() {
int nextSeed = controller.getNewSeed();
if (nextSeed == 1) {
setup();
} else if (nextSeed != 0) {
setSeed(nextSeed);
}
offsetX += controller.velocityX() * controller.zoomLevel() * controller.zoomLevel();
offsetZ += controller.velocityY() * controller.zoomLevel() * controller.zoomLevel();
cache.update(offsetX, offsetZ, controller.zoomLevel(), controller.filters());
// color stuff
noStroke();
background(0);
colorMode(HSB, 100);
// lighting
ambientLight(0, 0, 75, width / 2, -height, height / 2);
pointLight(0, 0, 50, width / 2, -height * 100, height / 2);
// render
pushMatrix();
controller.apply(this);
// translate(-width / 2F, -height / 2F);
drawTerrain(controller.zoomLevel());
drawCompass();
// translate(0, 0, 255 * (width / (float) controller.resolution()) / controller.zoomLevel());
// mesh.renderWind(controller.resolution(), controller.zoomLevel());
popMatrix();
pushMatrix();
translate(0, 0, -1);
// drawGradient(0, height - 150, 100F, width, 150);
popMatrix();
drawStats();
drawBiomeKey();
drawControls();
}
private void drawGradient(int x, int y, float d, float w, float h) {
noFill();
for (int dy = 0; dy <= h; dy++) {
float dist = Math.min(1, dy / d);
stroke(0, 0, 0, dist * 100F);
line(x, y + dy, x + w, y + dy);
}
noStroke();
}
private void drawStats() {
int resolution = cache.getRegion().getBlockSize().size;
int blocks = NoiseUtil.round(resolution * controller.zoomLevel());
String[][] info = {
{"Java:", String.format("x%s", bits)},
{"Fps: ", String.format("%.3f", frameRate)},
{"Seed:", String.format("%s", seed)},
{"Zoom: ", String.format("%.2f", controller.zoomLevel())},
{"Area: ", String.format("%sx%s [%sx%s]", blocks, blocks, resolution, resolution)},
{"Center: ", String.format("x=%.0f, y=%s, z=%.0f", offsetX, cache.getCenterHeight(), offsetZ)},
{"Terrain: ", cache.getCenterTerrain().getName()},
{"BiomeType:", cache.getCenterBiomeType().name()},
// {"Biome: ", String.format("%s", biomeProvider.getBiome(cache.getCenterCell()).name)},
{"Overlay: ", colorModeName()},
};
int widest = 0;
for (String[] s : info) {
widest = Math.max(widest, (int) textWidth(s[0]));
}
int top = 20;
int lineHeight = 15;
for (String[] s : info) {
leftAlignText(10, top, 0, s[0]);
top += lineHeight;
}
top = 20;
for (String[] s : info) {
if (s.length == 2) {
leftAlignText(12 + widest, top, 0, s[1]);
top += lineHeight;
}
}
}
private void drawBiomeKey() {
int top = 20;
int lineHeight = 15;
int widest = 0;
for (BiomeType type : BiomeType.values()) {
widest = Math.max(widest, (int) textWidth(type.name()));
}
int left = width - widest - lineHeight - 15;
for (BiomeType type : BiomeType.values()) {
leftAlignText(left, top, 0, type.name());
float[] hsb = Color.RGBtoHSB(type.getColor().getRed(), type.getColor().getGreen(),
type.getColor().getBlue(), null);
fill(0, 0, 100);
rect(width - lineHeight - 11, top - lineHeight + 1, lineHeight + 2, lineHeight + 2);
fill(hsb[0] * 100, hsb[1] * 100, hsb[2] * 100);
rect(width - lineHeight - 10, top - lineHeight + 2, lineHeight, lineHeight);
top += lineHeight;
}
}
private void drawControls() {
String[][][] columns = {
{
{"Mouse-Left + Move", " - Rotate terrain"},
{"Mouse-Right + Move", " - Pan terrain"},
{"Mouse-Scroll + Move", " - Zoom camera"},
{"Mouse-Scroll + LCTRL + Move", " - Zoom terrain"},
{"WASD", "- Move terrain"}
}, {
{"Key 1-8", "- Select overlay"},
{"Key R", "- Toggle mesh renderer"},
{"Key F", "- Toggle filters"},
{"Key N", "- Generate new world"},
{"Key C", "- Copy seed to clipboard"},
{"Key V", "- Paste seed from clipboard"},
}};
int lineHeight = 15;
int rows = 0;
for (String[][] column : columns) {
rows = Math.max(rows, column.length);
}
int left = 10;
int widest = 0;
for (String[][] column : columns) {
int top = (height - 10) - ((rows - 1) * lineHeight);
for (String[] row : column) {
int width = 0;
for (String cell : row) {
leftAlignText(left + width, top, 0, cell);
width += (int) textWidth(cell);
}
top += lineHeight;
widest = Math.max(widest, width);
}
left += widest + 10;
}
}
}

View File

@ -1,59 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.app.biome;
import me.dags.noise.util.NoiseUtil;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
public class BiomeColor {
private static final BufferedImage image = load();
private static final int width = image.getWidth() - 1;
private static final int height = image.getHeight() - 1;
public static int getRGB(float temp, float moist) {
float humidity = temp * moist;
temp = 1 - temp;
humidity = 1 - humidity;
int x = NoiseUtil.round(temp * width);
int y = NoiseUtil.round(humidity * height);
return image.getRGB(x, y);
}
private static BufferedImage load() {
try (InputStream inputStream = BiomeColor.class.getResourceAsStream("/grass.png")) {
return ImageIO.read(inputStream);
} catch (IOException e) {
e.printStackTrace();
return new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
}
}
}

View File

@ -1,140 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.app.biome;
import com.terraforged.core.cell.Cell;
import com.terraforged.core.util.grid.FixedGrid;
import com.terraforged.core.world.biome.BiomeData;
import com.terraforged.core.world.biome.BiomeType;
import com.terraforged.core.world.terrain.Terrain;
import processing.data.JSONArray;
import processing.data.JSONObject;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
public class BiomeProvider {
private final List<FixedGrid<BiomeData>> biomes;
public BiomeProvider() {
biomes = getBiomes(5);
}
public BiomeData getBiome(Cell<Terrain> cell) {
FixedGrid<BiomeData> grid = biomes.get(cell.biomeType.ordinal());
if (grid == null) {
return null;
}
return grid.get(cell.moisture, cell.temperature, cell.biome);
}
private static List<FixedGrid<BiomeData>> getBiomes(int gridSize) {
List<FixedGrid<BiomeData>> data = new ArrayList<>();
for (BiomeType type : BiomeType.values()) {
data.add(type.ordinal(), null);
}
Map<String, BiomeData> biomes = loadBiomes();
Map<BiomeType, List<String>> types = loadBiomeTypes();
for (Map.Entry<BiomeType, List<String>> e : types.entrySet()) {
List<BiomeData> list = new LinkedList<>();
for (String id : e.getValue()) {
BiomeData biome = biomes.get(id);
if (biome != null) {
list.add(biome);
}
}
FixedGrid<BiomeData> grid = FixedGrid.generate(gridSize, list, b -> b.rainfall, b -> b.temperature);
data.set(e.getKey().ordinal(), grid);
}
return data;
}
private static Map<String, BiomeData> loadBiomes() {
try (InputStream inputStream = BiomeProvider.class.getResourceAsStream("/biome_data.json")) {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder sb = new StringBuilder();
reader.lines().forEach(sb::append);
JSONArray array = JSONArray.parse(sb.toString());
Map<String,BiomeData> biomes = new HashMap<>();
for (int i = 0; i < array.size(); i++) {
JSONObject object = array.getJSONObject(i);
String name = object.getString("id");
float moisture = object.getFloat("moisture");
float temperature = object.getFloat("temperature");
int color = BiomeColor.getRGB(temperature, moisture);
BiomeData biome = new BiomeData(name, null, color, moisture, temperature);
biomes.put(name, biome);
}
return biomes;
} catch (IOException e) {
e.printStackTrace();
return Collections.emptyMap();
}
}
private static Map<BiomeType, List<String>> loadBiomeTypes() {
try (InputStream inputStream = BiomeProvider.class.getResourceAsStream("/biome_groups.json")) {
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
StringBuilder sb = new StringBuilder();
reader.lines().forEach(sb::append);
JSONObject object = JSONObject.parse(sb.toString());
Iterator iterator = object.keyIterator();
Map<BiomeType, List<String>> biomes = new HashMap<>();
while (iterator.hasNext()) {
String key = "" + iterator.next();
if (key.contains("rivers")) {
continue;
}
if (key.contains("oceans")) {
continue;
}
BiomeType type = BiomeType.valueOf(key);
List<String> group = new LinkedList<>();
JSONArray array = object.getJSONArray(key);
for (int i = 0; i < array.size(); i++) {
group.add(array.getString(i));
}
biomes.put(type, group);
}
return biomes;
} catch (IOException e) {
e.printStackTrace();
return Collections.emptyMap();
}
}
}

View File

@ -1,141 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.app.mesh;
public class Mesh {
private final Mesh inner;
private final float x0;
private final float y0;
private final float x1;
private final float y1;
private final float quality;
public Mesh(Mesh inner, float x0, float y0, float x1, float y1, float quality) {
this.inner = inner;
this.x0 = x0;
this.y0 = y0;
this.x1 = x1;
this.y1 = y1;
this.quality = quality;
}
public Mesh expand(float scale) {
return expand(scale, scale);
}
public Mesh expand(float scale, float quality) {
float width0 = getWidth();
float height0 = getHeight();
float width1 = width0 * scale;
float height1 = height0 * scale;
float deltaX = (width1 - width0) / 2F;
float deltaY = (height1 - height0) / 2F;
float newQuality = this.quality * quality;
return new Mesh(this, x0 - deltaX, y0 - deltaY, x1 + deltaX, y1 + deltaY, newQuality);
}
public float getWidth() {
return x1 - x0;
}
public float getHeight() {
return y1 - y0;
}
public void start(float width, float height) {
if (inner != null) {
inner.start(width, height);
}
}
public void render() {
if (inner == null) {
renderNormal();
} else {
renderCutout();
inner.render();
}
}
public void beginStrip() {
if (inner != null) {
inner.beginStrip();
}
}
public void endStrip() {
if (inner != null) {
inner.endStrip();
}
}
public void visit(float x, float y) {
if (inner != null) {
inner.visit(x, y);
}
}
private void renderNormal() {
beginStrip();
iterate(x0, y0, x1, y1);
endStrip();
}
private void renderCutout() {
beginStrip();
iterate(x0, y0, inner.x1, inner.y0);
endStrip();
beginStrip();
iterate(inner.x1, y0, x1, inner.y1);
endStrip();
beginStrip();
iterate(inner.x0, inner.y1, x1, y1);
endStrip();
beginStrip();
iterate(x0, inner.y0, inner.x0, y1);
endStrip();
}
private void iterate(float minX, float minY, float maxX, float maxY) {
float x = minX - quality;
float y = minY - quality;
while (y < maxY) {
y = Math.min(y + quality, maxY);
beginStrip();
while (x < maxX) {
x = Math.min(x + quality, maxX);
visit(x, y);
visit(x, y + quality);
}
x = minX - quality;
endStrip();
}
}
}

View File

@ -1,67 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.app.mesh;
import com.terraforged.app.Applet;
import com.terraforged.app.renderer.Renderer;
import com.terraforged.core.cell.Cell;
import com.terraforged.core.world.terrain.Terrain;
import processing.core.PApplet;
public class NoiseMesh extends Mesh {
private final Applet applet;
private final Renderer renderer;
private final Cell<Terrain> cell = new Cell<>();
public NoiseMesh(Applet applet, Renderer renderer, float x0, float y0, float x1, float y1) {
super(null, x0, y0, x1, y1, 1F);
this.applet = applet;
this.renderer = renderer;
}
@Override
public void start(float width, float height) {
applet.noStroke();
}
@Override
public void beginStrip() {
applet.beginShape(PApplet.TRIANGLE_STRIP);
}
@Override
public void endStrip() {
applet.endShape();
}
@Override
public void visit(float x, float y) {
float height = cell.value * 255;
float surface = renderer.getSurface(cell, height, 63, 10F);
applet.vertex(x * 10F, y * 10F, (int) surface);
}
}

View File

@ -1,58 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.app.mesh;
import com.terraforged.app.Applet;
import com.terraforged.app.renderer.Renderer;
public class TestRenderer extends Renderer {
private static boolean printed = false;
public TestRenderer(Applet visualizer) {
super(visualizer);
}
@Override
public void render(float zoom) {
Mesh mesh = new NoiseMesh(applet, this, -64, -64, 64, 64);
for (int i = 0; i < 1; i++) {
// mesh = mesh.expand(4);
}
float width = mesh.getWidth();
float height = mesh.getHeight();
if (!printed) {
printed = true;
System.out.println(width + "x" + height);
}
applet.pushMatrix();
mesh.start(mesh.getWidth(), mesh.getHeight());
mesh.render();
applet.popMatrix();
}
}

View File

@ -1,75 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.app.renderer;
import com.terraforged.app.Applet;
import com.terraforged.core.cell.Cell;
import com.terraforged.core.world.heightmap.Levels;
import com.terraforged.core.world.terrain.Terrain;
import processing.core.PApplet;
public class MeshRenderer extends Renderer {
public MeshRenderer(Applet visualizer) {
super(visualizer);
}
@Override
public void render(float zoom) {
float seaLevel = new Levels(applet.getCache().getSettings().generator).water;
int worldHeight = applet.getCache().getSettings().generator.world.worldHeight;
int waterLevel = (int) (seaLevel * worldHeight);
int seabedLevel = (int) ((seaLevel - 0.04) * worldHeight);
int resolution = applet.getCache().getRegion().getBlockSize().size;
float w = applet.width / (float) (resolution - 1);
float h = applet.width / (float) (resolution - 1);
applet.noStroke();
applet.pushMatrix();
applet.translate(-applet.width / 2F, -applet.width / 2F);
for (int dy = 0; dy < resolution - 1; dy++) {
applet.beginShape(PApplet.TRIANGLE_STRIP);
for (int dx = 0; dx < resolution; dx++) {
draw(dx, dy, w, h, zoom, worldHeight, waterLevel, seabedLevel);
draw(dx, dy + 1, w, h, zoom, worldHeight, waterLevel, resolution / 2);
}
applet.endShape();
}
applet.popMatrix();
}
private void draw(int dx, int dz, float w, float h, float zoom, int worldHeight, int waterLevel, int center) {
Cell<Terrain> cell = applet.getCache().getRegion().getCell(dx, dz);
float height = (cell.value * worldHeight);
float x = dx * w;
float z = dz * h;
float y = (int) getSurface(cell, height, waterLevel, 1);
applet.vertex(x, z, y / (zoom * 0.2F));
}
}

View File

@ -1,133 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.app.renderer;
import com.terraforged.app.Applet;
import com.terraforged.core.cell.Cell;
import com.terraforged.core.world.terrain.Terrain;
import java.awt.*;
public abstract class Renderer {
protected final Applet applet;
protected Renderer(Applet visualizer) {
this.applet = visualizer;
}
public float getSurface(Cell<Terrain> cell, float height, int waterLevel, float el) {
if (cell.tag == applet.getCache().getTerrain().volcanoPipe) {
applet.fill(2, 80, 64);
return height * 0.95F * el;
}
if (height < waterLevel) {
float temp = cell.temperature;
float tempDelta = temp > 0.5 ? temp - 0.5F : -(0.5F - temp);
float tempAlpha = (tempDelta / 0.5F);
float hueMod = 4 * tempAlpha;
float depth = (waterLevel - height) / (float) (90);
float darkness = (1 - depth);
float darknessMod = 0.5F + (darkness * 0.5F);
applet.fill(60 - hueMod, 65, 90 * darknessMod);
return height * el;
} else if (applet.controller.getColorMode() == Applet.ELEVATION) {
float hei = Math.min(1, Math.max(0, height - waterLevel) / (255F - waterLevel));
float temp = cell.temperature;
float moist = Math.min(temp, cell.moisture);
float hue = 35 - (temp * (1 - moist)) * 25;
float sat = 75 * (1 - hei);
float bri = 50 + 40 * hei;
applet.fill(hue, sat, bri);
return height * el;
} else if (applet.controller.getColorMode() == Applet.BIOME_TYPE) {
Color c = cell.biomeType.getColor();
if (cell.riverMask < 0.025) {
c = Color.white;
}
float[] hsb = Color.RGBtoHSB(c.getRed(), c.getGreen(), c.getBlue(), null);
float bri = 90 + cell.biomeTypeMask * 10;
applet.fill(hsb[0] * 100, hsb[1] * 100, hsb[2] * bri);
return height * el;
} else if (applet.controller.getColorMode() == Applet.BIOME) {
float hue = applet.color(cell);
float sat = 70;
float bright = 50 + 50 * cell.riverMask;
applet.fill(hue, sat, bright);
return height * el;
} else if(applet.controller.getColorMode() == Applet.TERRAIN_TYPE) {
float hue = applet.color(cell);
if (cell.tag == applet.getCache().getTerrain().coast) {
hue = 15;
}
float modifier = cell.mask(0.4F, 0.5F, 0F, 1F);
float modAlpha = 0.1F;
float mod = (1 - modAlpha) + (modifier * modAlpha);
float sat = 70;
float bri = 70;
applet.fill(hue, 65, 70);
return height * el;
} else if(applet.controller.getColorMode() == Applet.EROSION) {
float change = cell.sediment + cell.erosion;
float value = Math.abs(cell.sediment * 250);
value = Math.max(0, Math.min(1, value));
float hue = value * 70;
float sat = 70;
float bri = 70;
applet.fill(hue, sat, bri);
return height * el;
} else {
float hue = applet.color(cell);
float sat = 70;
float bri = 70;
applet.fill(hue, sat, bri);
return height * el;
}
}
public abstract void render(float zoom);
private void renderGradLine(int steps, float x1, float y1, float x2, float y2, float hue1, float hue2, float sat, float bright) {
float dx = x2 - x1;
float dy = y2 - y1;
float fx = dx / steps;
float fy = dy / steps;
float dhue = hue2 - hue1;
float fhue = dhue / steps;
for (int i = 0; i < steps; i++) {
float px1 = x1 + (i * fx);
float py1 = y1 + (i * fy);
float px2 = x2 + ((i + 1) * fx);
float py2 = y2 + ((i + 1) * fy);
float hue = (i + 1) * fhue;
applet.stroke(hue1 + hue, sat, bright);
applet.line(px1, py1, px2, py2);
}
}
}

View File

@ -1,155 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.app.renderer;
import com.terraforged.app.Applet;
import com.terraforged.core.cell.Cell;
import com.terraforged.core.world.heightmap.Levels;
import com.terraforged.core.world.terrain.Terrain;
import processing.core.PApplet;
public class VoxelRenderer extends Renderer {
public VoxelRenderer(Applet visualizer) {
super(visualizer);
}
@Override
public void render(float zoom) {
Levels levels = new Levels(applet.getCache().getSettings().generator);
int worldHeight = applet.getCache().getSettings().generator.world.worldHeight;
int waterLevel = levels.waterY;
int resolution = applet.getCache().getRegion().getBlockSize().size;
int center = resolution / 2;
float w = applet.width / (float) resolution;
float h = applet.width / (float) resolution;
float el = w / zoom;
applet.pushMatrix();
applet.translate(-applet.width / 2F, -applet.width / 2F);
int difX = Math.max(0, applet.getCache().getRegion().getBlockSize().size - resolution);
int difY = Math.max(0, applet.getCache().getRegion().getBlockSize().size - resolution);
int offsetX = difX / 2;
int offsetZ = difY / 2;
for (int dy = 0; dy < resolution; dy++) {
for (int dx = 0; dx < resolution; dx++) {
Cell<Terrain> cell = applet.getCache().getRegion().getCell(dx + offsetX, dy + offsetZ);
float cellHeight = cell.value * worldHeight;
int height = Math.min(worldHeight, Math.max(0, (int) cellHeight));
if (height < 0) {
continue;
}
float x0 = dx * w;
float x1 = (dx + 1) * w;
float z0 = dy * h;
float z1 = (dy + 1) * h;
float y = getSurface(cell, height, waterLevel, el);
if ((dx == center && (dy == center || dy - 1 == center || dy + 1 == center))
|| (dy == center && (dx - 1 == center || dx + 1 == center))) {
applet.fill(100F, 100F, 100F);
}
drawColumn(x0, z0, 0, x1, z1, y);
}
}
drawRulers(16, worldHeight, resolution, h, el);
applet.popMatrix();
}
private void drawRulers(int step, int max, int resolution, float unit, float height) {
float width = (resolution + 1) * unit;
int doubleStep = step * 2;
for (int dz = 0; dz <= 1; dz++) {
for (int dx = 0; dx <= 1; dx++) {
float x0 = dx * width;
float x1 = x0 - unit;
float z0 = dz * width;
float z1 = z0 - unit;
for (int dy = 0; dy < max; dy += step) {
float y0 = dy * height;
float y1 = y0 + (step * height);
float h = 100, s = 100, b = 100;
if ((dy % doubleStep) != step) {
s = 0;
}
applet.fill(h, s, b);
drawColumn(x0, z0, y0, x1, z1, y1);
}
}
}
}
private void drawColumn(float x0, float y0, float z0, float x1, float y1, float z1) {
applet.beginShape(PApplet.QUADS);
// +Z "front" face
applet.vertex(x0, y0, z1);
applet.vertex(x1, y0, z1);
applet.vertex(x1, y1, z1);
applet.vertex(x0, y1, z1);
// -Z "back" face
applet.vertex(x1, y0, z0);
applet.vertex(x0, y0, z0);
applet.vertex(x0, y1, z0);
applet.vertex(x1, y1, z0);
// +Y "bottom" face
applet.vertex(x0, y1, z1);
applet.vertex(x1, y1, z1);
applet.vertex(x1, y1, z0);
applet.vertex(x0, y1, z0);
// -Y "top" face
applet.vertex(x0, y0, z0);
applet.vertex(x1, y0, z0);
applet.vertex(x1, y0, z1);
applet.vertex(x0, y0, z1);
// +X "right" face
applet.vertex(x1, y0, z1);
applet.vertex(x1, y0, z0);
applet.vertex(x1, y1, z0);
applet.vertex(x1, y1, z1);
// -X "left" face
applet.vertex(x0, y0, z0);
applet.vertex(x0, y0, z1);
applet.vertex(x0, y1, z1);
applet.vertex(x0, y1, z0);
applet.endShape();
}
}

View File

@ -1,63 +0,0 @@
package com.terraforged.app.util;
import com.google.gson.JsonElement;
import com.terraforged.core.util.serialization.serializer.Reader;
import java.util.Collection;
import java.util.Map;
import java.util.stream.Collectors;
public class JsonReader implements Reader {
private final JsonElement element;
public JsonReader(JsonElement element) {
this.element = element;
}
@Override
public int getSize() {
if (element.isJsonObject()) {
return element.getAsJsonObject().size();
}
if (element.isJsonArray()) {
return element.getAsJsonArray().size();
}
return 0;
}
@Override
public Reader getChild(String key) {
return new JsonReader(element.getAsJsonObject().get(key));
}
@Override
public Reader getChild(int index) {
return new JsonReader(element.getAsJsonArray().get(index));
}
@Override
public Collection<String> getKeys() {
return element.getAsJsonObject().entrySet().stream().map(Map.Entry::getKey).collect(Collectors.toList());
}
@Override
public String getString() {
return element.getAsString();
}
@Override
public boolean getBool() {
return element.getAsBoolean();
}
@Override
public float getFloat() {
return element.getAsFloat();
}
@Override
public int getInt() {
return element.getAsInt();
}
}

View File

@ -1,28 +0,0 @@
package com.terraforged.app.util;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.terraforged.core.settings.Settings;
import com.terraforged.core.util.serialization.serializer.Deserializer;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.Reader;
public class Loader {
public static Settings load() {
Settings settings = new Settings();
load(settings);
return settings;
}
private static void load(Settings settings) {
try (Reader reader = new BufferedReader(new FileReader("terraforged-generator.json"))) {
JsonElement json = new JsonParser().parse(reader);
new Deserializer().deserialize(new JsonReader(json), settings);
} catch (Throwable e) {
e.printStackTrace();
}
}
}

View File

@ -1,764 +0,0 @@
[
{
"id": "biomesoplenty:alps",
"moisture": 0.2,
"temperature": 0.1,
"color": -2302756
},
{
"id": "biomesoplenty:alps_foothills",
"moisture": 0.2,
"temperature": 0.1,
"color": -10461088
},
{
"id": "biomesoplenty:bayou",
"moisture": 0.59999996,
"temperature": 0.58000004,
"color": -13592211
},
{
"id": "biomesoplenty:bog",
"moisture": 0.59999996,
"temperature": 0.42,
"color": -13592211
},
{
"id": "biomesoplenty:boreal_forest",
"moisture": 0.4,
"temperature": 0.32,
"color": -13592211
},
{
"id": "biomesoplenty:brushland",
"moisture": 0.06666667,
"temperature": 0.8,
"color": -13592211
},
{
"id": "biomesoplenty:chaparral",
"moisture": 0.29999998,
"temperature": 0.52,
"color": -13592211
},
{
"id": "biomesoplenty:cherry_blossom_grove",
"moisture": 0.59999996,
"temperature": 0.44,
"color": -13592211
},
{
"id": "biomesoplenty:cold_desert",
"moisture": 0.0,
"temperature": 0.3,
"color": -6034953
},
{
"id": "biomesoplenty:coniferous_forest",
"moisture": 0.33333334,
"temperature": 0.38,
"color": -13592211
},
{
"id": "biomesoplenty:dead_forest",
"moisture": 0.2,
"temperature": 0.32,
"color": -13592211
},
{
"id": "biomesoplenty:fir_clearing",
"moisture": 0.33333334,
"temperature": 0.38,
"color": -13592211
},
{
"id": "biomesoplenty:floodplain",
"moisture": 0.8,
"temperature": 0.56,
"color": -13592211
},
{
"id": "biomesoplenty:flower_meadow",
"moisture": 0.46666667,
"temperature": 0.35999998,
"color": -13592211
},
{
"id": "biomesoplenty:grassland",
"moisture": 0.46666667,
"temperature": 0.44,
"color": -13592211
},
{
"id": "biomesoplenty:gravel_beach",
"moisture": 0.33333334,
"temperature": 0.44,
"color": -6034953
},
{
"id": "biomesoplenty:grove",
"moisture": 0.18333334,
"temperature": 0.52,
"color": -13592211
},
{
"id": "biomesoplenty:highland",
"moisture": 0.4,
"temperature": 0.44,
"color": -13592211
},
{
"id": "biomesoplenty:highland_moor",
"moisture": 0.4,
"temperature": 0.44,
"color": -13592211
},
{
"id": "biomesoplenty:lavender_field",
"moisture": 0.46666667,
"temperature": 0.52,
"color": -13592211
},
{
"id": "biomesoplenty:lush_grassland",
"moisture": 0.59999996,
"temperature": 0.58000004,
"color": -13592211
},
{
"id": "biomesoplenty:lush_swamp",
"moisture": 0.6666667,
"temperature": 0.48000002,
"color": -13592211
},
{
"id": "biomesoplenty:mangrove",
"moisture": 0.46666667,
"temperature": 0.524,
"color": -13592211
},
{
"id": "biomesoplenty:maple_woods",
"moisture": 0.53333336,
"temperature": 0.3,
"color": -13592211
},
{
"id": "biomesoplenty:marsh",
"moisture": 0.46666667,
"temperature": 0.45999998,
"color": -13592211
},
{
"id": "biomesoplenty:meadow",
"moisture": 0.46666667,
"temperature": 0.35999998,
"color": -13592211
},
{
"id": "biomesoplenty:mire",
"moisture": 0.59999996,
"temperature": 0.42,
"color": -13592211
},
{
"id": "biomesoplenty:mystic_grove",
"moisture": 0.53333336,
"temperature": 0.48000002,
"color": -13592211
},
{
"id": "biomesoplenty:oasis",
"moisture": 0.33333334,
"temperature": 1.0,
"color": -6034953
},
{
"id": "biomesoplenty:ominous_woods",
"moisture": 0.4,
"temperature": 0.44,
"color": -13592211
},
{
"id": "biomesoplenty:orchard",
"moisture": 0.26666668,
"temperature": 0.52,
"color": -13592211
},
{
"id": "biomesoplenty:outback",
"moisture": 0.033333335,
"temperature": 1.0,
"color": -6034953
},
{
"id": "biomesoplenty:overgrown_cliffs",
"moisture": 0.53333336,
"temperature": 0.58000004,
"color": -13592211
},
{
"id": "biomesoplenty:pasture",
"moisture": 0.2,
"temperature": 0.52,
"color": -13592211
},
{
"id": "biomesoplenty:prairie",
"moisture": 0.2,
"temperature": 0.52,
"color": -13592211
},
{
"id": "biomesoplenty:pumpkin_patch",
"moisture": 0.53333336,
"temperature": 0.35999998,
"color": -13592211
},
{
"id": "biomesoplenty:rainforest",
"moisture": 1.0,
"temperature": 0.54,
"color": -13592211
},
{
"id": "biomesoplenty:redwood_forest",
"moisture": 0.4,
"temperature": 0.52,
"color": -12427646
},
{
"id": "biomesoplenty:redwood_forest_edge",
"moisture": 0.4,
"temperature": 0.52,
"color": -12427646
},
{
"id": "biomesoplenty:scrubland",
"moisture": 0.06666667,
"temperature": 0.64,
"color": -13592211
},
{
"id": "biomesoplenty:seasonal_forest",
"moisture": 0.53333336,
"temperature": 0.35999998,
"color": -13592211
},
{
"id": "biomesoplenty:shield",
"moisture": 0.53333336,
"temperature": 0.35999998,
"color": -13592211
},
{
"id": "biomesoplenty:shrubland",
"moisture": 0.033333335,
"temperature": 0.44,
"color": -13592211
},
{
"id": "biomesoplenty:silkglade",
"moisture": 0.13333334,
"temperature": 0.5,
"color": -13592211
},
{
"id": "biomesoplenty:snowy_coniferous_forest",
"moisture": 0.33333334,
"temperature": 0.1,
"color": -13592211
},
{
"id": "biomesoplenty:snowy_fir_clearing",
"moisture": 0.33333334,
"temperature": 0.1,
"color": -13592211
},
{
"id": "biomesoplenty:snowy_forest",
"moisture": 0.33333334,
"temperature": 0.1,
"color": -13592211
},
{
"id": "biomesoplenty:steppe",
"moisture": 0.033333335,
"temperature": 0.51,
"color": -13592211
},
{
"id": "biomesoplenty:temperate_rainforest",
"moisture": 0.8,
"temperature": 0.45999998,
"color": -13592211
},
{
"id": "biomesoplenty:temperate_rainforest_hills",
"moisture": 0.8,
"temperature": 0.45999998,
"color": -13592211
},
{
"id": "biomesoplenty:tropical_rainforest",
"moisture": 0.6666667,
"temperature": 0.6,
"color": -13592211
},
{
"id": "biomesoplenty:tundra",
"moisture": 0.33333334,
"temperature": 0.28,
"color": -13592211
},
{
"id": "biomesoplenty:wasteland",
"moisture": 0.0,
"temperature": 1.0,
"color": -12427646
},
{
"id": "biomesoplenty:wetland",
"moisture": 0.46666667,
"temperature": 0.44,
"color": -13592211
},
{
"id": "biomesoplenty:white_beach",
"moisture": 0.6666667,
"temperature": 0.58000004,
"color": -6034953
},
{
"id": "biomesoplenty:woodland",
"moisture": 0.33333334,
"temperature": 0.52,
"color": -13592211
},
{
"id": "biomesoplenty:xeric_shrubland",
"moisture": 0.06666667,
"temperature": 0.9,
"color": -6034953
},
{
"id": "minecraft:badlands",
"moisture": 0.0,
"temperature": 1.0,
"color": -6034953
},
{
"id": "minecraft:badlands_plateau",
"moisture": 0.0,
"temperature": 1.0,
"color": -6034953
},
{
"id": "minecraft:bamboo_jungle",
"moisture": 0.59999996,
"temperature": 0.58000004,
"color": -13592211
},
{
"id": "minecraft:bamboo_jungle_hills",
"moisture": 0.59999996,
"temperature": 0.58000004,
"color": -13592211
},
{
"id": "minecraft:beach",
"moisture": 0.26666668,
"temperature": 0.52,
"color": -6034953
},
{
"id": "minecraft:birch_forest",
"moisture": 0.4,
"temperature": 0.44,
"color": -13592211
},
{
"id": "minecraft:birch_forest_hills",
"moisture": 0.4,
"temperature": 0.44,
"color": -13592211
},
{
"id": "minecraft:cold_ocean",
"moisture": 0.33333334,
"temperature": 0.4,
"color": -13592211
},
{
"id": "minecraft:dark_forest",
"moisture": 0.53333336,
"temperature": 0.48000002,
"color": -13592211
},
{
"id": "minecraft:dark_forest_hills",
"moisture": 0.53333336,
"temperature": 0.48000002,
"color": -13592211
},
{
"id": "minecraft:deep_cold_ocean",
"moisture": 0.33333334,
"temperature": 0.4,
"color": -13592211
},
{
"id": "minecraft:deep_frozen_ocean",
"moisture": 0.33333334,
"temperature": 0.4,
"color": -13592211
},
{
"id": "minecraft:deep_lukewarm_ocean",
"moisture": 0.33333334,
"temperature": 0.4,
"color": -13592211
},
{
"id": "minecraft:deep_ocean",
"moisture": 0.33333334,
"temperature": 0.4,
"color": -13592211
},
{
"id": "minecraft:deep_warm_ocean",
"moisture": 0.33333334,
"temperature": 0.4,
"color": -6034953
},
{
"id": "minecraft:desert",
"moisture": 0.0,
"temperature": 1.0,
"color": -6034953
},
{
"id": "minecraft:desert_hills",
"moisture": 0.0,
"temperature": 1.0,
"color": -6034953
},
{
"id": "minecraft:desert_lakes",
"moisture": 0.0,
"temperature": 1.0,
"color": -6034953
},
{
"id": "minecraft:eroded_badlands",
"moisture": 0.0,
"temperature": 1.0,
"color": -6034953
},
{
"id": "minecraft:flower_forest",
"moisture": 0.53333336,
"temperature": 0.48000002,
"color": -13592211
},
{
"id": "minecraft:forest",
"moisture": 0.53333336,
"temperature": 0.48000002,
"color": -13592211
},
{
"id": "minecraft:frozen_ocean",
"moisture": 0.33333334,
"temperature": 0.2,
"color": -13592211
},
{
"id": "minecraft:frozen_river",
"moisture": 0.33333334,
"temperature": 0.2,
"color": -13592211
},
{
"id": "minecraft:giant_spruce_taiga",
"moisture": 0.53333336,
"temperature": 0.3,
"color": -13592211
},
{
"id": "minecraft:giant_spruce_taiga_hills",
"moisture": 0.53333336,
"temperature": 0.3,
"color": -13592211
},
{
"id": "minecraft:giant_tree_taiga",
"moisture": 0.53333336,
"temperature": 0.32,
"color": -13592211
},
{
"id": "minecraft:giant_tree_taiga_hills",
"moisture": 0.53333336,
"temperature": 0.32,
"color": -13592211
},
{
"id": "minecraft:gravelly_mountains",
"moisture": 0.2,
"temperature": 0.28,
"color": -13592211
},
{
"id": "minecraft:ice_spikes",
"moisture": 0.33333334,
"temperature": 0.2,
"color": -2302756
},
{
"id": "minecraft:jungle",
"moisture": 0.59999996,
"temperature": 0.58000004,
"color": -13592211
},
{
"id": "minecraft:jungle_hills",
"moisture": 0.59999996,
"temperature": 0.58000004,
"color": -13592211
},
{
"id": "minecraft:lukewarm_ocean",
"moisture": 0.33333334,
"temperature": 0.4,
"color": -13592211
},
{
"id": "minecraft:modified_badlands_plateau",
"moisture": 0.0,
"temperature": 1.0,
"color": -6034953
},
{
"id": "minecraft:modified_gravelly_mountains",
"moisture": 0.2,
"temperature": 0.28,
"color": -13592211
},
{
"id": "minecraft:modified_jungle",
"moisture": 0.59999996,
"temperature": 0.58000004,
"color": -13592211
},
{
"id": "minecraft:modified_wooded_badlands_plateau",
"moisture": 0.0,
"temperature": 1.0,
"color": -6034953
},
{
"id": "minecraft:mountains",
"moisture": 0.2,
"temperature": 0.28,
"color": -13592211
},
{
"id": "minecraft:mushroom_field_shore",
"moisture": 0.6666667,
"temperature": 0.56,
"color": -13592211
},
{
"id": "minecraft:mushroom_fields",
"moisture": 0.6666667,
"temperature": 0.56,
"color": -13592211
},
{
"id": "minecraft:ocean",
"moisture": 0.33333334,
"temperature": 0.4,
"color": -13592211
},
{
"id": "minecraft:plains",
"moisture": 0.26666668,
"temperature": 0.52,
"color": -13592211
},
{
"id": "minecraft:river",
"moisture": 0.33333334,
"temperature": 0.4,
"color": -13592211
},
{
"id": "minecraft:savanna",
"moisture": 0.0,
"temperature": 0.68,
"color": -13592211
},
{
"id": "minecraft:savanna_plateau",
"moisture": 0.0,
"temperature": 0.6,
"color": -13592211
},
{
"id": "minecraft:shattered_savanna",
"moisture": 0.0,
"temperature": 0.64,
"color": -13592211
},
{
"id": "minecraft:shattered_savanna_plateau",
"moisture": 0.0,
"temperature": 0.6,
"color": -13592211
},
{
"id": "minecraft:snowy_beach",
"moisture": 0.2,
"temperature": 0.22,
"color": -6034953
},
{
"id": "minecraft:snowy_mountains",
"moisture": 0.33333334,
"temperature": 0.2,
"color": -13592211
},
{
"id": "minecraft:snowy_taiga",
"moisture": 0.26666668,
"temperature": 0.0,
"color": -13592211
},
{
"id": "minecraft:snowy_taiga_hills",
"moisture": 0.26666668,
"temperature": 0.0,
"color": -13592211
},
{
"id": "minecraft:snowy_taiga_mountains",
"moisture": 0.26666668,
"temperature": 0.0,
"color": -13592211
},
{
"id": "minecraft:snowy_tundra",
"moisture": 0.33333334,
"temperature": 0.2,
"color": -13592211
},
{
"id": "minecraft:sunflower_plains",
"moisture": 0.26666668,
"temperature": 0.52,
"color": -13592211
},
{
"id": "minecraft:swamp",
"moisture": 0.59999996,
"temperature": 0.52,
"color": -13592211
},
{
"id": "minecraft:swamp_hills",
"moisture": 0.59999996,
"temperature": 0.52,
"color": -13592211
},
{
"id": "minecraft:taiga",
"moisture": 0.53333336,
"temperature": 0.3,
"color": -13592211
},
{
"id": "minecraft:taiga_hills",
"moisture": 0.53333336,
"temperature": 0.3,
"color": -13592211
},
{
"id": "minecraft:taiga_mountains",
"moisture": 0.53333336,
"temperature": 0.3,
"color": -13592211
},
{
"id": "minecraft:tall_birch_forest",
"moisture": 0.4,
"temperature": 0.44,
"color": -13592211
},
{
"id": "minecraft:tall_birch_hills",
"moisture": 0.4,
"temperature": 0.44,
"color": -13592211
},
{
"id": "minecraft:warm_ocean",
"moisture": 0.33333334,
"temperature": 0.4,
"color": -6034953
},
{
"id": "minecraft:wooded_badlands_plateau",
"moisture": 0.0,
"temperature": 1.0,
"color": -6034953
},
{
"id": "minecraft:wooded_hills",
"moisture": 0.53333336,
"temperature": 0.48000002,
"color": -13592211
},
{
"id": "minecraft:wooded_mountains",
"moisture": 0.2,
"temperature": 0.28,
"color": -13592211
},
{
"id": "terraforged:cold_steppe",
"moisture": 0.06666667,
"temperature": 0.28,
"color": -13592211
},
{
"id": "terraforged:savanna_scrub",
"moisture": 0.0,
"temperature": 0.68,
"color": -13592211
},
{
"id": "terraforged:shattered_savanna_scrub",
"moisture": 0.0,
"temperature": 0.64,
"color": -13592211
},
{
"id": "terraforged:snowy_taiga_scrub",
"moisture": 0.26666668,
"temperature": 0.0,
"color": -13592211
},
{
"id": "terraforged:steppe",
"moisture": 0.06666667,
"temperature": 0.48000002,
"color": -13592211
},
{
"id": "terraforged:taiga_scrub",
"moisture": 0.53333336,
"temperature": 0.3,
"color": -13592211
}
]

View File

@ -1,168 +0,0 @@
{
"TROPICAL_RAINFOREST": [
"biomesoplenty:overgrown_cliffs",
"biomesoplenty:tropical_rainforest",
"minecraft:bamboo_jungle",
"minecraft:bamboo_jungle_hills",
"minecraft:jungle",
"minecraft:jungle_hills",
"minecraft:modified_jungle"
],
"SAVANNA": [
"biomesoplenty:brushland",
"biomesoplenty:scrubland",
"biomesoplenty:xeric_shrubland",
"minecraft:savanna",
"minecraft:savanna_plateau",
"minecraft:shattered_savanna",
"minecraft:shattered_savanna_plateau",
"terraforged:savanna_scrub",
"terraforged:shattered_savanna_scrub"
],
"DESERT": [
"biomesoplenty:oasis",
"biomesoplenty:outback",
"biomesoplenty:wasteland",
"minecraft:badlands",
"minecraft:badlands_plateau",
"minecraft:desert",
"minecraft:desert_hills",
"minecraft:desert_lakes",
"minecraft:eroded_badlands",
"minecraft:modified_badlands_plateau",
"minecraft:modified_wooded_badlands_plateau",
"minecraft:wooded_badlands_plateau"
],
"TEMPERATE_RAINFOREST": [
"biomesoplenty:rainforest",
"biomesoplenty:temperate_rainforest",
"biomesoplenty:temperate_rainforest_hills",
"minecraft:plains"
],
"TEMPERATE_FOREST": [
"biomesoplenty:cherry_blossom_grove",
"biomesoplenty:grove",
"biomesoplenty:mystic_grove",
"biomesoplenty:orchard",
"biomesoplenty:pumpkin_patch",
"biomesoplenty:redwood_forest",
"biomesoplenty:redwood_forest_edge",
"biomesoplenty:seasonal_forest",
"biomesoplenty:silkglade",
"biomesoplenty:temperate_rainforest",
"biomesoplenty:temperate_rainforest_hills",
"biomesoplenty:woodland",
"minecraft:birch_forest",
"minecraft:birch_forest_hills",
"minecraft:dark_forest",
"minecraft:flower_forest",
"minecraft:forest",
"minecraft:plains",
"minecraft:tall_birch_forest",
"minecraft:wooded_hills"
],
"GRASSLAND": [
"biomesoplenty:bayou",
"biomesoplenty:bog",
"biomesoplenty:chaparral",
"biomesoplenty:floodplain",
"biomesoplenty:grassland",
"biomesoplenty:highland_moor",
"biomesoplenty:lavender_field",
"biomesoplenty:lush_grassland",
"biomesoplenty:lush_swamp",
"biomesoplenty:mangrove",
"biomesoplenty:marsh",
"biomesoplenty:mire",
"biomesoplenty:pasture",
"biomesoplenty:prairie",
"biomesoplenty:shrubland",
"biomesoplenty:steppe",
"biomesoplenty:wetland",
"minecraft:plains",
"minecraft:sunflower_plains",
"minecraft:swamp"
],
"COLD_STEPPE": [
"terraforged:cold_steppe"
],
"STEPPE": [
"biomesoplenty:steppe",
"terraforged:steppe"
],
"TAIGA": [
"biomesoplenty:boreal_forest",
"biomesoplenty:coniferous_forest",
"biomesoplenty:dead_forest",
"biomesoplenty:fir_clearing",
"biomesoplenty:flower_meadow",
"biomesoplenty:maple_woods",
"biomesoplenty:meadow",
"biomesoplenty:ominous_woods",
"biomesoplenty:shield",
"biomesoplenty:tundra",
"minecraft:giant_spruce_taiga",
"minecraft:giant_tree_taiga",
"minecraft:giant_tree_taiga_hills",
"minecraft:taiga",
"minecraft:taiga_hills",
"terraforged:taiga_scrub"
],
"TUNDRA": [
"biomesoplenty:alps",
"biomesoplenty:alps_foothills",
"biomesoplenty:snowy_coniferous_forest",
"biomesoplenty:snowy_fir_clearing",
"biomesoplenty:snowy_forest",
"minecraft:ice_spikes",
"minecraft:snowy_taiga",
"minecraft:snowy_taiga_hills",
"minecraft:snowy_tundra",
"terraforged:snowy_taiga_scrub"
],
"ALPINE": [
"biomesoplenty:highland",
"minecraft:gravelly_mountains",
"minecraft:modified_gravelly_mountains",
"minecraft:mountains",
"minecraft:snowy_mountains",
"minecraft:snowy_taiga_mountains",
"minecraft:taiga_mountains",
"minecraft:wooded_mountains"
],
"rivers": {
"COLD": [
"minecraft:frozen_river"
],
"MEDIUM": [
"minecraft:river"
],
"WARM": []
},
"oceans": {
"COLD": [
"minecraft:cold_ocean",
"minecraft:frozen_ocean"
],
"MEDIUM": [
"minecraft:ocean"
],
"WARM": [
"minecraft:lukewarm_ocean",
"minecraft:warm_ocean"
]
},
"deep_oceans": {
"COLD": [
"minecraft:deep_cold_ocean",
"minecraft:deep_frozen_ocean"
],
"MEDIUM": [
"minecraft:deep_ocean"
],
"WARM": [
"minecraft:deep_lukewarm_ocean",
"minecraft:deep_warm_ocean"
]
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

View File

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2020 TerraForged
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,31 +0,0 @@
apply plugin: "maven-publish"
repositories {
mavenCentral()
}
dependencies {
compile project(":Noise2D")
compile "it.unimi.dsi:fastutil:8.2.1"
}
publishing {
publications {
mavenJava(MavenPublication) {
artifact jar
}
}
if (System.getenv("MAVEN_USER") != null && System.getenv("MAVEN_PASS") != null) {
repositories {
maven {
credentials {
username System.getenv("MAVEN_USER")
password System.getenv("MAVEN_PASS")
}
name = "nexus"
url = "https://io.terraforged.com/repository/maven/"
}
}
}
}

View File

@ -1,136 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.cell;
import com.terraforged.core.util.concurrent.ObjectPool;
import com.terraforged.core.world.biome.BiomeType;
import com.terraforged.core.world.terrain.Terrain;
import me.dags.noise.util.NoiseUtil;
public class Cell<T extends Tag> {
private static final Cell EMPTY = new Cell() {
@Override
public boolean isAbsent() {
return true;
}
};
private static final ObjectPool<Cell<Terrain>> POOL = new ObjectPool<>(100, Cell::new);
public float continent;
public float continentEdge;
public float region;
public float regionEdge;
public float biome;
public float biomeEdge = 1F;
public float riverMask = 1F;
public float value;
public float biomeMoisture;
public float biomeTemperature;
public float moisture;
public float temperature;
public float steepness;
public float erosion;
public float sediment;
public float biomeTypeMask = 1F;
public BiomeType biomeType = BiomeType.GRASSLAND;
public T tag = null;
public void copy(Cell<T> other) {
value = other.value;
continent = other.continent;
continentEdge = other.continentEdge;
region = other.region;
regionEdge = other.regionEdge;
biome = other.biome;
biomeEdge = other.biomeEdge;
riverMask = other.riverMask;
moisture = other.moisture;
temperature = other.temperature;
biomeMoisture = other.biomeMoisture;
biomeTemperature = other.biomeTemperature;
steepness = other.steepness;
erosion = other.erosion;
sediment = other.sediment;
biomeType = other.biomeType;
biomeTypeMask = other.biomeTypeMask;
tag = other.tag;
}
public float continentMask(float min, float max) {
return NoiseUtil.map(continentEdge, min, max, max - min);
}
public float regionMask(float min, float max) {
return NoiseUtil.map(regionEdge, min, max, max - min);
}
public float biomeMask(float min, float max) {
return NoiseUtil.map(biomeEdge, min, max, max - min);
}
public float mask(float cmin, float cmax, float rmin, float rmax) {
return riverMask * continentMask(cmin, cmax) * regionMask(rmin, rmax);
}
public boolean isAbsent() {
return false;
}
@SuppressWarnings("unchecked")
public static <T extends Tag> Cell<T> empty() {
return EMPTY;
}
public static ObjectPool.Item<Cell<Terrain>> pooled() {
return POOL.get();
}
public interface Visitor<T extends Tag> {
void visit(Cell<T> cell, int dx, int dz);
}
public interface ContextVisitor<C, T extends Tag> {
void visit(Cell<T> cell, int dx, int dz, C ctx);
}
public interface ZoomVisitor<T extends Tag> {
void visit(Cell<T> cell, float x, float z);
}
}

View File

@ -1,33 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.cell;
import com.terraforged.core.world.terrain.Terrain;
public interface Extent {
void visit(int minX, int minZ, int maxX, int maxZ, Cell.Visitor<Terrain> visitor);
}

View File

@ -1,45 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.cell;
import com.terraforged.core.util.concurrent.ObjectPool;
import com.terraforged.core.world.terrain.Terrain;
import me.dags.noise.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()) {
apply(cell.getValue(), x, z);
return cell.getValue().value;
}
}
}

View File

@ -1,31 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.cell;
public interface Tag {
String getName();
}

View File

@ -1,291 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.filter;
import com.terraforged.core.cell.Cell;
import com.terraforged.core.region.Size;
import com.terraforged.core.settings.Settings;
import com.terraforged.core.world.heightmap.Levels;
import me.dags.noise.util.NoiseUtil;
import java.util.Random;
/*
* This class in an adaption of the work by Sebastian Lague which is also licensed under MIT.
* Reference:
* https://github.com/SebLague/Hydraulic-Erosion/blob/Coding-Adventure-E01/Assets/Scripts/Erosion.cs
* https://github.com/SebLague/Hydraulic-Erosion/blob/Coding-Adventure-E01/LICENSE
*
* License In Full:
* MIT License
*
* Copyright (c) 2019 Sebastian Lague
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
public class Erosion implements Filter {
private int erosionRadius = 3;
private float inertia = 0.05f;
private float sedimentCapacityFactor = 4;
private float minSedimentCapacity = 0.01f;
private float erodeSpeed = 0.3f;
private float depositSpeed = 0.3f;
private float evaporateSpeed = 0.01f;
private float gravity = 8;
private int maxDropletLifetime = 30;
private float initialWaterVolume = 1;
private float initialSpeed = 1;
private final TerrainPos gradient = new TerrainPos();
private int[][] erosionBrushIndices = new int[0][];
private float[][] erosionBrushWeights = new float[0][];
private final Modifier modifier;
private final Random random = new Random();
public Erosion(Settings settings, Levels levels) {
erodeSpeed = settings.filters.erosion.erosionRate;
depositSpeed = settings.filters.erosion.depositeRate;
modifier = Modifier.range(levels.ground, levels.ground(15));
}
@Override
public void apply(Filterable<?> map, int seedX, int seedZ, int iterations) {
if (erosionBrushIndices.length != map.getSize().total) {
init(map.getSize().total, erosionRadius);
}
applyMain(map, seedX, seedZ, iterations, random);
// applyNeighbours(map, seedX, seedZ, iterations, random);
}
private int nextCoord(Size size, Random random) {
return random.nextInt(size.total - 1);
}
private void applyMain(Filterable<?> map, int seedX, int seedZ, int iterations, Random random) {
random.setSeed(NoiseUtil.seed(seedX, seedZ));
while (iterations-- > 0) {
int posX = nextCoord(map.getSize(), random);
int posZ = nextCoord(map.getSize(), random);
apply(map.getBacking(), posX, posZ, map.getSize().total);
}
}
private void apply(Cell<?>[] cells, float posX, float posY, int size) {
float dirX = 0;
float dirY = 0;
float speed = initialSpeed;
float water = initialWaterVolume;
float sediment = 0;
for (int lifetime = 0; lifetime < maxDropletLifetime; lifetime++) {
int nodeX = (int) posX;
int nodeY = (int) posY;
int dropletIndex = nodeY * size + nodeX;
// Calculate droplet's offset inside the cell (0,0) = at NW node, (1,1) = at SE node
float cellOffsetX = posX - nodeX;
float cellOffsetY = posY - nodeY;
// Calculate droplet's height and direction of flow with bilinear interpolation of surrounding heights
gradient.update(cells, size, posX, posY);
// Update the droplet's direction and position (move position 1 unit regardless of speed)
dirX = (dirX * inertia - gradient.gradientX * (1 - inertia));
dirY = (dirY * inertia - gradient.gradientY * (1 - inertia));
// Normalize direction
float len = (float) Math.sqrt(dirX * dirX + dirY * dirY);
if (Float.isNaN(len)) {
len = 0;
}
if (len != 0) {
dirX /= len;
dirY /= len;
}
posX += dirX;
posY += dirY;
// Stop simulating droplet if it's not moving or has flowed over edge of map
if ((dirX == 0 && dirY == 0) || posX < 0 || posX >= size - 1 || posY < 0 || posY >= size - 1) {
break;
}
// Find the droplet's new height and calculate the deltaHeight
float oldHeight = gradient.height;
float newHeight = gradient.update(cells, size, posX, posY).height;
float deltaHeight = newHeight - oldHeight;
// Calculate the droplet's sediment capacity (higher when moving fast down a slope and contains lots of water)
float sedimentCapacity = Math.max(-deltaHeight * speed * water * sedimentCapacityFactor, minSedimentCapacity);
// If carrying more sediment than capacity, or if flowing uphill:
if (sediment > sedimentCapacity || deltaHeight > 0) {
// If moving uphill (deltaHeight > 0) try fill up to the current height, otherwise deposit a fraction of the excess sediment
float amountToDeposit = (deltaHeight > 0) ? Math.min(deltaHeight, sediment) : (sediment - sedimentCapacity) * depositSpeed;
sediment -= amountToDeposit;
// Add the sediment to the four nodes of the current cell using bilinear interpolation
// Deposition is not distributed over a radius (like erosion) so that it can fill small pits
deposit(cells[dropletIndex], amountToDeposit * (1 - cellOffsetX) * (1 - cellOffsetY));
deposit(cells[dropletIndex + 1], amountToDeposit * cellOffsetX * (1 - cellOffsetY));
deposit(cells[dropletIndex + size], amountToDeposit * (1 - cellOffsetX) * cellOffsetY);
deposit(cells[dropletIndex + size + 1], amountToDeposit * cellOffsetX * cellOffsetY);
} else {
// Erode a fraction of the droplet's current carry capacity.
// Clamp the erosion to the change in height so that it doesn't dig a hole in the terrain behind the droplet
float amountToErode = Math.min((sedimentCapacity - sediment) * erodeSpeed, -deltaHeight);
// Use erosion brush to erode from all nodes inside the droplet's erosion radius
for (int brushPointIndex = 0; brushPointIndex < erosionBrushIndices[dropletIndex].length; brushPointIndex++) {
int nodeIndex = erosionBrushIndices[dropletIndex][brushPointIndex];
Cell<?> cell = cells[nodeIndex];
float brushWeight = erosionBrushWeights[dropletIndex][brushPointIndex];
float weighedErodeAmount = amountToErode * brushWeight;
float deltaSediment = Math.min(cell.value, weighedErodeAmount);//cell.value < weighedErodeAmount) ? cell.value : weighedErodeAmount;
erode(cell, deltaSediment);
sediment += deltaSediment;
}
}
// Update droplet's speed and water content
speed = (float) Math.sqrt(speed * speed + deltaHeight * gravity);
water *= (1 - evaporateSpeed);
if (Float.isNaN(speed)) {
speed = 0;
}
}
}
private void init(int size, int radius) {
erosionBrushIndices = new int[size * size][];
erosionBrushWeights = new float[size * size][];
int[] xOffsets = new int[radius * radius * 4];
int[] yOffsets = new int[radius * radius * 4];
float[] weights = new float[radius * radius * 4];
float weightSum = 0;
int addIndex = 0;
for (int i = 0; i < erosionBrushIndices.length; i++) {
int centreX = i % size;
int centreY = i / size;
if (centreY <= radius || centreY >= size - radius || centreX <= radius + 1 || centreX >= size - radius) {
weightSum = 0;
addIndex = 0;
for (int y = -radius; y <= radius; y++) {
for (int x = -radius; x <= radius; x++) {
float sqrDst = x * x + y * y;
if (sqrDst < radius * radius) {
int coordX = centreX + x;
int coordY = centreY + y;
if (coordX >= 0 && coordX < size && coordY >= 0 && coordY < size) {
float weight = 1 - (float) Math.sqrt(sqrDst) / radius;
weightSum += weight;
weights[addIndex] = weight;
xOffsets[addIndex] = x;
yOffsets[addIndex] = y;
addIndex++;
}
}
}
}
}
int numEntries = addIndex;
erosionBrushIndices[i] = new int[numEntries];
erosionBrushWeights[i] = new float[numEntries];
for (int j = 0; j < numEntries; j++) {
erosionBrushIndices[i][j] = (yOffsets[j] + centreY) * size + xOffsets[j] + centreX;
erosionBrushWeights[i][j] = weights[j] / weightSum;
}
}
}
private void deposit(Cell<?> cell, float amount) {
float change = modifier.modify(cell, amount);
cell.value += change;
cell.sediment += change;
}
private void erode(Cell<?> cell, float amount) {
float change = modifier.modify(cell, amount);
cell.value -= change;
cell.erosion -= change;
}
private static class TerrainPos {
private float height;
private float gradientX;
private float gradientY;
private TerrainPos update(Cell<?>[] nodes, int mapSize, float posX, float posY) {
int coordX = (int) posX;
int coordY = (int) posY;
// Calculate droplet's offset inside the cell (0,0) = at NW node, (1,1) = at SE node
float x = posX - coordX;
float y = posY - coordY;
// Calculate heights of the four nodes of the droplet's cell
int nodeIndexNW = coordY * mapSize + coordX;
float heightNW = nodes[nodeIndexNW].value;
float heightNE = nodes[nodeIndexNW + 1].value;
float heightSW = nodes[nodeIndexNW + mapSize].value;
float heightSE = nodes[nodeIndexNW + mapSize + 1].value;
// Calculate droplet's direction of flow with bilinear interpolation of height difference along the edges
this.gradientX = (heightNE - heightNW) * (1 - y) + (heightSE - heightSW) * y;
this.gradientY = (heightSW - heightNW) * (1 - x) + (heightSE - heightNE) * x;
// Calculate height with bilinear interpolation of the heights of the nodes of the cell
this.height = heightNW * (1 - x) * (1 - y) + heightNE * x * (1 - y) + heightSW * (1 - x) * y + heightSE * x * y;
return this;
}
}
}

View File

@ -1,47 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.filter;
import com.terraforged.core.cell.Cell;
public interface Filter {
void apply(Filterable<?> map, int seedX, int seedZ, int iterations);
default void iterate(Filterable<?> map, Visitor visitor) {
for (int dz = 0; dz < map.getSize().total; dz++) {
for (int dx = 0; dx < map.getSize().total; dx++) {
Cell<?> cell = map.getCellRaw(dx, dz);
visitor.visit(map, cell, dx, dz);
}
}
}
interface Visitor {
void visit(Filterable<?> cellMap, Cell cell, int dx, int dz);
}
}

View File

@ -1,39 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.filter;
import com.terraforged.core.cell.Cell;
import com.terraforged.core.cell.Tag;
import com.terraforged.core.region.Size;
public interface Filterable<T extends Tag> {
Size getSize();
Cell<T>[] getBacking();
Cell<T> getCellRaw(int x, int z);
}

View File

@ -1,61 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.filter;
import com.terraforged.core.cell.Cell;
public interface Modifier {
float getModifier(float value);
default float modify(Cell cell, float value) {
return value * getModifier(cell.value);
}
default Modifier invert() {
return v -> 1 - getModifier(v);
}
static Modifier range(float minValue, float maxValue) {
return new Modifier() {
private final float min = minValue;
private final float max = maxValue;
private final float range = maxValue - minValue;
@Override
public float getModifier(float value) {
if (value > max) {
return 1F;
}
if (value < min) {
return 0F;
}
return (value - min) / range;
}
};
}
}

View File

@ -1,90 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.filter;
import com.terraforged.core.cell.Cell;
import com.terraforged.core.settings.Settings;
import com.terraforged.core.world.heightmap.Levels;
import me.dags.noise.util.NoiseUtil;
public class Smoothing implements Filter {
private final int radius;
private final float rad2;
private final float strength;
private final Modifier modifier;
public Smoothing(Settings settings, Levels levels) {
this.radius = NoiseUtil.round(settings.filters.smoothing.smoothingRadius + 0.5F);
this.rad2 = settings.filters.smoothing.smoothingRadius * settings.filters.smoothing.smoothingRadius;
this.strength = settings.filters.smoothing.smoothingRate;
this.modifier = Modifier.range(levels.ground(1), levels.ground(120)).invert();
}
@Override
public void apply(Filterable<?> map, int seedX, int seedZ, int iterations) {
while (iterations-- > 0) {
apply(map);
}
}
private void apply(Filterable<?> cellMap) {
int maxZ = cellMap.getSize().total - radius;
int maxX = cellMap.getSize().total - radius;
for (int z = radius; z < maxZ; z++) {
for (int x = radius; x < maxX; x++) {
Cell<?> cell = cellMap.getCellRaw(x, z);
float total = 0;
float weights = 0;
for (int dz = -radius; dz <= radius; dz++) {
for (int dx = -radius; dx <= radius; dx++) {
float dist2 = dx * dx + dz * dz;
if (dist2 > rad2) {
continue;
}
int px = x + dx;
int pz = z + dz;
Cell<?> neighbour = cellMap.getCellRaw(px, pz);
if (neighbour.isAbsent()) {
continue;
}
float value = neighbour.value;
float weight = 1F - (dist2 / rad2);
total += (value * weight);
weights += weight;
}
}
if (weights > 0) {
float dif = cell.value - (total / weights);
cell.value -= modifier.modify(cell, dif * strength);
}
}
}
}
}

View File

@ -1,79 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.filter;
import com.terraforged.core.cell.Cell;
import com.terraforged.core.world.heightmap.Levels;
import com.terraforged.core.world.terrain.Terrains;
public class Steepness implements Filter, Filter.Visitor {
private final int radius;
private final float scaler;
private final float waterLevel;
private final float maxBeachLevel;
private final Terrains terrains;
public Steepness(int radius, float scaler, Terrains terrains, Levels levels) {
this.radius = radius;
this.scaler = scaler;
this.terrains = terrains;
this.waterLevel = levels.water;
this.maxBeachLevel = levels.water(6);
}
@Override
public void apply(Filterable<?> cellMap, int seedX, int seedZ, int iterations) {
iterate(cellMap, this);
}
@Override
public void visit(Filterable<?> cellMap, Cell cell, int cx, int cz) {
float totalHeightDif = 0F;
for (int dz = -1; dz <= 2; dz++) {
for (int dx = -1; dx <= 2; dx++) {
if (dx == 0 && dz == 0) {
continue;
}
int x = cx + dx * radius;
int z = cz + dz * radius;
Cell<?> neighbour = cellMap.getCellRaw(x, z);
if (neighbour.isAbsent()) {
continue;
}
float height = Math.max(neighbour.value, waterLevel);
totalHeightDif += (Math.abs(cell.value - height) / radius);
}
}
cell.steepness = Math.min(1, totalHeightDif * scaler);
if (cell.tag == terrains.coast && cell.steepness < 0.225F && cell.value < maxBeachLevel) {
cell.tag = terrains.beach;
}
}
}

View File

@ -1,116 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.module;
import com.terraforged.core.cell.Cell;
import com.terraforged.core.cell.Populator;
import com.terraforged.core.world.terrain.Terrain;
import me.dags.noise.Module;
import me.dags.noise.func.Interpolation;
import me.dags.noise.util.NoiseUtil;
public class Blender extends Select implements Populator {
private final Populator lower;
private final Populator upper;
private final float blendLower;
private final float blendUpper;
private final float blendRange;
private final float midpoint;
private final float tagThreshold;
public Blender(Module control, Populator lower, Populator upper, float min, float max, float split) {
super(control);
this.lower = lower;
this.upper = upper;
this.blendLower = min;
this.blendUpper = max;
this.blendRange = blendUpper - blendLower;
this.midpoint = blendLower + (blendRange * split);
this.tagThreshold = midpoint;
}
public Blender(Populator control, Populator lower, Populator upper, float min, float max, float split, float tagThreshold) {
super(control);
this.lower = lower;
this.upper = upper;
this.blendLower = min;
this.blendUpper = max;
this.blendRange = blendUpper - blendLower;
this.midpoint = blendLower + (blendRange * split);
this.tagThreshold = tagThreshold;
}
@Override
public void apply(Cell<Terrain> cell, float x, float y) {
float select = getSelect(cell, x, y);
if (select < blendLower) {
lower.apply(cell, x, y);
return;
}
if (select > blendUpper) {
upper.apply(cell, x, y);
return;
}
float alpha = Interpolation.LINEAR.apply((select - blendLower) / blendRange);
lower.apply(cell, x, y);
float lowerVal = cell.value;
Terrain lowerType = cell.tag;
upper.apply(cell, x, y);
float upperVal = cell.value;
cell.value = NoiseUtil.lerp(lowerVal, upperVal, alpha);
if (select < midpoint) {
cell.tag = lowerType;
}
}
@Override
public void tag(Cell<Terrain> cell, float x, float y) {
float select = getSelect(cell, x, y);
if (select < blendLower) {
lower.tag(cell, x, y);
return;
}
if (select > blendUpper) {
upper.tag(cell, x, y);
return;
}
if (select < tagThreshold) {
lower.tag(cell, x, y);
} else {
upper.tag(cell, x, y);
}
}
}

View File

@ -1,122 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.module;
import com.terraforged.core.cell.Cell;
import com.terraforged.core.cell.Populator;
import com.terraforged.core.world.climate.Climate;
import com.terraforged.core.world.terrain.Terrain;
import me.dags.noise.func.Interpolation;
import me.dags.noise.util.NoiseUtil;
public class MultiBlender extends Select implements Populator {
private final Climate climate;
private final Populator lower;
private final Populator middle;
private final Populator upper;
private final float midpoint;
private final float blendLower;
private final float blendUpper;
private final float lowerRange;
private final float upperRange;
public MultiBlender(Climate climate, Populator control, Populator lower, Populator middle, Populator upper, float min, float mid, float max) {
super(control);
this.climate = climate;
this.lower = lower;
this.upper = upper;
this.middle = middle;
this.midpoint = mid;
this.blendLower = min;
this.blendUpper = max;
this.lowerRange = midpoint - blendLower;
this.upperRange = blendUpper - midpoint;
}
@Override
public void apply(Cell<Terrain> cell, float x, float y) {
float select = getSelect(cell, x, y);
if (select < blendLower) {
lower.apply(cell, x, y);
return;
}
if (select > blendUpper) {
upper.apply(cell, x, y);
return;
}
if (select < midpoint) {
float alpha = Interpolation.CURVE3.apply((select - blendLower) / lowerRange);
lower.apply(cell, x, y);
float lowerVal = cell.value;
Terrain lowerType = cell.tag;
middle.apply(cell, x, y);
float upperVal = cell.value;
cell.value = NoiseUtil.lerp(lowerVal, upperVal, alpha);
} else {
float alpha = Interpolation.CURVE3.apply((select - midpoint) / upperRange);
middle.apply(cell, x, y);
float lowerVal = cell.value;
upper.apply(cell, x, y);
cell.value = NoiseUtil.lerp(lowerVal, cell.value, alpha);
}
}
@Override
public void tag(Cell<Terrain> cell, float x, float y) {
float select = getSelect(cell, x, y);
if (select < blendLower) {
lower.tag(cell, x, y);
return;
}
if (select > blendUpper) {
upper.tag(cell, x, y);
return;
}
if (select < midpoint) {
lower.tag(cell, x, y);
// upper.tag(cell, x, y);
if (cell.value > cell.tag.getMax(climate.getRand().getValue(x, y))) {
upper.tag(cell, x, y);
}
} else {
upper.tag(cell, x, y);
}
}
}

View File

@ -1,43 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.module;
import com.terraforged.core.cell.Cell;
import com.terraforged.core.world.terrain.Terrain;
import me.dags.noise.Module;
public class Select {
private final Module control;
public Select(Module control) {
this.control = control;
}
public float getSelect(Cell<Terrain> cell, float x, float y) {
return control.getValue(x, y);
}
}

View File

@ -1,404 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.region;
import com.terraforged.core.cell.Cell;
import com.terraforged.core.cell.Extent;
import com.terraforged.core.filter.Filterable;
import com.terraforged.core.region.chunk.ChunkReader;
import com.terraforged.core.region.chunk.ChunkWriter;
import com.terraforged.core.util.concurrent.Disposable;
import com.terraforged.core.world.decorator.Decorator;
import com.terraforged.core.world.heightmap.Heightmap;
import com.terraforged.core.world.rivermap.RiverRegionList;
import com.terraforged.core.world.terrain.Terrain;
import me.dags.noise.util.NoiseUtil;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
public class Region implements Extent, Disposable {
private final int regionX;
private final int regionZ;
private final int chunkX;
private final int chunkZ;
private final int blockX;
private final int blockZ;
private final int border;
private final Size blockSize;
private final Size chunkSize;
private final GenCell[] blocks;
private final GenChunk[] chunks;
private final int disposableChunks;
private final Disposable.Listener<Region> disposalListener;
private final AtomicInteger disposedChunks = new AtomicInteger();
public Region(int regionX, int regionZ, int size, int borderChunks) {
this(regionX, regionZ, size, borderChunks, region -> {});
}
public Region(int regionX, int regionZ, int size, int borderChunks, Disposable.Listener<Region> disposalListener) {
this.regionX = regionX;
this.regionZ = regionZ;
this.chunkX = regionX << size;
this.chunkZ = regionZ << size;
this.blockX = Size.chunkToBlock(chunkX);
this.blockZ = Size.chunkToBlock(chunkZ);
this.border = borderChunks;
this.chunkSize = Size.chunks(size, borderChunks);
this.blockSize = Size.blocks(size, borderChunks);
this.disposalListener = disposalListener;
this.disposableChunks = chunkSize.size * chunkSize.size;
this.blocks = new GenCell[blockSize.total * blockSize.total];
this.chunks = new GenChunk[chunkSize.total * chunkSize.total];
}
@Override
public void dispose() {
int disposed = disposedChunks.incrementAndGet();
if (disposed < disposableChunks) {
return;
}
disposalListener.onDispose(this);
}
public long getRegionId() {
return NoiseUtil.seed(getRegionX(), getRegionZ());
}
public int getRegionX() {
return regionX;
}
public int getRegionZ() {
return regionZ;
}
public int getBlockX() {
return blockX;
}
public int getBlockZ() {
return blockZ;
}
public int getOffsetChunks() {
return border;
}
public int getChunkCount() {
return chunks.length;
}
public int getBlockCount() {
return blocks.length;
}
public Size getChunkSize() {
return chunkSize;
}
public Size getBlockSize() {
return blockSize;
}
public Filterable<Terrain> filterable() {
return new FilterRegion();
}
public Cell<Terrain> getCell(int blockX, int blockZ) {
int relBlockX = blockSize.border + blockSize.mask(blockX);
int relBlockZ = blockSize.border + blockSize.mask(blockZ);
int index = blockSize.indexOf(relBlockX, relBlockZ);
return blocks[index];
}
public Cell<Terrain> getRawCell(int blockX, int blockZ) {
int index = blockSize.indexOf(blockX, blockZ);
return blocks[index];
}
public ChunkReader getChunk(int chunkX, int chunkZ) {
int relChunkX = chunkSize.border + chunkSize.mask(chunkX);
int relChunkZ = chunkSize.border + chunkSize.mask(chunkZ);
int index = chunkSize.indexOf(relChunkX, relChunkZ);
return chunks[index];
}
public void generate(Consumer<ChunkWriter> consumer) {
for (int cz = 0; cz < chunkSize.total; cz++) {
for (int cx = 0; cx < chunkSize.total; cx++) {
int index = chunkSize.indexOf(cx, cz);
GenChunk chunk = computeChunk(index, cx, cz);
consumer.accept(chunk);
}
}
}
public void generateBase(Heightmap heightmap) {
for (int cz = 0; cz < chunkSize.total; cz++) {
for (int cx = 0; cx < chunkSize.total; cx++) {
int index = chunkSize.indexOf(cx, cz);
GenChunk chunk = computeChunk(index, cx, cz);
for (int dz = 0; dz < 16; dz++) {
for (int dx = 0; dx < 16; dx++) {
float x = chunk.getBlockX() + dx;
float z = chunk.getBlockZ() + dz;
Cell<Terrain> cell = chunk.genCell(dx, dz);
heightmap.applyBase(cell, x, z);
}
}
}
}
}
public void generateRivers(Heightmap heightmap, RiverRegionList rivers) {
for (int cz = 0; cz < chunkSize.total; cz++) {
for (int cx = 0; cx < chunkSize.total; cx++) {
int index = chunkSize.indexOf(cx, cz);
GenChunk chunk = computeChunk(index, cx, cz);
for (int dz = 0; dz < 16; dz++) {
for (int dx = 0; dx < 16; dx++) {
float x = chunk.getBlockX() + dx;
float z = chunk.getBlockZ() + dz;
Cell<Terrain> cell = chunk.genCell(dx, dz);
heightmap.applyRivers(cell, x, z, rivers);
heightmap.applyClimate(cell, x, z);
}
}
}
}
}
public void generateZoom(Heightmap heightmap, float offsetX, float offsetZ, float zoom) {
float translateX = offsetX - ((blockSize.size * zoom) / 2F);
float translateZ = offsetZ - ((blockSize.size * zoom) / 2F);
for (int cz = 0; cz < chunkSize.total; cz++) {
for (int cx = 0; cx < chunkSize.total; cx++) {
int index = chunkSize.indexOf(cx, cz);
GenChunk chunk = computeChunk(index, cx, cz);
for (int dz = 0; dz < 16; dz++) {
for (int dx = 0; dx < 16; dx++) {
float x = ((chunk.getBlockX() + dx) * zoom) + translateX;
float z = ((chunk.getBlockZ() + dz) * zoom) + translateZ;
Cell<Terrain> cell = chunk.genCell(dx, dz);
heightmap.apply(cell, x, z);
}
}
}
}
}
public void decorate(Collection<Decorator> decorators) {
for (int dz = 0; dz < blockSize.total; dz++) {
for (int dx = 0; dx < blockSize.total; dx++) {
int index = blockSize.indexOf(dx, dz);
GenCell cell = blocks[index];
for (Decorator decorator : decorators) {
if (decorator.apply(cell, getBlockX() + dx, getBlockZ() + dz)) {
break;
}
}
}
}
}
public void decorateZoom(Collection<Decorator> decorators, float offsetX, float offsetZ, float zoom) {
float translateX = offsetX - ((blockSize.size * zoom) / 2F);
float translateZ = offsetZ - ((blockSize.size * zoom) / 2F);
for (int cz = 0; cz < chunkSize.total; cz++) {
for (int cx = 0; cx < chunkSize.total; cx++) {
int index = chunkSize.indexOf(cx, cz);
GenChunk chunk = computeChunk(index, cx, cz);
chunk.iterate((cell, dx, dz) -> {
float x = ((chunk.getBlockX() + dx) * zoom) + translateX;
float z = ((chunk.getBlockZ() + dz) * zoom) + translateZ;
for (Decorator decorator : decorators) {
decorator.apply(cell, x, z);
}
});
}
}
}
public void iterate(Consumer<ChunkReader> consumer) {
for (int cz = 0; cz < chunkSize.size; cz++) {
int chunkZ = chunkSize.border + cz;
for (int cx = 0; cx < chunkSize.size; cx++) {
int chunkX = chunkSize.border + cx;
int index = chunkSize.indexOf(chunkX, chunkZ);
GenChunk chunk = chunks[index];
consumer.accept(chunk);
}
}
}
public void iterate(Cell.Visitor<Terrain> visitor) {
for (int dz = 0; dz < blockSize.size; dz++) {
int z = blockSize.border + dz;
for (int dx = 0; dx < blockSize.size; dx++) {
int x = blockSize.border + dx;
int index = blockSize.indexOf(x, z);
GenCell cell = blocks[index];
visitor.visit(cell, dx, dz);
}
}
}
@Override
public void visit(int minX, int minZ, int maxX, int maxZ, Cell.Visitor<Terrain> visitor) {
int regionMinX = getBlockX();
int regionMinZ = getBlockZ();
if (maxX < regionMinX || maxZ < regionMinZ) {
return;
}
int regionMaxX = getBlockX() + getBlockSize().size - 1;
int regionMaxZ = getBlockZ() + getBlockSize().size - 1;
if (minX > regionMaxX || maxZ > regionMaxZ) {
return;
}
minX = Math.max(minX, regionMinX);
minZ = Math.max(minZ, regionMinZ);
maxX = Math.min(maxX, regionMaxX);
maxZ = Math.min(maxZ, regionMaxZ);
for (int z = minZ; z <= maxX; z++) {
for (int x = minX; x <= maxZ; x++) {
visitor.visit(getCell(x, z), x, z);
}
}
}
private GenChunk computeChunk(int index, int chunkX, int chunkZ) {
GenChunk chunk = chunks[index];
if (chunk == null) {
chunk = new GenChunk(chunkX, chunkZ);
chunks[index] = chunk;
}
return chunk;
}
private GenCell computeCell(int index) {
GenCell cell = blocks[index];
if (cell == null) {
cell = new GenCell();
blocks[index] = cell;
}
return cell;
}
private static class GenCell extends Cell<Terrain> {}
private class GenChunk implements ChunkReader, ChunkWriter {
private final int chunkX;
private final int chunkZ;
private final int blockX;
private final int blockZ;
private final int regionBlockX;
private final int regionBlockZ;
// 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 - getOffsetChunks();
this.chunkZ = Region.this.chunkZ + regionChunkZ - getOffsetChunks();
// the real block coordinate of this chunk within the world
this.blockX = chunkX << 4;
this.blockZ = chunkZ << 4;
}
@Override
public int getChunkX() {
return chunkX;
}
@Override
public int getChunkZ() {
return chunkZ;
}
@Override
public int getBlockX() {
return blockX;
}
@Override
public int getBlockZ() {
return blockZ;
}
@Override
public void dispose() {
Region.this.dispose();
}
@Override
public Cell<Terrain> getCell(int blockX, int blockZ) {
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 = regionBlockX + (blockX & 15);
int relZ = regionBlockZ + (blockZ & 15);
int index = blockSize.indexOf(relX, relZ);
return computeCell(index);
}
}
private class FilterRegion implements Filterable<Terrain> {
@Override
public Size getSize() {
return blockSize;
}
@Override
public Cell<Terrain>[] getBacking() {
return blocks;
}
@Override
public Cell<Terrain> getCellRaw(int x, int z) {
int index = blockSize.indexOf(x, z);
if (index < 0 || index >= blocks.length) {
return Cell.empty();
}
return blocks[index];
}
}
}

View File

@ -1,8 +0,0 @@
package com.terraforged.core.region;
import com.terraforged.core.util.concurrent.Disposable;
public interface RegionFactory {
Region create(int regionX, int regionZ, int size, int borderChunks, Disposable.Listener<Region> listener);
}

View File

@ -1,75 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.region;
public class Size {
public final int size;
public final int total;
public final int border;
private final int mask;
public Size(int size, int border) {
this.size = size;
this.mask = size - 1;
this.border = border;
this.total = size + (2 * border);
}
public int mask(int i) {
return i & mask;
}
public int indexOf(int x, int z) {
return (z * total) + x;
}
public static int chunkToBlock(int i) {
return i << 4;
}
public static int blockToChunk(int i) {
return i >> 4;
}
public static int count(int minX, int minZ, int maxX, int maxZ) {
int dx = maxX - minX;
int dz = maxZ - minZ;
return dx * dz;
}
public static Size chunks(int factor, int borderChunks) {
int chunks = 1 << factor;
return new Size(chunks, borderChunks);
}
public static Size blocks(int factor, int borderChunks) {
int chunks = 1 << factor;
int blocks = chunks << 4;
int borderBlocks = borderChunks << 4;
return new Size(blocks, borderBlocks);
}
}

View File

@ -1,48 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.region.chunk;
import com.terraforged.core.world.heightmap.Heightmap;
public class ChunkGenTask implements Runnable {
protected final ChunkWriter chunk;
protected final Heightmap heightmap;
public ChunkGenTask(ChunkWriter chunk, Heightmap heightmap) {
this.chunk = chunk;
this.heightmap = heightmap;
}
@Override
public void run() {
chunk.generate((cell, dx, dz) -> {
float x = chunk.getBlockX() + dx;
float z = chunk.getBlockZ() + dz;
heightmap.apply(cell, x, z);
});
}
}

View File

@ -1,40 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.region.chunk;
import com.terraforged.core.cell.Extent;
import com.terraforged.core.util.concurrent.Disposable;
public interface ChunkHolder extends Extent, Disposable {
int getChunkX();
int getChunkZ();
int getBlockX();
int getBlockZ();
}

View File

@ -1,76 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.region.chunk;
import com.terraforged.core.cell.Cell;
import com.terraforged.core.world.terrain.Terrain;
public interface ChunkReader extends ChunkHolder {
Cell<Terrain> getCell(int dx, int dz);
@Override
default void visit(int minX, int minZ, int maxX, int maxZ, Cell.Visitor<Terrain> visitor) {
int regionMinX = getBlockX();
int regionMinZ = getBlockZ();
if (maxX < regionMinX || maxZ < regionMinZ) {
return;
}
int regionMaxX = getBlockX() + 15;
int regionMaxZ = getBlockZ() + 15;
if (minX > regionMaxX || maxZ > regionMaxZ) {
return;
}
minX = Math.max(minX, regionMinX);
minZ = Math.max(minZ, regionMinZ);
maxX = Math.min(maxX, regionMaxX);
maxZ = Math.min(maxZ, regionMaxZ);
for (int z = minZ; z <= maxX; z++) {
for (int x = minX; x <= maxZ; x++) {
visitor.visit(getCell(x, z), x, z);
}
}
}
default void iterate(Cell.Visitor<Terrain> visitor) {
for (int dz = 0; dz < 16; dz++) {
for (int dx = 0; dx < 16; dx++) {
visitor.visit(getCell(dx, dz), dx, dz);
}
}
}
default <C> void iterate(C context, Cell.ContextVisitor<C, Terrain> visitor) {
for (int dz = 0; dz < 16; dz++) {
for (int dx = 0; dx < 16; dx++) {
visitor.visit(getCell(dx, dz), dx, dz, context);
}
}
}
}

View File

@ -1,42 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.region.chunk;
import com.terraforged.core.cell.Cell;
import com.terraforged.core.world.terrain.Terrain;
public interface ChunkWriter extends ChunkHolder {
Cell<Terrain> genCell(int dx, int dz);
default void generate(Cell.Visitor<Terrain> visitor) {
for (int dz = 0; dz < 16; dz++) {
for (int dx = 0; dx < 16; dx++) {
visitor.visit(genCell(dx, dz), dx, dz);
}
}
}
}

View File

@ -1,51 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.region.chunk;
import com.terraforged.core.world.heightmap.Heightmap;
public class ChunkZoomTask extends ChunkGenTask {
private final float translateX;
private final float translateZ;
private final float zoom;
public ChunkZoomTask(ChunkWriter chunk, Heightmap heightmap, float translateX, float translateZ, float zoom) {
super(chunk, heightmap);
this.translateX = translateX;
this.translateZ = translateZ;
this.zoom = zoom;
}
@Override
public void run() {
chunk.generate((cell, dx, dz) -> {
float x = ((chunk.getBlockX() + dx) * zoom) + translateX;
float z = ((chunk.getBlockZ() + dz) * zoom) + translateZ;
heightmap.apply(cell, x, z);
});
}
}

View File

@ -1,57 +0,0 @@
package com.terraforged.core.region.gen;
import com.terraforged.core.region.Region;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class FutureRegion implements Future<Region>, Callable<Region> {
private final int rx;
private final int rz;
private final RegionGenerator generator;
private volatile Region result;
public FutureRegion(int rx, int rz, RegionGenerator generator) {
this.rx = rx;
this.rz = rz;
this.generator = generator;
}
@Override
public Region call() {
Region region = result;
if (region == null) {
region = generator.generateRegion(rx, rz);
result = region;
}
return region;
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
return false;
}
@Override
public boolean isCancelled() {
return false;
}
@Override
public boolean isDone() {
return result != null;
}
@Override
public Region get() {
return call();
}
@Override
public Region get(long timeout, TimeUnit unit) {
return get();
}
}

View File

@ -1,61 +0,0 @@
package com.terraforged.core.region.gen;
import com.terraforged.core.region.Region;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class FutureRegionZoom implements Future<Region>, Callable<Region> {
private final float cx;
private final float cz;
private final float zoom;
private final boolean filters;
private final RegionGenerator generator;
private volatile Region result;
public FutureRegionZoom(float cx, float cz, float zoom, boolean filters, RegionGenerator generator) {
this.cx = cx;
this.cz = cz;
this.zoom = zoom;
this.filters = filters;
this.generator = generator;
}
@Override
public Region call() {
Region region = result;
if (region == null) {
region = generator.generateRegion(cx, cz, zoom, filters);
result = region;
}
return region;
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
return false;
}
@Override
public boolean isCancelled() {
return false;
}
@Override
public boolean isDone() {
return result != null;
}
@Override
public Region get() {
return call();
}
@Override
public Region get(long timeout, TimeUnit unit) {
return get();
}
}

View File

@ -1,21 +0,0 @@
package com.terraforged.core.region.gen;
import com.terraforged.core.world.WorldGenerator;
import com.terraforged.core.world.WorldGeneratorFactory;
import com.terraforged.core.world.rivermap.RiverRegionList;
import java.util.function.Supplier;
public class GenContext {
public final WorldGenerator generator;
public final RiverRegionList rivers = new RiverRegionList();
public GenContext(WorldGenerator generator) {
this.generator = generator;
}
public static Supplier<GenContext> supplier(WorldGeneratorFactory factory) {
return () -> new GenContext(factory.get());
}
}

View File

@ -1,105 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.region.gen;
import com.terraforged.core.region.Region;
import com.terraforged.core.region.chunk.ChunkReader;
import com.terraforged.core.util.concurrent.Disposable;
import com.terraforged.core.util.concurrent.cache.Cache;
import com.terraforged.core.util.concurrent.cache.CacheEntry;
import com.terraforged.core.world.heightmap.RegionExtent;
import me.dags.noise.util.NoiseUtil;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
public class RegionCache implements RegionExtent, Disposable.Listener<Region> {
private final boolean queuing;
private final RegionGenerator generator;
private final Cache<CacheEntry<Region>> cache;
public RegionCache(boolean queueNeighbours, RegionGenerator generator) {
this.queuing = queueNeighbours;
this.generator = new RegionGenerator(generator, this);
this.cache = new Cache<>(60, 30, TimeUnit.SECONDS);
}
@Override
public void onDispose(Region region) {
cache.remove(region.getRegionId());
}
@Override
public int chunkToRegion(int coord) {
return generator.chunkToRegion(coord);
}
@Override
public CompletableFuture<Region> getRegionAsync(int regionX, int regionZ) {
return generator.generate(regionX, regionZ);
}
@Override
public ChunkReader getChunk(int chunkX, int chunkZ) {
int regionX = generator.chunkToRegion(chunkX);
int regionZ = generator.chunkToRegion(chunkZ);
Region region = getRegion(regionX, regionZ);
return region.getChunk(chunkX, chunkZ);
}
@Override
public Region getRegion(int regionX, int regionZ) {
Region region = computeRegion(regionX, regionZ).get();
if (queuing) {
queueNeighbours(regionX, regionZ);
}
return region;
}
private CacheEntry<Region> computeRegion(int regionX, int regionZ) {
long id = NoiseUtil.seed(regionX, regionZ);
return cache.computeIfAbsent(id, l -> generator.compute(regionX, regionZ));
}
public CacheEntry<Region> queueRegion(int regionX, int regionZ) {
long id = NoiseUtil.seed(regionX, regionZ);
return cache.computeIfAbsent(id, l -> generator.queue(regionX, regionZ));
}
private void queueNeighbours(int regionX, int regionZ) {
for (int z = -1; z <= 1; z++) {
for (int x = -1; x <= 1; x++){
if (x == 0 && z == 0) {
continue;
}
queueRegion(regionX + x, regionZ + z);
}
}
}
}

View File

@ -1,33 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.region.gen;
import com.terraforged.core.world.WorldGeneratorFactory;
public interface RegionCacheFactory {
RegionCache create(WorldGeneratorFactory factory);
}

View File

@ -1,204 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.region.gen;
import com.terraforged.core.region.Region;
import com.terraforged.core.region.RegionFactory;
import com.terraforged.core.region.legacy.LegacyRegion;
import com.terraforged.core.util.concurrent.Disposable;
import com.terraforged.core.util.concurrent.ObjectPool;
import com.terraforged.core.util.concurrent.ThreadPool;
import com.terraforged.core.util.concurrent.cache.CacheEntry;
import com.terraforged.core.world.WorldGenerator;
import com.terraforged.core.world.WorldGeneratorFactory;
import com.terraforged.core.world.heightmap.RegionExtent;
import com.terraforged.core.world.rivermap.RiverRegionList;
import java.util.concurrent.CompletableFuture;
public class RegionGenerator implements RegionExtent {
private final int factor;
private final int border;
private final RegionFactory regions;
private final ThreadPool threadPool;
private final ObjectPool<GenContext> genPool;
private final Disposable.Listener<Region> disposalListener;
private RegionGenerator(Builder builder) {
this.factor = builder.factor;
this.border = builder.border;
this.threadPool = builder.threadPool;
this.regions = builder.regionFactory;
this.genPool = new ObjectPool<>(6, GenContext.supplier(builder.factory));
this.disposalListener = region -> {};
}
protected RegionGenerator(RegionGenerator from, Disposable.Listener<Region> listener) {
this.factor = from.factor;
this.border = from.border;
this.threadPool = from.threadPool;
this.regions = from.regions;
this.genPool = from.genPool;
this.disposalListener = listener;
}
public RegionCache toCache() {
return toCache(true);
}
public RegionCache toCache(boolean queueNeighbours) {
return new RegionCache(queueNeighbours, this);
}
@Override
public int chunkToRegion(int i) {
return i >> factor;
}
@Override
public Region getRegion(int regionX, int regionZ) {
return generateRegion(regionX, regionZ);
}
@Override
public CompletableFuture<Region> getRegionAsync(int regionX, int regionZ) {
return generate(regionX, regionZ);
}
public CompletableFuture<Region> generate(int regionX, int regionZ) {
return CompletableFuture.supplyAsync(() -> generateRegion(regionX, regionZ), threadPool);
}
public CompletableFuture<Region> generate(float centerX, float centerZ, float zoom, boolean filter) {
return CompletableFuture.supplyAsync(() -> generateRegion(centerX, centerZ, zoom, filter), threadPool);
}
public CacheEntry<Region> compute(int regionX, int regionZ) {
return CacheEntry.supply(new FutureRegion(regionX, regionZ, this));
}
public CacheEntry<Region> compute(float centerX, float centerZ, float zoom, boolean filter) {
return CacheEntry.supply(new FutureRegionZoom(centerX, centerZ, zoom, filter, this));
}
public CacheEntry<Region> queue(int regionX, int regionZ) {
return CacheEntry.supplyAsync(new FutureRegion(regionX, regionZ, this), threadPool);
}
public CacheEntry<Region> queue(float centerX, float centerZ, float zoom, boolean filter) {
return CacheEntry.supplyAsync(new FutureRegionZoom(centerX, centerZ, zoom, filter, this), threadPool);
}
public Region generateRegion(int regionX, int regionZ) {
try (ObjectPool.Item<GenContext> item = genPool.get()) {
RiverRegionList rivers = item.getValue().rivers;
WorldGenerator generator = item.getValue().generator;
Region region = regions.create(regionX, regionZ, factor, border, disposalListener);
generator.getHeightmap().getRiverMap().getRivers(region, rivers);
region.generateBase(generator.getHeightmap());
region.generateRivers(generator.getHeightmap(), rivers);
postProcess(region, generator);
rivers.clear();
return region;
}
}
private void postProcess(Region region, WorldGenerator generator) {
generator.getFilters().apply(region);
region.decorate(generator.getDecorators().getDecorators());
}
public Region generateRegion(float centerX, float centerZ, float zoom, boolean filter) {
try (ObjectPool.Item<GenContext> item = genPool.get()) {
WorldGenerator generator = item.getValue().generator;
Region region = regions.create(0, 0, factor, border, disposalListener);
region.generateZoom(generator.getHeightmap(), centerX, centerZ, zoom);
postProcess(region, generator, centerX, centerZ, zoom, filter);
return region;
}
}
private void postProcess(Region region, WorldGenerator generator, float centerX, float centerZ, float zoom, boolean filter) {
if (filter) {
generator.getFilters().apply(region);
}
region.decorateZoom(generator.getDecorators().getDecorators(), centerX, centerZ, zoom);
}
public static Builder builder() {
return new Builder();
}
public static class Builder {
private int factor = 0;
private int border = 0;
private ThreadPool threadPool;
private WorldGeneratorFactory factory;
private RegionFactory regionFactory = Region::new;
public Builder size(int factor, int border) {
return factor(factor).border(border);
}
public Builder factor(int factor) {
this.factor = factor;
return this;
}
public Builder border(int border) {
this.border = border;
return this;
}
public Builder pool(ThreadPool threadPool) {
this.threadPool = threadPool;
return this;
}
public Builder regions(RegionFactory factory) {
this.regionFactory = factory;
return this;
}
public Builder legacy(boolean legacy) {
if (legacy) {
return regions(LegacyRegion::new);
}
return this;
}
public Builder factory(WorldGeneratorFactory factory) {
this.factory = factory;
return this;
}
public RegionGenerator build() {
return new RegionGenerator(this);
}
}
}

View File

@ -1,27 +0,0 @@
package com.terraforged.core.region.legacy;
import com.terraforged.core.region.Region;
import com.terraforged.core.util.concurrent.Disposable;
/**
* This is here to provide compatibility for versions 0.0.2 and below which contained a
* bug where Regions generated with an x,z offset equal to the size of the chunk border
* around the region (x16) ie 32 blocks
*/
public class LegacyRegion extends Region {
public LegacyRegion(int regionX, int regionZ, int size, int borderChunks, Disposable.Listener<Region> listener) {
super(regionX, regionZ, size, borderChunks, listener);
}
/**
* This is used when calculating the 'real world' chunk position of the chunk-view
* and subsequently the 'real world' block start position. In versions 0.0.2 and
* below, no offset was being deducted, so return 0 here to maintain that broken
* behaviour... RIP :/
*/
@Override
public int getOffsetChunks() {
return 0;
}
}

View File

@ -1,104 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.settings;
import com.terraforged.core.util.serialization.annotation.Comment;
import com.terraforged.core.util.serialization.annotation.Range;
import com.terraforged.core.util.serialization.annotation.Serializable;
import com.terraforged.core.world.biome.BiomeType;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class BiomeSettings {
public BiomeGroup desert = new BiomeGroup(BiomeType.DESERT);
public BiomeGroup steppe = new BiomeGroup(BiomeType.STEPPE);
public BiomeGroup coldSteppe = new BiomeGroup(BiomeType.COLD_STEPPE);
public BiomeGroup grassland = new BiomeGroup(BiomeType.GRASSLAND);
public BiomeGroup savanna = new BiomeGroup(BiomeType.SAVANNA);
public BiomeGroup taiga = new BiomeGroup(BiomeType.TAIGA);
public BiomeGroup temperateForest = new BiomeGroup(BiomeType.TEMPERATE_FOREST);
public BiomeGroup temperateRainForest = new BiomeGroup(BiomeType.TEMPERATE_RAINFOREST);
public BiomeGroup tropicalRainForest = new BiomeGroup(BiomeType.TROPICAL_RAINFOREST);
public BiomeGroup tundra = new BiomeGroup(BiomeType.TUNDRA);
public List<BiomeGroup> asList() {
return Arrays.asList(
desert,
steppe,
coldSteppe,
grassland,
savanna,
taiga,
temperateForest,
temperateRainForest,
tropicalRainForest,
tundra
);
}
public Map<BiomeType, BiomeGroup> asMap() {
return asList().stream().collect(Collectors.toMap(g -> g.type, g -> g));
}
@Serializable
public static class BiomeGroup {
public BiomeType type;
public BiomeWeight[] biomes = new BiomeWeight[0];
public BiomeGroup() {
}
public BiomeGroup(BiomeType biomeType) {
this.type = biomeType;
}
}
@Serializable
public static class BiomeWeight {
public String id;
@Range(min = 0, max = 50)
@Comment("Controls how common this biome type is")
public int weight;
public BiomeWeight() {
}
public BiomeWeight(String id, int weight) {
this.id = id;
this.weight = weight;
}
}
}

View File

@ -1,54 +0,0 @@
package com.terraforged.core.settings;
import com.terraforged.core.util.serialization.annotation.Comment;
import com.terraforged.core.util.serialization.annotation.Range;
import com.terraforged.core.util.serialization.annotation.Serializable;
import me.dags.noise.Module;
import me.dags.noise.Source;
@Serializable
public class ClimateSettings {
public RangeValue moisture = new RangeValue(0, 1F);
public RangeValue temperature = new RangeValue(0, 1F);
@Serializable
public static class RangeValue {
@Range(min = 0F, max = 1F)
@Comment("The lower limit of the range")
public float min;
@Range(min = 0F, max = 1F)
@Comment("The upper limit of the range")
public float max;
public RangeValue() {
this(0, 1);
}
public RangeValue(float min, float max) {
this.min = min;
this.max = max;
}
public float getMin() {
return Math.min(min, max);
}
public float getMax() {
return Math.max(min, max);
}
public Module clamp(Module module) {
float min = getMin();
float max = getMax();
float range = max - min;
if (range == 0) {
return Source.constant(min);
}
return module.scale(range).bias(min);
}
}
}

View File

@ -1,70 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.settings;
import com.terraforged.core.util.serialization.annotation.Comment;
import com.terraforged.core.util.serialization.annotation.Range;
import com.terraforged.core.util.serialization.annotation.Serializable;
@Serializable
public class FilterSettings {
public Erosion erosion = new Erosion();
public Smoothing smoothing = new Smoothing();
@Serializable
public static class Erosion {
@Range(min = 1000, max = 50000)
@Comment("Controls the number of erosion iterations")
public int iterations = 12000;
@Range(min = 0F, max = 1F)
@Comment("Controls how quickly material dissolves (during erosion)")
public float erosionRate = 0.5F;
@Range(min = 0F, max = 1F)
@Comment("Controls how quickly material is deposited (during erosion)")
public float depositeRate = 0.2F;
}
@Serializable
public static class Smoothing {
@Range(min = 0, max = 5)
@Comment("Controls the number of smoothing iterations")
public int iterations = 1;
@Range(min = 0, max = 5)
@Comment("Controls the smoothing radius")
public float smoothingRadius = 1.75F;
@Range(min = 0, max = 1)
@Comment("Controls how strongly smoothing is applied")
public float smoothingRate = 0.85F;
}
}

View File

@ -1,136 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.settings;
import com.terraforged.core.util.serialization.annotation.Comment;
import com.terraforged.core.util.serialization.annotation.Name;
import com.terraforged.core.util.serialization.annotation.Range;
import com.terraforged.core.util.serialization.annotation.Serializable;
import me.dags.noise.Module;
import me.dags.noise.Source;
@Serializable
public class GeneratorSettings {
public transient long seed = 0L;
/**
* WORLD PROPERTIES
*/
public World world = new World();
/**
* TERRAIN PROPERTIES
*/
public Land land = new Land();
/**
* BIOME PROPERTIES
*/
public Biome biome = new Biome();
public BiomeNoise biomeEdgeNoise = new BiomeNoise();
@Serializable
public static class World {
@Range(min = 0, max = 256)
@Comment("Controls the world height")
public int worldHeight = 256;
@Range(min = 0, max = 255)
@Comment("Controls the sea level")
public int seaLevel = 63;
@Range(min = 0F, max = 1F)
@Comment("Controls the amount of ocean between continents")
public float oceanSize = 0.25F;
}
@Serializable
public static class Land {
@Range(min = 100, max = 10000)
@Comment("Controls the size of continents")
public int continentScale = 4000;
@Range(min = 250, max = 5000)
@Name("Mountain Range Scale")
@Comment("Controls the size of mountain ranges")
public int mountainScale = 950;
@Range(min = 125, max = 5000)
@Comment("Controls the size of terrain regions")
public int regionSize = 1000;
}
@Serializable
public static class Biome {
@Range(min = 50, max = 1000)
@Comment("Controls the size of individual biomes")
public int biomeSize = 200;
@Range(min = 1, max = 500)
@Comment("Controls the scale of shape distortion for biomes")
public int biomeWarpScale = 35;
@Range(min = 1, max = 500)
@Comment("Controls the strength of shape distortion for biomes")
public int biomeWarpStrength = 70;
}
@Serializable
public static class BiomeNoise {
@Comment("The noise type")
public Source type = Source.PERLIN;
@Range(min = 1, max = 500)
@Comment("Controls the scale of the noise")
public int scale = 8;
@Range(min = 1, max = 5)
@Comment("Controls the number of noise octaves")
public int octaves = 2;
@Range(min = 0F, max = 5.5F)
@Comment("Controls the gain subsequent noise octaves")
public float gain = 0.5F;
@Range(min = 0F, max = 10.5F)
@Comment("Controls the lacunarity of subsequent noise octaves")
public float lacunarity = 2.5F;
@Range(min = 1, max = 500)
@Comment("Controls the strength of the noise")
public int strength = 24;
public Module build(int seed) {
return Source.build(seed, scale, octaves).gain(gain).lacunarity(lacunarity).build(type).bias(-0.5);
}
}
}

View File

@ -1,128 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.settings;
import com.terraforged.core.util.serialization.annotation.Comment;
import com.terraforged.core.util.serialization.annotation.Range;
import com.terraforged.core.util.serialization.annotation.Serializable;
@Serializable
public class RiverSettings {
/**
* RIVER PROPERTIES
*/
@Range(min = 0.0F, max = 5F)
@Comment("Controls how frequently rivers generate")
public float riverFrequency = 1;
public River primaryRivers = new River(5, 2, 8, 25, 8, 0.75F);
public River secondaryRiver = new River(4, 1, 6, 15, 5, 0.75F);
public River tertiaryRivers = new River(3, 0, 4, 10, 4, 0.75F);
public Lake lake = new Lake();
@Serializable
public static class River {
@Range(min = 1, max = 10)
@Comment("Controls the depth of the river")
public int bedDepth;
@Range(min = 0, max = 10)
@Comment("Controls the height of river banks")
public int minBankHeight;
@Range(min = 1, max = 10)
@Comment("Controls the height of river banks")
public int maxBankHeight;
@Range(min = 1, max = 20)
@Comment("Controls the river-bed width")
public int bedWidth;
@Range(min = 1, max = 50)
@Comment("Controls the river-banks width")
public int bankWidth;
@Range(min = 0.0F, max = 1.0F)
@Comment("Controls how much rivers taper")
public float fade;
public River() {
}
public River(int depth, int minBank, int maxBank, int outer, int inner, float fade) {
this.minBankHeight = minBank;
this.maxBankHeight = maxBank;
this.bankWidth = outer;
this.bedWidth = inner;
this.bedDepth = depth;
this.fade = fade;
}
}
public static class Lake {
@Range(min = 0.0F, max = 1.0F)
@Comment("Controls the chance of a lake spawning")
public float chance = 0.2F;
@Range(min = 0F, max = 1F)
@Comment("The minimum distance along a river that a lake will spawn")
public float minStartDistance = 0.03F;
@Range(min = 0F, max = 1F)
@Comment("The maximum distance along a river that a lake will spawn")
public float maxStartDistance = 0.07F;
@Range(min = 1, max = 20)
@Comment("The max depth of the lake")
public int depth = 10;
@Range(min = 10, max = 50)
@Comment("The minimum size of the lake")
public int sizeMin = 50;
@Range(min = 50, max = 150)
@Comment("The maximum size of the lake")
public int sizeMax = 100;
@Range(min = 1, max = 10)
@Comment("The minimum bank height")
public int minBankHeight = 2;
@Range(min = 1, max = 10)
@Comment("The maximum bank height")
public int maxBankHeight = 10;
public Lake() {
}
}
}

View File

@ -1,44 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.settings;
import com.terraforged.core.util.serialization.annotation.Serializable;
@Serializable
public class Settings {
public GeneratorSettings generator = new GeneratorSettings();
public ClimateSettings climate = new ClimateSettings();
public RiverSettings rivers = new RiverSettings();
public FilterSettings filters = new FilterSettings();
public TerrainSettings terrain = new TerrainSettings();
public BiomeSettings biomes = new BiomeSettings();
}

View File

@ -1,91 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.settings;
import com.terraforged.core.util.serialization.annotation.Comment;
import com.terraforged.core.util.serialization.annotation.Range;
import com.terraforged.core.util.serialization.annotation.Serializable;
import com.terraforged.core.world.terrain.TerrainPopulator;
import me.dags.noise.Module;
@Serializable
public class TerrainSettings {
@Range(min = 0, max = 1)
@Comment("Globally controls the vertical scaling of terrain")
public float globalVerticalScale = 0.985F;
@Range(min = 0, max = 5)
@Comment("Globally controls the horizontal scaling of terrain")
public float globalHorizontalScale = 1.0F;
public Terrain steppe = new Terrain(5F, 1F, 1F);
public Terrain plains = new Terrain(5F, 1F, 1F);
public Terrain hills = new Terrain(2F, 1F, 1F);
public Terrain dales = new Terrain(2F, 1F, 1F);
public Terrain plateau = new Terrain(2F, 1F, 1F);
public Terrain badlands = new Terrain(2F, 1F, 1F);
public Terrain torridonian = new Terrain(0.5F, 1F, 1F);
public Terrain mountains = new Terrain(0.5F, 1F, 1F);
public Terrain volcano = new Terrain(1F, 1F, 1F);
@Serializable
public static class Terrain {
@Range(min = 0, max = 10)
@Comment("Controls how common this terrain type is")
public float weight = 1F;
@Range(min = 0, max = 2)
@Comment("Controls the base height of this terrain")
public float baseScale = 1F;
@Range(min = 0F, max = 10F)
@Comment("Stretches or compresses the terrain vertically")
public float verticalScale = 1F;
@Range(min = 0F, max = 10F)
@Comment("Stretches or compresses the terrain horizontally")
public float horizontalScale = 1F;
public Terrain() {
}
public Terrain(float weight, float vertical, float horizontal) {
this.weight = weight;
this.verticalScale = vertical;
this.horizontalScale = horizontal;
}
public Module apply(double bias, double scale, Module module) {
double moduleBias = bias * baseScale;
double moduleScale = scale * verticalScale;
Module outputModule = module.scale(moduleScale).bias(moduleBias);
return TerrainPopulator.clamp(outputModule);
}
}
}

View File

@ -1,156 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.util;
public class PosIterator {
private final int minX;
private final int minZ;
private final int maxX;
private final int maxY;
private final int maxZ;
private final int size;
private int x;
private int y;
private int z;
private int index = -1;
public PosIterator(int x, int y, int z, int width, int height, int length) {
this.x = x - 1;
this.y = y;
this.z = z;
this.minX = x;
this.minZ = z;
this.maxX = x + width;
this.maxY = y + height;
this.maxZ = z + length;
this.size = (width * height * length) - 1;
}
/**
* Steps the iterator forward one position if there there is a new position within it's x/y/z bounds.
*
* @return true if the an increment was made, false if the maximum x,y,z coord has been reached
*/
public boolean next() {
if (x + 1 < maxX) {
x += 1;
index++;
return true;
}
if (z + 1 < maxZ) {
x = minX;
z += 1;
index++;
return true;
}
if (y + 1 < maxY) {
x = minX - 1;
z = minZ;
y += 1;
return true;
}
return false;
}
public int size() {
return size;
}
public int index() {
return index;
}
public int x() {
return x;
}
public int y() {
return y;
}
public int z() {
return z;
}
/**
* Iterates over a 2D area in the x-z planes, centered on x:z, with the given radius
*
* Iteration Order:
* 1. Increments the x-axis from x - radius to x + radius (inclusive), then:
* 2. Increments the z-axis once, resets the x-axis to x - radius, then:
* 3. Repeats steps 1 & 2 until z reaches z + radius
*/
public static PosIterator radius2D(int x, int z, int radius) {
int startX = x - radius;
int startZ = z - radius;
int size = radius * 2 + 1;
return new PosIterator(startX, 0, startZ, size, 0, size);
}
/**
* Iterates over a 3D volume, centered on x:y:z, with the given radius
*
* Iteration Order:
* 1. Increments the x-axis (starting from x - radius) up to x + radius (inclusive), then:
* 2. Increments the z-axis once (starting from z - radius) and resets the x-axis to x - radius, then:
* 3. Increments the y-axis once (starting from y - radius), resets the x & z axes to x - radius & z - radius
* respectively, then:
* 4. Repeats steps 1-3 until y reaches y + radius
*/
public static PosIterator radius3D(int x, int y, int z, int radius) {
int startX = x - radius;
int startY = y - radius;
int startZ = z - radius;
int size = radius * 2 + 1;
return new PosIterator(startX, startY, startZ, size, size, size);
}
public static PosIterator area(int x, int z, int width, int length) {
return new PosIterator(x, 0, z, width, 0, length);
}
public static PosIterator volume3D(int x, int y, int z, int width, int height, int length) {
return new PosIterator(x, y, z, width, height, length);
}
public static PosIterator range2D(int minX, int minZ, int maxX, int maxZ) {
int width = maxX - minX;
int length = maxZ - minZ;
return new PosIterator(minX, 0, minZ, width, 0, length);
}
public static PosIterator range2D(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) {
int width = 1 + maxX - minX;
int height = 1 + maxY - minY;
int length = 1 + maxZ - minZ;
return new PosIterator(minX, minY, minZ, width, height, length);
}
}

View File

@ -1,67 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.util;
public class Seed {
private final Seed root;
private final int value;
private int seed;
public Seed(long seed) {
this((int) seed);
}
public Seed(int seed) {
this.value = seed;
this.seed = seed;
this.root = this;
}
private Seed(Seed root) {
this.root = root;
this.seed = root.next();
this.value = seed;
}
public int next() {
return ++root.seed;
}
public int get() {
return value;
}
public Seed nextSeed() {
return new Seed(root);
}
public Seed reset() {
this.seed = value;
return this;
}
}

View File

@ -1,56 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.util;
import com.terraforged.core.cell.Cell;
import com.terraforged.core.world.heightmap.Levels;
import com.terraforged.core.world.terrain.Terrain;
import me.dags.noise.Module;
import me.dags.noise.Source;
import java.util.function.BiPredicate;
public class VariablePredicate {
private final Module module;
private final BiPredicate<Cell<Terrain>, Float> predicate;
public VariablePredicate(Module module, BiPredicate<Cell<Terrain>, Float> predicate) {
this.module = module;
this.predicate = predicate;
}
public boolean test(Cell<Terrain> cell, float x, float z) {
return predicate.test(cell, module.getValue(x, z));
}
public static VariablePredicate height(Seed seed, Levels levels, int min, int max, int size, int octaves) {
float bias = levels.scale(min);
float scale = levels.scale(max - min);
Module source = Source.perlin(seed.next(), size, 1).scale(scale).bias(bias);
return new VariablePredicate(source, (cell, height) -> cell.value < height);
}
}

View File

@ -1,11 +0,0 @@
package com.terraforged.core.util.concurrent;
public interface Disposable {
void dispose();
interface Listener<T> {
void onDispose(T t);
}
}

View File

@ -1,103 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.util.concurrent;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
public class ObjectPool<T> {
private final int capacity;
private final List<Item<T>> pool;
private final Supplier<? extends T> supplier;
public ObjectPool(int size, Supplier<? extends T> supplier) {
this.capacity = size;
this.pool = new ArrayList<>(size);
this.supplier = supplier;
}
public Item<T> get() {
synchronized (pool) {
if (pool.size() > 0) {
return pool.remove(pool.size() - 1).retain();
}
}
return new Item<>(supplier.get(), this);
}
public int size() {
synchronized (pool) {
return pool.size();
}
}
private boolean restore(Item<T> item) {
synchronized (pool) {
int size = pool.size();
if (size < capacity) {
pool.add(item);
return true;
}
}
return false;
}
public static class Item<T> implements AutoCloseable {
private final T value;
private final ObjectPool<T> pool;
private boolean released = false;
private Item(T value, ObjectPool<T> pool) {
this.value = value;
this.pool = pool;
}
public T getValue() {
return value;
}
public void release() {
if (!released) {
released = true;
released = pool.restore(this);
}
}
private Item<T> retain() {
released = false;
return this;
}
@Override
public void close() {
release();
}
}
}

View File

@ -1,114 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.util.concurrent;
import com.terraforged.core.util.concurrent.batcher.AsyncBatcher;
import com.terraforged.core.util.concurrent.batcher.Batcher;
import com.terraforged.core.util.concurrent.batcher.SyncBatcher;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
public class ThreadPool implements Executor {
private static final ThreadPool instance = create("TF", defaultPoolSize());
private final ForkJoinPool service;
private ThreadPool(ForkJoinPool service) {
this.service = service;
}
@Override
public void execute(Runnable command) {
service.submit(command);
}
public ForkJoinTask<?> submit(Runnable runnable) {
return service.submit(runnable);
}
public <T> ForkJoinTask<T> submit(Callable<T> callable) {
return service.submit(callable);
}
public Batcher batcher(int size) {
return new AsyncBatcher(service, size);
}
public static ThreadPool getPool() {
return instance;
}
public static ThreadPool create(String name, int size) {
if (size < 2) {
return new SingleThreadExecutor();
}
return new ThreadPool(createPool(name, size));
}
public static ForkJoinPool createPool(String name, int size) {
return new ForkJoinPool(size, new WorkerFactory.ForkJoin(name), null, true);
}
private static int defaultPoolSize() {
int threads = Runtime.getRuntime().availableProcessors();
return Math.max(1, (int) ((threads / 3F) * 2F));
}
private static class SingleThreadExecutor extends ThreadPool {
private SingleThreadExecutor() {
super(null);
}
@Override
public void execute(Runnable command) {
command.run();
}
@Override
public ForkJoinTask<?> submit(Runnable runnable) {
ForkJoinTask<?> task = ForkJoinTask.adapt(runnable);
task.invoke();
return task;
}
@Override
public <T> ForkJoinTask<T> submit(Callable<T> callable) {
ForkJoinTask<T> task = ForkJoinTask.adapt(callable);
task.invoke();
return task;
}
@Override
public Batcher batcher(int size) {
return new SyncBatcher();
}
}
}

View File

@ -1,42 +0,0 @@
package com.terraforged.core.util.concurrent;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinWorkerThread;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
// As DefaultThreadPool but with custom thread names
public class WorkerFactory implements ThreadFactory {
protected final String prefix;
protected final ThreadGroup group;
protected final AtomicInteger threadNumber = new AtomicInteger(1);
public WorkerFactory(String name) {
group = Thread.currentThread().getThreadGroup();
prefix = name + "-Worker-";
}
@Override
public Thread newThread(Runnable task) {
Thread thread = new Thread(group, task);
thread.setDaemon(true);
thread.setName(prefix + threadNumber.getAndIncrement());
return thread;
}
public static class ForkJoin extends WorkerFactory implements ForkJoinPool.ForkJoinWorkerThreadFactory {
public ForkJoin(String name) {
super(name);
}
@Override
public ForkJoinWorkerThread newThread(ForkJoinPool pool) {
ForkJoinWorkerThread thread = new ForkJoinWorkerThread(pool) {};
thread.setDaemon(true);
thread.setName(prefix + threadNumber.getAndIncrement());
return thread;
}
}
}

View File

@ -1,67 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.util.concurrent.batcher;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
public class AsyncBatcher implements Batcher {
private final List<Future<?>> tasks;
private final ExecutorService executor;
public AsyncBatcher(ExecutorService executor, int size) {
this.executor = executor;
this.tasks = new ArrayList<>(size);
}
@Override
public void submit(Runnable task) {
tasks.add(executor.submit(task));
}
@Override
public void submit(Callable<?> task) {
tasks.add(executor.submit(task));
}
@Override
public void close() {
boolean hasMore = true;
while (hasMore) {
hasMore = false;
for (Future<?> future : tasks) {
if (!future.isDone()) {
hasMore = true;
}
}
}
tasks.clear();
}
}

View File

@ -1,38 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.util.concurrent.batcher;
import java.util.concurrent.Callable;
public interface Batcher extends AutoCloseable {
void submit(Runnable task);
void submit(Callable<?> task);
@Override
void close();
}

View File

@ -1,50 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.util.concurrent.batcher;
import java.util.concurrent.Callable;
public class SyncBatcher implements Batcher {
@Override
public void submit(Runnable task) {
task.run();
}
@Override
public void submit(Callable<?> task) {
try {
task.call();
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public void close() {
}
}

View File

@ -1,46 +0,0 @@
package com.terraforged.core.util.concurrent.cache;
import com.terraforged.core.util.concurrent.ThreadPool;
import java.util.concurrent.TimeUnit;
import java.util.function.LongFunction;
public class Cache<V extends ExpiringEntry> implements Runnable {
private final long expireMS;
private final long intervalMS;
private final SynchronizedLongMap<V> map;
private final ThreadPool threadPool = ThreadPool.getPool();
private volatile long timestamp = 0L;
public Cache(long expireTime, long interval, TimeUnit unit) {
this.expireMS = unit.toMillis(expireTime);
this.intervalMS = unit.toMillis(interval);
this.map = new SynchronizedLongMap<>(100);
}
public void remove(long key) {
map.remove(key);
}
public V computeIfAbsent(long key, LongFunction<V> func) {
V v = map.computeIfAbsent(key, func);
queueUpdate();
return v;
}
private void queueUpdate() {
long now = System.currentTimeMillis();
if (now - timestamp > intervalMS) {
timestamp = now;
threadPool.submit(this);
}
}
@Override
public void run() {
final long now = timestamp;
map.removeIf(val -> now - val.getTimestamp() > expireMS);
}
}

View File

@ -1,48 +0,0 @@
package com.terraforged.core.util.concurrent.cache;
import com.terraforged.core.util.concurrent.ThreadPool;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.Future;
public class CacheEntry<T> implements ExpiringEntry {
private volatile long timestamp;
private final Future<T> task;
public CacheEntry(Future<T> task) {
this.task = task;
this.timestamp = System.currentTimeMillis();
}
@Override
public long getTimestamp() {
return timestamp;
}
public boolean isDone() {
return task.isDone();
}
public T get() {
if (task instanceof ForkJoinTask) {
return ((ForkJoinTask<T>) task).join();
}
try {
return task.get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
public static <T> CacheEntry<T> supply(Future<T> future) {
return new CacheEntry<>(future);
}
public static <T> CacheEntry<T> supplyAsync(Callable<T> callable, ThreadPool executor) {
return new CacheEntry<>(executor.submit(callable));
}
}

View File

@ -1,6 +0,0 @@
package com.terraforged.core.util.concurrent.cache;
public interface ExpiringEntry {
long getTimestamp();
}

View File

@ -1,54 +0,0 @@
package com.terraforged.core.util.concurrent.cache;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectIterator;
import java.util.function.LongFunction;
import java.util.function.Predicate;
public class SynchronizedLongMap<V> {
private final Object lock;
private final Long2ObjectOpenHashMap<V> map;
public SynchronizedLongMap(int size) {
this.map = new Long2ObjectOpenHashMap<>(size);
this.lock = this;
}
public void remove(long key) {
synchronized (lock) {
map.remove(key);
}
}
public void put(long key, V v) {
synchronized (lock) {
map.put(key, v);
}
}
public V get(long key) {
synchronized (lock) {
return map.get(key);
}
}
public V computeIfAbsent(long key, LongFunction<V> func) {
synchronized (lock) {
return map.computeIfAbsent(key, func);
}
}
public void removeIf(Predicate<V> predicate) {
synchronized (lock) {
ObjectIterator<Long2ObjectMap.Entry<V>> iterator = map.long2ObjectEntrySet().fastIterator();
while (iterator.hasNext()) {
if (predicate.test(iterator.next().getValue())) {
iterator.remove();
}
}
}
}
}

View File

@ -1,163 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.util.grid;
import me.dags.noise.util.NoiseUtil;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Supplier;
public class FixedGrid<T> implements Iterable<MappedList<FixedList<T>>> {
private final MappedList<MappedList<FixedList<T>>> grid;
private FixedGrid(MappedList<MappedList<FixedList<T>>> grid) {
this.grid = grid;
}
public int size() {
return grid.size();
}
public FixedList<T> get(float x, float y) {
return grid.get(y).get(x);
}
public T get(float x, float y, float z) {
MappedList<FixedList<T>> row = grid.get(y);
FixedList<T> cell = row.get(x);
return cell.get(z);
}
@Override
public Iterator<MappedList<FixedList<T>>> iterator() {
return grid.iterator();
}
public static <T> FixedGrid<T> create(List<List<List<T>>> grid, float minX, float minY, float rangeX, float rangeY) {
List<MappedList<FixedList<T>>> list = new ArrayList<>();
for (List<List<T>> src : grid) {
List<FixedList<T>> row = new ArrayList<>(src.size());
for (List<T> cell : src) {
row.add(FixedList.of(cell));
}
list.add(MappedList.of(row, minX, rangeX));
}
return new FixedGrid<>(MappedList.of(list, minY, rangeY));
}
public static <T> FixedGrid<T> generate(int size, List<T> values, Function<T, Float> xFunc, Function<T, Float> yFunc) {
List<List<List<T>>> src = createList(size, () -> createList(size, ArrayList::new));
List<List<List<T>>> dest = createList(size, () -> createList(size, ArrayList::new));
float minX = 1F;
float maxX = 0F;
float minY = 1F;
float maxY = 0F;
for (T value : values) {
float x = xFunc.apply(value);
float y = yFunc.apply(value);
minX = Math.min(minX, x);
maxX = Math.max(maxX, x);
minY = Math.min(minY, y);
maxY = Math.max(maxY, y);
}
int maxIndex = size - 1;
float rangeX = maxX - minX;
float rangeY = maxY - minY;
for (T value : values) {
float colVal = (xFunc.apply(value) - minX) / rangeX;
float rowVal = (yFunc.apply(value) - minY) / rangeY;
int colIndex = NoiseUtil.round(maxIndex * colVal);
int rowIndex = NoiseUtil.round(maxIndex * rowVal);
List<List<T>> row = src.get(rowIndex);
List<T> group = row.get(colIndex);
group.add(value);
}
for (int y = 0; y < size; y++) {
List<List<T>> srcRow = src.get(y);
List<List<T>> destRow = dest.get(y);
for (int x = 0; x < size; x++) {
List<T> srcGroup = srcRow.get(x);
List<T> destGroup = destRow.get(x);
if (srcGroup.isEmpty()) {
float fx = minX + (x / (float) maxIndex) * rangeX;
float fy = minY + (x / (float) maxIndex) * rangeY;
addClosest(values, destGroup, fx, fy, xFunc, yFunc);
} else {
destGroup.addAll(srcGroup);
}
}
}
return create(dest, minX, minY, rangeX, rangeY);
}
private static <T> void addClosest(List<T> source, List<T> dest, float fx, float fy, Function<T, Float> xFunc, Function<T, Float> yFunc) {
float dist2 = Float.MAX_VALUE;
Map<T, Float> distances = new HashMap<>();
for (T t : source) {
if (!distances.containsKey(t)) {
float dx = fx - xFunc.apply(t);
float dy = fy - yFunc.apply(t);
float d2 = dx * dx + dy * dy;
distances.put(t, d2);
if (d2 < dist2) {
dist2 = d2;
}
}
}
if (dist2 <= 0) {
dist2 = 1F;
}
List<T> sorted = new ArrayList<>(distances.keySet());
sorted.sort((o1, o2) -> Float.compare(distances.getOrDefault(o1, Float.MAX_VALUE), distances.getOrDefault(o2, Float.MAX_VALUE)));
for (T t : sorted) {
float d2 = distances.get(t);
if (d2 / dist2 < 1.025F) {
dest.add(t);
}
}
}
private static <T> List<T> createList(int size, Supplier<T> supplier) {
List<T> list = new ArrayList<>();
while (list.size() < size) {
list.add(supplier.get());
}
return list;
}
}

View File

@ -1,96 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.util.grid;
import me.dags.noise.util.NoiseUtil;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
public class FixedList<T> implements Iterable<T> {
private final int maxIndex;
private final T[] elements;
FixedList(T[] elements) {
this.maxIndex = elements.length - 1;
this.elements = elements;
}
public T get(int index) {
if (index < 0) {
return elements[0];
}
if (index > maxIndex) {
return elements[maxIndex];
}
return elements[index];
}
public T get(float value) {
return get(indexOf(value));
}
public int size() {
return elements.length;
}
public int indexOf(float value) {
return NoiseUtil.round(value * maxIndex);
}
public Set<T> uniqueValues() {
Set<T> set = new HashSet<>();
Collections.addAll(set, elements);
return set;
}
@Override
public Iterator<T> iterator() {
return new Iterator<T>() {
private int index = 0;
@Override
public boolean hasNext() {
return index < elements.length;
}
@Override
public T next() {
return elements[index++];
}
};
}
@SuppressWarnings("unchecked")
public static <T> FixedList<T> of(List<T> list) {
return new FixedList<>((T[]) list.toArray());
}
}

View File

@ -1,50 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.util.grid;
import java.util.List;
public class MappedList<T> extends FixedList<T> {
private final float min;
private final float range;
public MappedList(T[] elements, float min, float range) {
super(elements);
this.min = min;
this.range = range;
}
@Override
public int indexOf(float value) {
return super.indexOf((value - min) / range);
}
@SuppressWarnings("unchecked")
public static <T> MappedList<T> of(List<T> list, float min, float range) {
return new MappedList<>((T[]) list.toArray(), min, range);
}
}

View File

@ -1,76 +0,0 @@
package com.terraforged.core.util.points;
import com.terraforged.core.cell.Cell;
import com.terraforged.core.region.Region;
import me.dags.noise.Module;
import me.dags.noise.Source;
import me.dags.noise.util.Vec2i;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
public class Poisson {
public static void main(String[] args) {
Region region = new Region(0, 0, 5, 2);
BufferedImage image = new BufferedImage(region.getBlockSize().size, region.getBlockSize().size, BufferedImage.TYPE_INT_RGB);
points(region, 123,8, 20F, 0.8F);
render(region, image);
JFrame frame = new JFrame();
frame.add(new JLabel(new ImageIcon(image)));
frame.pack();
frame.setVisible(true);
frame.setResizable(false);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private static void points(Region region, int seed, int scale, float radius, float threshold) {
region.generate(chunk -> chunk.generate((cell, dx, dz) -> {}));
Module noise = Source.simplex(seed, scale, 1);
int gridSize = (int) Math.ceil(region.getBlockSize().size / radius);
Vec2i[][] grid = new Vec2i[gridSize][gridSize];
for (int dz = 0; dz < region.getBlockSize().size; dz++) {
for (int dx = 0; dx < region.getBlockSize().size; dx++) {
int x = region.getBlockX() + dx;
int z = region.getBlockZ() + dz;
float value = noise.getValue(x, z);
region.getCell(dx, dz).value = value;
if (true) continue;
if (value > threshold) {
continue;
}
int gridX = (int) (dx / radius);
int gridZ = (int) (dz / radius);
Vec2i point = grid[gridZ][gridX];
if (point != null) {
Cell<?> current = region.getCell(point.x, point.y);
if (current.value > value) {
continue;
}
}
region.getCell(dx, dz).value = value;
grid[gridZ][gridX] = new Vec2i(dx, dz);
}
}
}
private static void render(Region region, BufferedImage image) {
region.iterate((cell, dx, dz) -> {
if (cell.value == 0) {
return;
}
int w = (int) (cell.value * 255);
image.setRGB(dx, dz, new Color(w, w, w).getRGB());
});
}
}

View File

@ -1,38 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.util.serialization.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Comment {
String[] value();
}

View File

@ -1,38 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.util.serialization.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Name {
String value();
}

View File

@ -1,37 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.util.serialization.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Option {
}

View File

@ -1,40 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.util.serialization.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Range {
float min();
float max();
}

View File

@ -1,36 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.util.serialization.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Serializable {
}

View File

@ -1,116 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.util.serialization.serializer;
import com.terraforged.core.util.serialization.annotation.Serializable;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
public class Deserializer {
public void deserialize(Reader reader, Object object) throws Throwable {
Class<?> type = object.getClass();
for (String name : reader.getKeys()) {
if (name.charAt(0) == '#') {
continue;
}
try {
Reader child = reader.getChild(name);
Field field = type.getField(name);
if (Serializer.isSerializable(field)) {
field.setAccessible(true);
fromValue(child, object, field);
}
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
}
}
private void fromValue(Reader reader, Object object, Field field) throws Throwable {
if (field.getType() == int.class) {
field.set(object, reader.getInt("value"));
return;
}
if (field.getType() == float.class) {
field.set(object, reader.getFloat("value"));
return;
}
if (field.getType() == boolean.class) {
field.set(object, reader.getString("value").equals("true"));
return;
}
if (field.getType() == String.class) {
field.set(object, reader.getString("value"));
return;
}
if (field.getType().isEnum()) {
String name = reader.getString("value");
for (Enum<?> e : field.getType().asSubclass(Enum.class).getEnumConstants()) {
if (e.name().equals(name)) {
field.set(object, e);
return;
}
}
}
if (field.getType().isAnnotationPresent(Serializable.class)) {
Reader child = reader.getChild("value");
Object value = field.getType().newInstance();
deserialize(child, value);
field.set(object, value);
return;
}
if (field.getType().isArray()) {
Class<?> type = field.getType().getComponentType();
if (type.isAnnotationPresent(Serializable.class)) {
Reader child = reader.getChild("value");
Object array = Array.newInstance(type, child.getSize());
for (int i = 0; i < child.getSize(); i++) {
Object value = type.newInstance();
deserialize(child.getChild(i), value);
Array.set(array, i, value);
}
field.set(object, array);
}
}
}
private static String getName(String name) {
StringBuilder sb = new StringBuilder(name.length());
for (int i = 0; i < name.length(); i++) {
char c = name.charAt(i);
if (i == 0) {
c = Character.toLowerCase(c);
} else if (c == ' ' && i + 1 < name.length()) {
c = Character.toUpperCase(name.charAt(++i));
}
sb.append(c);
}
return sb.toString();
}
}

View File

@ -1,83 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.util.serialization.serializer;
import java.util.Collection;
public interface Reader {
int getSize();
Reader getChild(String key);
Reader getChild(int index);
Collection<String> getKeys();
String getString();
boolean getBool();
float getFloat();
int getInt();
default String getString(String key) {
return getChild(key).getString();
}
default boolean getBool(String key) {
return getChild(key).getBool();
}
default float getFloat(String key) {
return getChild(key).getFloat();
}
default int getInt(String key) {
return getChild(key).getInt();
}
default String getString(int index) {
return getChild(index).getString();
}
default boolean getBool(int index) {
return getChild(index).getBool();
}
default float getFloat(int index) {
return getChild(index).getFloat();
}
default int getInt(int index) {
return getChild(index).getInt();
}
default void writeTo(Object object) throws Throwable {
new Deserializer().deserialize(this, object);
}
}

View File

@ -1,191 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.util.serialization.serializer;
import com.terraforged.core.util.serialization.annotation.Comment;
import com.terraforged.core.util.serialization.annotation.Name;
import com.terraforged.core.util.serialization.annotation.Range;
import com.terraforged.core.util.serialization.annotation.Serializable;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
public class Serializer {
public void serialize(Object object, Writer writer) throws IllegalAccessException {
if (object.getClass().isArray()) {
writer.beginArray();
int length = Array.getLength(object);
for (int i = 0; i < length; i++) {
Object element = Array.get(object, i);
serialize(element, writer);
}
writer.endArray();
} else if (!object.getClass().isPrimitive()) {
int order = 0;
writer.beginObject();
for (Field field : object.getClass().getFields()) {
if (Serializer.isSerializable(field)) {
field.setAccessible(true);
write(object, field, order, writer);
order++;
}
}
writer.endObject();
}
}
private void write(Object object, Field field, int order, Writer writer) throws IllegalAccessException {
if (field.getType() == int.class) {
writer.name(field.getName());
writer.beginObject();
writer.name("value").value((int) field.get(object));
writeMeta(field, order, writer);
writer.endObject();
return;
}
if (field.getType() == float.class) {
writer.name(field.getName());
writer.beginObject();
writer.name("value").value((float) field.get(object));
writeMeta(field, order, writer);
writer.endObject();
return;
}
if (field.getType() == String.class) {
writer.name(field.getName());
writer.beginObject();
writer.name("value").value((String) field.get(object));
writeMeta(field, order, writer);
writer.endObject();
return;
}
if (field.getType() == boolean.class) {
writer.name(field.getName());
writer.beginObject();
writer.name("value").value("" + (field.get(object)));
writeMeta(field, order, writer);
writer.endObject();
}
if (field.getType().isEnum()) {
writer.name(field.getName());
writer.beginObject();
writer.name("value").value(((Enum<?>) field.get(object)).name());
writeMeta(field, order, writer);
writer.endObject();
return;
}
if (field.getType().isArray()) {
if (field.getType().getComponentType().isAnnotationPresent(Serializable.class)) {
writer.name(field.getName());
writer.beginObject();
writer.name("value");
serialize(field.get(object), writer);
writeMeta(field, order, writer);
writer.endObject();
}
return;
}
if (field.getType().isAnnotationPresent(Serializable.class)) {
writer.name(field.getName());
writer.beginObject();
writer.name("value");
serialize(field.get(object), writer);
writeMeta(field, order, writer);
writer.endObject();
}
}
private void writeMeta(Field field, int order, Writer writer) {
writer.name("#display").value(getName(field));
writer.name("#order").value(order);
Range range = field.getAnnotation(Range.class);
if (range != null) {
if (field.getType() == int.class) {
writer.name("#min").value((int) range.min());
writer.name("#max").value((int) range.max());
} else {
writer.name("#min").value(range.min());
writer.name("#max").value(range.max());
}
}
Comment comment = field.getAnnotation(Comment.class);
if (comment != null) {
writer.name("#comment");
writer.beginArray();
for (String line : comment.value()) {
writer.value(line);
}
writer.endArray();
}
if (field.getType() == boolean.class) {
writer.name("#options");
writer.beginArray();
writer.value("true");
writer.value("false");
writer.endArray();
}
if (field.getType().isEnum()) {
writer.name("#options");
writer.beginArray();
for (Enum<?> o : field.getType().asSubclass(Enum.class).getEnumConstants()) {
writer.value(o.name());
}
writer.endArray();
}
}
private static String getName(Field field) {
Name nameMeta = field.getAnnotation(Name.class);
String name = nameMeta == null ? field.getName() : nameMeta.value();
StringBuilder sb = new StringBuilder(name.length() * 2);
for (int i = 0; i < name.length(); i++) {
char c = name.charAt(i);
if (i == 0) {
c = Character.toUpperCase(c);
} else if (Character.isUpperCase(c)) {
sb.append(' ');
}
sb.append(c);
}
return sb.toString();
}
protected static boolean isSerializable(Field field) {
int modifiers = field.getModifiers();
return Modifier.isPublic(modifiers)
&& !Modifier.isFinal(modifiers)
&& !Modifier.isStatic(modifiers)
&& !Modifier.isTransient(modifiers);
}
}

View File

@ -1,49 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.util.serialization.serializer;
public interface Writer {
Writer name(String name);
Writer beginObject();
Writer endObject();
Writer beginArray();
Writer endArray();
Writer value(String value);
Writer value(float value);
Writer value(int value);
default void readFrom(Object value) throws IllegalAccessException {
new Serializer().serialize(value, this);
}
}

View File

@ -1,66 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.world;
import com.terraforged.core.settings.Settings;
import com.terraforged.core.util.Seed;
import com.terraforged.core.world.heightmap.Levels;
import com.terraforged.core.world.terrain.Terrains;
import com.terraforged.core.world.terrain.provider.StandardTerrainProvider;
import com.terraforged.core.world.terrain.provider.TerrainProviderFactory;
public class GeneratorContext {
public final Seed seed;
public final Levels levels;
public final Terrains terrain;
public final Settings settings;
public final TerrainProviderFactory terrainFactory;
public GeneratorContext(Terrains terrain, Settings settings) {
this(terrain, settings, StandardTerrainProvider::new);
}
public GeneratorContext(Terrains terrain, Settings settings, TerrainProviderFactory terrainFactory) {
this.terrain = terrain;
this.settings = settings;
this.seed = new Seed(settings.generator.seed);
this.levels = new Levels(settings.generator);
this.terrainFactory = terrainFactory;
}
private GeneratorContext(GeneratorContext src) {
seed = new Seed(src.seed.get());
levels = src.levels;
terrain = src.terrain;
settings = src.settings;
terrainFactory = src.terrainFactory;
}
public GeneratorContext copy() {
return new GeneratorContext(this);
}
}

View File

@ -1,51 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.world;
import com.terraforged.core.world.decorator.Decorator;
import com.terraforged.core.world.decorator.DesertStacks;
import com.terraforged.core.world.decorator.Wetlands;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class WorldDecorators {
private final List<Decorator> decorators;
public WorldDecorators(GeneratorContext context) {
context = context.copy();
List<Decorator> list = new ArrayList<>();
list.add(new DesertStacks(context.seed, context.levels));
list.add(new Wetlands(context.seed, context.terrain, context.levels));
decorators = Collections.unmodifiableList(list);
}
public List<Decorator> getDecorators() {
return decorators;
}
}

View File

@ -1,57 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.world;
import com.terraforged.core.filter.Erosion;
import com.terraforged.core.filter.Filterable;
import com.terraforged.core.filter.Smoothing;
import com.terraforged.core.filter.Steepness;
import com.terraforged.core.region.Region;
import com.terraforged.core.settings.FilterSettings;
import com.terraforged.core.world.terrain.Terrain;
public class WorldFilters {
private final Erosion erosion;
private final Smoothing smoothing;
private final Steepness steepness;
private final FilterSettings settings;
public WorldFilters(GeneratorContext context) {
context = context.copy();
this.settings = context.settings.filters;
this.erosion = new Erosion(context.settings, context.levels);
this.smoothing = new Smoothing(context.settings, context.levels);
this.steepness = new Steepness(1, 10F, context.terrain, context.levels);
}
public void apply(Region region) {
Filterable<Terrain> map = region.filterable();
erosion.apply(map, region.getRegionX(), region.getRegionZ(), settings.erosion.iterations);
smoothing.apply(map, region.getRegionX(), region.getRegionZ(), settings.smoothing.iterations);
steepness.apply(map, region.getRegionX(), region.getRegionZ(), 1);
}
}

View File

@ -1,53 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.world;
import com.terraforged.core.world.heightmap.Heightmap;
public class WorldGenerator {
private final Heightmap heightmap;
private final WorldFilters filters;
private final WorldDecorators decorators;
public WorldGenerator(Heightmap heightmap, WorldDecorators decorators, WorldFilters filters) {
this.filters = filters;
this.heightmap = heightmap;
this.decorators = decorators;
}
public Heightmap getHeightmap() {
return heightmap;
}
public WorldFilters getFilters() {
return filters;
}
public WorldDecorators getDecorators() {
return decorators;
}
}

View File

@ -1,73 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.world;
import com.terraforged.core.world.climate.Climate;
import com.terraforged.core.world.heightmap.Heightmap;
import com.terraforged.core.world.heightmap.WorldHeightmap;
import java.util.function.Supplier;
public class WorldGeneratorFactory implements Supplier<WorldGenerator> {
private final GeneratorContext context;
private final Heightmap heightmap;
private final WorldDecorators decorators;
public WorldGeneratorFactory(GeneratorContext context) {
this.context = context;
this.heightmap = new WorldHeightmap(context);
this.decorators = new WorldDecorators(context);
}
public WorldGeneratorFactory(GeneratorContext context, Heightmap heightmap) {
this.context = context;
this.heightmap = heightmap;
this.decorators = new WorldDecorators(context);
}
public Heightmap getHeightmap() {
return heightmap;
}
public Climate getClimate() {
return getHeightmap().getClimate();
}
public WorldDecorators getDecorators() {
return decorators;
}
public WorldFilters getFilters() {
return new WorldFilters(context);
}
@Override
public WorldGenerator get() {
return new WorldGenerator(heightmap, decorators, getFilters());
}
}

View File

@ -1,159 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.world.biome;
import java.awt.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class BiomeData implements Comparable<BiomeData> {
private static float[] bounds = {0, 1 / 3F, 2 / 3F, 1F};
public static final List<BiomeData> BIOMES = new ArrayList<>();
public static BiomeData DEFAULT = new BiomeData("none", "", 1, 0.5F, 0.5F);
public final String name;
public final Object reference;
public final float color;
public final float rainfall;
public final float temperature;
public BiomeData(String name, Object reference, float color, float rainfall, float temperature) {
this.reference = reference;
this.name = name;
this.rainfall = rainfall;
this.temperature = temperature;
this.color = color;
}
public BiomeData(String name, Object reference, int color, float rainfall, float temperature) {
Color c = new Color(color);
this.reference = reference;
this.name = name;
this.rainfall = rainfall;
this.temperature = temperature;
this.color = getHue(c.getRed(), c.getGreen(), c.getBlue());
}
@Override
public int compareTo(BiomeData o) {
return name.compareTo(o.name);
}
public static Collection<BiomeData> getBiomes(float temperature, float rainfall) {
int temp = Math.min(3, (int) (bounds.length * temperature));
int rain = Math.min(3, (int) (bounds.length * rainfall));
return getBiomes(temp, rain);
}
public static Collection<BiomeData> getBiomes(int tempLower, int rainLower) {
int temp0 = tempLower;
int temp1 = temp0 + 1;
int rain0 = rainLower;
int rain1 = rain0 + 1;
float tempMin = bounds[temp0];
float tempMax = bounds[temp1];
float rainMin = bounds[rain0];
float rainMax = bounds[rain1];
List<BiomeData> biomes = new ArrayList<>();
for (BiomeData biome : BIOMES) {
if (biome.temperature >= tempMin && biome.temperature <= tempMax
&& biome.rainfall >= rainMin && biome.rainfall <= rainMax) {
biomes.add(biome);
}
}
if (biomes.isEmpty()) {
biomes.add(DEFAULT);
}
return biomes;
}
public static Collection<BiomeData> getTempBiomes(float temperature) {
int lower = Math.min(3, (int) (bounds.length * temperature));
int upper = lower + 1;
float min = bounds[lower];
float max = bounds[upper];
List<BiomeData> biomes = new ArrayList<>();
for (BiomeData data : BIOMES) {
if (data.temperature >= min && data.temperature <= max) {
biomes.add(data);
}
}
return biomes;
}
public static Collection<BiomeData> getRainBiomes(float rainfall) {
int lower = Math.min(3, (int) (bounds.length * rainfall));
int upper = lower + 1;
float min = bounds[lower];
float max = bounds[upper];
List<BiomeData> biomes = new ArrayList<>();
for (BiomeData data : BIOMES) {
if (data.rainfall >= min && data.rainfall <= max) {
biomes.add(data);
}
}
return biomes;
}
private static float getHue(int red, int green, int blue) {
float min = Math.min(Math.min(red, green), blue);
float max = Math.max(Math.max(red, green), blue);
if (min == max) {
return 0;
}
float hue;
if (max == red) {
hue = (green - blue) / (max - min);
} else if (max == green) {
hue = 2f + (blue - red) / (max - min);
} else {
hue = 4f + (red - green) / (max - min);
}
hue = hue * 60;
if (hue < 0) hue = hue + 360;
return (Math.round(hue) / 360F) * 100F;
}
}

View File

@ -1,35 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.world.biome;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class BiomeManager {
private final Map<BiomeType, List<BiomeData>> biomes = new HashMap<>();
}

View File

@ -1,140 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.world.biome;
import com.terraforged.core.cell.Cell;
import me.dags.noise.util.NoiseUtil;
import java.awt.*;
public enum BiomeType {
TROPICAL_RAINFOREST(7, 83, 48, new Color(7, 83, 48)),
SAVANNA(151, 165, 39, new Color(151, 165, 39)),
DESERT(200, 113, 55, new Color(200, 113, 55)),
TEMPERATE_RAINFOREST(10, 84, 109, new Color(10, 160, 65)),
TEMPERATE_FOREST(44, 137, 160, new Color(50, 200, 80)),
GRASSLAND(179, 124, 6, new Color(100, 220, 60)),
COLD_STEPPE(131, 112, 71, new Color(175, 180, 150)),
STEPPE(199, 155, 60, new Color(200, 200, 120)),
TAIGA(91, 143, 82, new Color(91, 143, 82)),
TUNDRA(147, 167, 172, new Color(147, 167, 172)),
ALPINE(0, 0, 0, new Color(160, 120, 170));
public static final int RESOLUTION = 256;
public static final int MAX = RESOLUTION - 1;
private final Color lookup;
private final Color color;
BiomeType(int r, int g, int b, Color color) {
this(new Color(r, g, b), color);
}
BiomeType(Color lookup, Color color) {
this.lookup = lookup;
this.color = BiomeTypeColors.getInstance().getColor(name(), color);
}
Color getLookup() {
return lookup;
}
public Color getColor() {
return color;
}
public boolean isExtreme() {
return this == TUNDRA || this == DESERT;
}
public static BiomeType get(float temperature, float moisture) {
return getCurve(temperature, moisture);
}
public static BiomeType getLinear(float temperature, float moisture) {
int x = NoiseUtil.round(MAX * temperature);
int y = getYLinear(x, temperature, moisture);
return getType(x, y);
}
public static BiomeType getCurve(float temperature, float moisture) {
int x = NoiseUtil.round(MAX * temperature);
int y = getYCurve(x, temperature, moisture);
return getType(x, y);
}
public static float getEdge(float temperature, float moisture) {
return getEdgeCurve(temperature, moisture);
}
public static float getEdgeLinear(float temperature, float moisture) {
int x = NoiseUtil.round(MAX * temperature);
int y = getYLinear(x, temperature, moisture);
return getEdge(x, y);
}
public static float getEdgeCurve(float temperature, float moisture) {
int x = NoiseUtil.round(MAX * temperature);
int y = getYCurve(x, temperature, moisture);
return getEdge(x, y);
}
public static void apply(Cell<?> cell) {
applyCurve(cell);
}
public static void applyLinear(Cell<?> cell) {
cell.biomeType = get(cell.biomeTemperature, cell.biomeMoisture);
cell.biomeTypeMask = getEdge(cell.temperature, cell.moisture);
}
public static void applyCurve(Cell<?> cell) {
cell.biomeType = get(cell.biomeTemperature, cell.biomeMoisture);
cell.biomeTypeMask = getEdge(cell.temperature, cell.moisture);
}
private static BiomeType getType(int x, int y) {
return BiomeTypeLoader.getInstance().getTypeMap()[y][x];
}
private static float getEdge(int x, int y) {
return BiomeTypeLoader.getInstance().getEdgeMap()[y][x];
}
private static int getYLinear(int x, float temperature, float moisture) {
if (moisture > temperature) {
return x;
}
return NoiseUtil.round(MAX * moisture);
}
private static int getYCurve(int x, float temperature, float moisture) {
int max = x + ((MAX - x) / 2);
int y = NoiseUtil.round(max * moisture);
return Math.min(x, y);
}
}

View File

@ -1,75 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.world.biome;
import java.awt.*;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
public class BiomeTypeColors {
private static BiomeTypeColors instance = new BiomeTypeColors();
private final Map<String, Color> colors = new HashMap<>();
private BiomeTypeColors() {
try (InputStream inputStream = BiomeType.class.getResourceAsStream("/biomes.txt")) {
Properties properties = new Properties();
properties.load(inputStream);
for (Map.Entry<?, ?> entry : properties.entrySet()) {
Color color = Color.decode("#" + entry.getValue().toString());
colors.put(entry.getKey().toString(), color);
}
} catch (IOException e) {
e.printStackTrace();
}
}
public Color getColor(String name, Color defaultColor) {
return colors.getOrDefault(name, defaultColor);
}
public static BiomeTypeColors getInstance() {
return instance;
}
public static void main(String[] args) throws Throwable {
try (FileWriter writer = new FileWriter("biome_colors.properties")) {
Properties properties = new Properties();
for (BiomeType type : BiomeType.values()) {
int r = type.getColor().getRed();
int g = type.getColor().getGreen();
int b = type.getColor().getBlue();
properties.setProperty(type.name(), String.format("%02x%02x%02x", r, g, b));
}
properties.store(writer, "TerraForged BiomeType Hex Colors (do not include hash/pound character)");
}
}
}

View File

@ -1,204 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.world.biome;
import me.dags.noise.util.NoiseUtil;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
public class BiomeTypeLoader {
private static BiomeTypeLoader instance;
private final float[][] edges = new float[BiomeType.RESOLUTION][BiomeType.RESOLUTION];
private final BiomeType[][] map = new BiomeType[BiomeType.RESOLUTION][BiomeType.RESOLUTION];
public BiomeTypeLoader() {
generateTypeMap();
generateEdgeMap();
}
public BiomeType[][] getTypeMap() {
return map;
}
public float[][] getEdgeMap() {
return edges;
}
private BiomeType getType(int x, int y) {
return map[y][x];
}
private void generateTypeMap() {
try {
BufferedImage image = ImageIO.read(BiomeType.class.getResourceAsStream("/biomes.png"));
float xf = image.getWidth() / (float) BiomeType.RESOLUTION;
float yf = image.getHeight() / (float) BiomeType.RESOLUTION;
for (int y = 0; y < BiomeType.RESOLUTION; y++) {
for (int x = 0; x < BiomeType.RESOLUTION; x++) {
if (BiomeType.MAX - y > x) {
map[BiomeType.MAX - y][x] = BiomeType.ALPINE;
continue;
}
int ix = NoiseUtil.round(x * xf);
int iy = NoiseUtil.round(y * yf);
int argb = image.getRGB(ix, iy);
Color color = fromARGB(argb);
map[BiomeType.MAX - y][x] = forColor(color);
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private void generateEdgeMap() {
int[] distances = new int[BiomeType.values().length];
for (int y = 0; y < BiomeType.RESOLUTION; y++) {
for (int x = 0; x < BiomeType.RESOLUTION; x++) {
if (y > x) continue;
BiomeType type = getType(x, y);
if (type == BiomeType.ALPINE) {
continue;
}
int distance2 = getEdge(x, y, type);
edges[y][x] = distance2;
distances[type.ordinal()] = Math.max(distances[type.ordinal()], distance2);
}
}
for (int y = 0; y < BiomeType.RESOLUTION; y++) {
for (int x = 0; x < BiomeType.RESOLUTION; x++) {
BiomeType type = getType(x, y);
int max = distances[type.ordinal()];
float distance = edges[y][x];
float value = NoiseUtil.pow(distance / max, 0.33F);
edges[y][x] = NoiseUtil.clamp(value, 0, 1);
}
}
}
private int getEdge(int cx, int cy, BiomeType type) {
int radius = BiomeType.RESOLUTION / 4;
int distance2 = Integer.MAX_VALUE;
int x0 = Math.max(0, cx - radius);
int x1 = Math.min(BiomeType.MAX, cx + radius);
int y0 = Math.max(0, cy - radius);
int y1 = Math.min(BiomeType.MAX, cy + radius);
for (int y = y0; y <= y1; y++) {
for (int x = x0; x <= x1; x++) {
BiomeType neighbour = getType(x, y);
if (neighbour == BiomeType.ALPINE) {
continue;
}
if (neighbour != type) {
int dist2 = dist2(cx, cy, x, y);
if (dist2 < distance2) {
distance2 = dist2;
}
}
}
}
return distance2;
}
private static BiomeType forColor(Color color) {
BiomeType type = null;
int closest = Integer.MAX_VALUE;
for (BiomeType t : BiomeType.values()) {
int distance2 = getDistance2(color, t.getLookup());
if (distance2 < closest) {
closest = distance2;
type = t;
}
}
if (type == null) {
return BiomeType.GRASSLAND;
}
return type;
}
private static int getDistance2(Color a, Color b) {
int dr = a.getRed() - b.getRed();
int dg = a.getGreen() - b.getGreen();
int db = a.getBlue() - b.getBlue();
return dr * dr + dg * dg + db * db;
}
private static Color fromARGB(int argb) {
int b = (argb) & 0xFF;
int g = (argb >> 8) & 0xFF;
int r = (argb >> 16) & 0xFF;
return new Color(r, g, b);
}
private static int dist2(int x1, int y1, int x2, int y2) {
int dx = x1 - x2;
int dy = y1 - y2;
return dx * dx + dy * dy;
}
private static BufferedImage generateEdgeMapImage() {
BufferedImage image = new BufferedImage(BiomeType.RESOLUTION, BiomeType.RESOLUTION, BufferedImage.TYPE_INT_RGB);
for (int y = 0; y < BiomeType.RESOLUTION; y++) {
for (int x = 0; x < BiomeType.RESOLUTION; x++) {
float temperature = x / (float) BiomeType.RESOLUTION;
float moisture = y / (float) BiomeType.RESOLUTION;
float value = BiomeType.getEdge(temperature, moisture);
int color = Color.HSBtoRGB(0, 0, value);
image.setRGB(x, image.getHeight() - 1 - y, color);
}
}
return image;
}
public static BiomeTypeLoader getInstance() {
if (instance == null) {
instance = new BiomeTypeLoader();
}
return instance;
}
public static void main(String[] args) throws Throwable {
BufferedImage img = generateEdgeMapImage();
ImageIO.write(img, "png", new File("biomes_dist.png"));
JLabel label = new JLabel(new ImageIcon(img));
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(label);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}

View File

@ -1,111 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.world.climate;
import com.terraforged.core.cell.Cell;
import com.terraforged.core.world.GeneratorContext;
import com.terraforged.core.world.terrain.Terrain;
import me.dags.noise.Module;
import me.dags.noise.Source;
import me.dags.noise.source.Rand;
public class Climate {
private final float seaLevel;
private final float lowerHeight;
private final float midHeight = 0.45F;
private final float upperHeight = 0.75F;
private final float moistureModifier = 0.1F;
private final float temperatureModifier = 0.05F;
private final Rand rand;
private final Module treeLine;
private final Module offsetX;
private final Module offsetY;
private final ClimateModule biomeNoise;
public Climate(GeneratorContext context) {
this.biomeNoise = new ClimateModule(context.seed, context.settings);
this.treeLine = Source.perlin(context.seed.next(), context.settings.generator.biome.biomeSize * 2, 1)
.scale(context.levels.scale(25)) // 30 units worth of variance
.bias(context.levels.ground(40)) // start at-least 30 units above ground level
.clamp(0, 1);
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());
this.seaLevel = context.levels.water;
this.lowerHeight = context.levels.ground;
}
public Rand getRand() {
return rand;
}
public float getOffsetX(float x, float z, int distance) {
return offsetX.getValue(x, z) * distance;
}
public float getOffsetZ(float x, float z, int distance) {
return offsetY.getValue(x, z) * distance;
}
public float getTreeLine(float x, float z) {
return treeLine.getValue(x, z);
}
public void apply(Cell<Terrain> cell, float x, float z, boolean mask) {
biomeNoise.apply(cell, x, z, mask);
modifyTemp(cell, x, z);
}
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;
}
// temperature decreases away from 'midHeight' towards 'upperHeight'
if (height > midHeight) {
float delta = (height - midHeight) / (upperHeight - midHeight);
cell.temperature = Math.max(0, cell.temperature - (delta * temperatureModifier));
return;
}
height = Math.max(lowerHeight, height);
// temperature increases away from 'midHeight' towards 'lowerHeight'
if (height >= lowerHeight) {
float delta = 1 - ((height - lowerHeight) / (midHeight - lowerHeight));
cell.temperature = Math.min(1, cell.temperature + (delta * temperatureModifier));
}
}
}

View File

@ -1,166 +0,0 @@
/*
*
* MIT License
*
* Copyright (c) 2020 TerraForged
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package com.terraforged.core.world.climate;
import com.terraforged.core.cell.Cell;
import com.terraforged.core.settings.Settings;
import com.terraforged.core.util.Seed;
import com.terraforged.core.world.biome.BiomeType;
import com.terraforged.core.world.terrain.Terrain;
import me.dags.noise.Module;
import me.dags.noise.Source;
import me.dags.noise.func.DistanceFunc;
import me.dags.noise.func.EdgeFunc;
import me.dags.noise.util.NoiseUtil;
import me.dags.noise.util.Vec2f;
public class ClimateModule {
private final int seed;
private final float edgeClamp;
private final float edgeScale;
private final float biomeFreq;
private final float warpStrength;
private final Module warpX;
private final Module warpZ;
private final Module moisture;
private final Module temperature;
public ClimateModule(Seed seed, Settings settings) {
int biomeSize = settings.generator.biome.biomeSize;
// todo - better solution (reduces the amount that temp/moist grows with biome size)
int tempScaler = biomeSize > 500 ? 8 : 10;
int moistScaler = biomeSize > 500 ? 20 : 40;
float biomeFreq = 1F / biomeSize;
int moistureSize = moistScaler * biomeSize;
int temperatureSize = tempScaler * biomeSize;
int moistScale = NoiseUtil.round(moistureSize * biomeFreq);
int tempScale = NoiseUtil.round(temperatureSize * biomeFreq);
int warpScale = settings.generator.biome.biomeWarpScale;
this.seed = seed.next();
this.edgeClamp = 1F;
this.edgeScale = 1 / edgeClamp;
this.biomeFreq = 1F / biomeSize;
this.warpStrength = settings.generator.biome.biomeWarpStrength;
this.warpX = Source.perlin(seed.next(), warpScale, 2).bias(-0.5);
this.warpZ = Source.perlin(seed.next(), warpScale, 2).bias(-0.5);
Module moisture = Source.simplex(seed.next(), moistScale, 2).clamp(0.15, 0.85).map(0, 1);
this.moisture = settings.climate.moisture.clamp(moisture)
.warp(seed.next(), moistScale / 2, 1, moistScale / 4D)
.warp(seed.next(), moistScale / 6, 2, moistScale / 12D);
Module temperature = Source.sin(tempScale, Source.constant(0.9))
.clamp(0.05, 0.95).map(0, 1);
this.temperature = new Compressor(settings.climate.temperature.clamp(temperature), 0.1F, 0.2F)
.warp(seed.next(), tempScale * 4, 2, tempScale * 4)
.warp(seed.next(), tempScale, 1, tempScale)
.warp(seed.next(), tempScale / 8, 1, tempScale / 8D);
}
public void apply(Cell<Terrain> cell, float x, float y, boolean mask) {
float ox = warpX.getValue(x, y) * warpStrength;
float oz = warpZ.getValue(x, y) * warpStrength;
x += ox;
y += oz;
x *= biomeFreq;
y *= biomeFreq;
int cellX = 0;
int cellY = 0;
Vec2f vec2f = null;
int xr = NoiseUtil.round(x);
int yr = NoiseUtil.round(y);
float edgeDistance = 999999.0F;
float edgeDistance2 = 999999.0F;
float valueDistance = 3.4028235E38F;
DistanceFunc dist = DistanceFunc.NATURAL;
for (int dy = -1; dy <= 1; dy++) {
for (int dx = -1; dx <= 1; dx++) {
int xi = xr + dx;
int yi = yr + dy;
Vec2f vec = NoiseUtil.CELL_2D[NoiseUtil.hash2D(seed, xi, yi) & 255];
float vecX = xi - x + vec.x;
float vecY = yi - y + vec.y;
float distance = dist.apply(vecX, vecY);
if (distance < valueDistance) {
valueDistance = distance;
vec2f = vec;
cellX = xi;
cellY = yi;
}
if (distance < edgeDistance2) {
edgeDistance2 = Math.max(edgeDistance, distance);
} else {
edgeDistance2 = Math.max(edgeDistance, edgeDistance2);
}
edgeDistance = Math.min(edgeDistance, distance);
}
}
if (mask) {
cell.biomeEdge = edgeValue(edgeDistance, edgeDistance2);
} else {
cell.biome = cellValue(seed, cellX, cellY);
cell.biomeEdge = edgeValue(edgeDistance, edgeDistance2);
cell.biomeMoisture = moisture.getValue(cellX + vec2f.x, cellY + vec2f.y);
cell.biomeTemperature = temperature.getValue(cellX + vec2f.x, cellY + vec2f.y);
cell.moisture = moisture.getValue(x, y);
cell.temperature = temperature.getValue(x, y);
BiomeType.apply(cell);
}
}
private float cellValue(int seed, int cellX, int cellY) {
float value = NoiseUtil.valCoord2D(seed, cellX, cellY);
return NoiseUtil.map(value, -1, 1, 2);
}
private float edgeValue(float distance, float distance2) {
EdgeFunc edge = EdgeFunc.DISTANCE_2_DIV;
float value = edge.apply(distance, distance2);
value = 1 - NoiseUtil.map(value, edge.min(), edge.max(), edge.range());
if (value > edgeClamp) {
return 1F;
}
return value * edgeScale;
}
}

Some files were not shown because too many files have changed in this diff Show More