mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-04-03 06:16:10 +00:00
Merge branch 'gh-builds'
# Conflicts: # build.gradle.kts # src/main/java/com/dfsek/terra/config/genconfig/CarverConfig.java # src/main/java/com/dfsek/terra/config/genconfig/FloraConfig.java # src/main/java/com/dfsek/terra/config/genconfig/OreConfig.java # src/main/java/com/dfsek/terra/config/genconfig/PaletteConfig.java # src/main/java/com/dfsek/terra/config/genconfig/biome/BiomeConfig.java # src/main/java/com/dfsek/terra/config/genconfig/biome/BiomeSnowConfig.java # src/test/java/LookupGeneratorTest.java
This commit is contained in:
40
.github/workflows/build.yml
vendored
Normal file
40
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
# This workflow will build a Java project with Gradle
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle
|
||||
|
||||
name: Java CI with Gradle
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*" # Push events to matching v*, i.e. v1.0, v20.15.10
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Set up JDK 1.8
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 1.8
|
||||
|
||||
- name: Build Terra
|
||||
run: gradle shadowJar
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: Package
|
||||
path: build/libs
|
||||
|
||||
- name: Publish release
|
||||
uses: marvinpinto/action-automatic-releases@latest
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
prerelease: false
|
||||
files: |
|
||||
build/libs/Terra-*.jar
|
||||
LICENSE
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -135,4 +135,5 @@ build
|
||||
.idea/**.xml
|
||||
.idea/modules/**.iml
|
||||
|
||||
!lib/*.jar
|
||||
!lib/*.jar
|
||||
.idea/Terra.iml
|
||||
|
||||
@@ -15,7 +15,6 @@ plugins {
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
flatDir {
|
||||
dirs("lib")
|
||||
}
|
||||
@@ -23,6 +22,7 @@ repositories {
|
||||
maven { url = uri("http://maven.enginehub.org/repo/") }
|
||||
maven { url = uri("https://repo.codemc.org/repository/maven-public") }
|
||||
maven { url = uri("https://papermc.io/repo/repository/maven-public/") }
|
||||
// maven { url = uri("https://maven.pkg.github.com/solonovamax/Gaea") }
|
||||
}
|
||||
|
||||
java {
|
||||
@@ -30,49 +30,36 @@ java {
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
val versionObj = Version("1", "3", "1", true)
|
||||
val versionObj = Version("1", "5", "0", true)
|
||||
|
||||
version = versionObj
|
||||
|
||||
dependencies {
|
||||
|
||||
// Commons. Used for stuff.
|
||||
implementation("commons-io:commons-io:2.4")
|
||||
// Commons-imagine. Used for loading images from disk for the biome images.
|
||||
implementation("org.apache.commons:commons-imaging:1.0-alpha2")
|
||||
// Bstats. For tracking stats.
|
||||
implementation("org.bstats:bstats-bukkit:1.7")
|
||||
// Parsii. Does parsing of the equations.
|
||||
implementation(name = "parsii-1.2", group = "")
|
||||
// Papermc API. for Paper spigot
|
||||
implementation("io.papermc:paperlib:1.0.5")
|
||||
|
||||
// Jackson
|
||||
implementation("com.fasterxml.jackson.core:jackson-core:2.11+")
|
||||
implementation("com.fasterxml.jackson.core:jackson-annotations:2.11+")
|
||||
implementation("com.fasterxml.jackson.core:jackson-databind:2.11+")
|
||||
implementation("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:2.11+")
|
||||
|
||||
// Spigot mc API. Provided by spigot.
|
||||
compileOnly("org.spigotmc:spigot-api:1.16.2-R0.1-SNAPSHOT")
|
||||
// Annotations. Provided by mc.
|
||||
compileOnly("org.jetbrains:annotations:20.1.0")
|
||||
// Gaea. Provided as a plugin.
|
||||
val gaeaVersion = "1.14.2"
|
||||
val gaeaVersion = "1.14.3"
|
||||
compileOnly(name = "Gaea-${gaeaVersion}", group = "")
|
||||
testImplementation(name = "Gaea-${gaeaVersion}", group = "")
|
||||
// Worldedit. For saving structures. Provided as a plugin.
|
||||
|
||||
compileOnly("org.jetbrains:annotations:20.1.0")
|
||||
|
||||
implementation("commons-io:commons-io:2.4")
|
||||
implementation("org.apache.commons:commons-imaging:1.0-alpha2")
|
||||
|
||||
compileOnly("com.sk89q.worldedit:worldedit-bukkit:7.2.0-SNAPSHOT")
|
||||
// GSON. idk how it's used.
|
||||
implementation("org.bstats:bstats-bukkit:1.7")
|
||||
|
||||
compileOnly("com.googlecode.json-simple:json-simple:1.1")
|
||||
|
||||
// JUnit. Used for testing.
|
||||
implementation(name = "parsii-1.2.1", group = "")
|
||||
|
||||
compileOnly("org.spigotmc:spigot-api:1.16.2-R0.1-SNAPSHOT")
|
||||
implementation("io.papermc:paperlib:1.0.5")
|
||||
|
||||
implementation("net.jafama:jafama:2.3.2")
|
||||
|
||||
|
||||
// JUnit.
|
||||
testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.0")
|
||||
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.7.0")
|
||||
|
||||
// Included here becaues tests rely on it.
|
||||
testImplementation(name = "Gaea-1.14.2", group = "")
|
||||
testImplementation("org.spigotmc:spigot-api:1.16.2-R0.1-SNAPSHOT")
|
||||
}
|
||||
|
||||
val compileJava: JavaCompile by tasks
|
||||
@@ -81,6 +68,7 @@ val mainSourceSet: SourceSet = sourceSets["main"]
|
||||
val tokenizeJavaSources = task<Copy>(name = "tokenizeJavaSources") {
|
||||
from(mainSourceSet.allSource) {
|
||||
include("**/plugin.yml")
|
||||
println("version: $versionObj")
|
||||
val tokens = mapOf("VERSION" to versionObj.toString())
|
||||
|
||||
filter(org.apache.tools.ant.filters.ReplaceTokens::class, "tokens" to tokens)
|
||||
@@ -118,6 +106,8 @@ tasks.named<ShadowJar>("shadowJar") {
|
||||
relocate("org.bstats.bukkit", "com.dfsek.terra.lib.bstats")
|
||||
relocate("parsii", "com.dfsek.terra.lib.parsii")
|
||||
relocate("io.papermc.lib", "com.dfsek.terra.lib.paperlib")
|
||||
relocate("net.jafama", "com.dfsek.terra.lib.jafama")
|
||||
minimize()
|
||||
}
|
||||
|
||||
tasks.build {
|
||||
@@ -204,31 +194,13 @@ val testWithPaper = task<JavaExec>(name = "testWithPaper") {
|
||||
classpath = files("${testDir}/paper.jar")
|
||||
}
|
||||
|
||||
tasks.named<ShadowJar>("shadowJar") {
|
||||
archiveClassifier.set("")
|
||||
archiveBaseName.set("Terra")
|
||||
setVersion(project.version)
|
||||
relocate("org.apache.commons", "com.dfsek.terra.lib.commons")
|
||||
relocate("org.bstats.bukkit", "com.dfsek.terra.lib.bstats")
|
||||
relocate("parsii", "com.dfsek.terra.lib.parsii")
|
||||
relocate("io.papermc.lib", "com.dfsek.terra.lib.paperlib")
|
||||
relocate("com.fasterxml.jackson", "com.dfsek.terra.lib.jackson")
|
||||
}
|
||||
|
||||
tasks.build {
|
||||
dependsOn(tasks.test)
|
||||
dependsOn(tasks.shadowJar)
|
||||
// dependsOn(testWithPaper)
|
||||
tasks.shadowJar.get().mustRunAfter(tasks.test)
|
||||
// testWithPaper.mustRunAfter(tasks.shadowJar)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Version class that does version stuff.
|
||||
*/
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
class Version(val major: String, val minor: String, val revision: String, val preRelease: Boolean = false) {
|
||||
|
||||
override fun toString(): String {
|
||||
return if (!preRelease)
|
||||
"$major.$minor.$revision"
|
||||
@@ -239,25 +211,19 @@ class Version(val major: String, val minor: String, val revision: String, val pr
|
||||
|
||||
fun getGitHash(): String {
|
||||
val stdout = ByteArrayOutputStream()
|
||||
val exitCode = exec {
|
||||
exec {
|
||||
commandLine = mutableListOf("git", "rev-parse", "--short", "HEAD")
|
||||
standardOutput = stdout
|
||||
}.exitValue
|
||||
if (exitCode == 128) // https://canary.discord.com/channels/715448651786485780/765260067812540416/777236094768381954
|
||||
System.err.println("You can only use this in a git repo. Please run \"git clone https://github.com/PolyhedralDev/Terra.git\", then cd into there.")
|
||||
if (exitCode == 127 || exitCode == 9009) // https://canary.discord.com/channels/715448651786485780/715448652411437099/777304618853335082
|
||||
System.err.println("You must install git for this to work. https://git-scm.com/downloads")
|
||||
}
|
||||
return stdout.toString().trim()
|
||||
}
|
||||
|
||||
fun gitClone(name: String) {
|
||||
val stdout = ByteArrayOutputStream()
|
||||
val result = exec {
|
||||
exec {
|
||||
commandLine = mutableListOf("git", "clone", name)
|
||||
standardOutput = stdout
|
||||
}.exitValue
|
||||
if (result == 127 || result == 9009) // https://canary.discord.com/channels/715448651786485780/715448652411437099/777304618853335082
|
||||
System.err.println("You must install git for this to work.")
|
||||
}
|
||||
}
|
||||
|
||||
fun downloadAndUnzipPack(packUrl: URL) {
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -2,6 +2,7 @@ package com.dfsek.terra;
|
||||
|
||||
import com.dfsek.terra.async.AsyncStructureFinder;
|
||||
import com.dfsek.terra.config.base.ConfigPack;
|
||||
import com.dfsek.terra.config.genconfig.TreeConfig;
|
||||
import com.dfsek.terra.config.genconfig.structure.StructureConfig;
|
||||
import com.dfsek.terra.registry.TreeRegistry;
|
||||
import com.dfsek.terra.util.StructureTypeEnum;
|
||||
@@ -22,8 +23,7 @@ import org.bukkit.event.world.StructureGrowEvent;
|
||||
import org.polydev.gaea.GaeaPlugin;
|
||||
import org.polydev.gaea.tree.Tree;
|
||||
import org.polydev.gaea.tree.TreeType;
|
||||
|
||||
import java.util.Random;
|
||||
import org.polydev.gaea.util.FastRandom;
|
||||
|
||||
public class EventListener implements Listener {
|
||||
private final GaeaPlugin main;
|
||||
@@ -80,6 +80,10 @@ public class EventListener implements Listener {
|
||||
TreeRegistry registry = c.getTreeRegistry();
|
||||
Tree tree = registry.get(TreeType.fromBukkit(e.getSpecies()).toString());
|
||||
Debug.info("Overriding tree type: " + e.getSpecies());
|
||||
if(!tree.plant(e.getLocation(), new Random(), Terra.getInstance())) block.setBlockData(data);
|
||||
if(tree instanceof TreeConfig) {
|
||||
if(!((TreeConfig) tree).plantBlockCheck(e.getLocation(), new FastRandom())) {
|
||||
block.setBlockData(data);
|
||||
}
|
||||
} else if(!tree.plant(e.getLocation(), new FastRandom(), Terra.getInstance())) block.setBlockData(data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,12 +16,12 @@ public class TerraProfiler extends WorldProfiler {
|
||||
super(w);
|
||||
this
|
||||
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "FloraTime")
|
||||
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "TreeTime")
|
||||
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "OreTime")
|
||||
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "CaveTime")
|
||||
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "StructureTime")
|
||||
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "ElevationTime")
|
||||
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "SnowTime")
|
||||
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "CaveBlockUpdate");
|
||||
.addMeasurement(new Measurement(1500000, DataType.PERIOD_MILLISECONDS), "SnowTime");
|
||||
}
|
||||
|
||||
public static TerraProfiler fromWorld(World w) {
|
||||
|
||||
@@ -24,14 +24,6 @@ public class TerraWorld {
|
||||
private final WorldConfig worldConfig;
|
||||
private boolean safe;
|
||||
|
||||
public static void loadWorld(WorldConfig w) {
|
||||
loaded.put(w.getWorldID(), w);
|
||||
}
|
||||
|
||||
public static synchronized TerraWorld getWorld(World w) {
|
||||
return map.computeIfAbsent(w, TerraWorld::new);
|
||||
}
|
||||
|
||||
private TerraWorld(World w) {
|
||||
safe = true;
|
||||
worldConfig = loaded.get(w.getName());
|
||||
@@ -87,6 +79,14 @@ public class TerraWorld {
|
||||
grid = new TerraBiomeGrid(w, config.freq1, config.freq2, zone, config, erosion);
|
||||
}
|
||||
|
||||
public static void loadWorld(WorldConfig w) {
|
||||
loaded.put(w.getWorldID(), w);
|
||||
}
|
||||
|
||||
public static synchronized TerraWorld getWorld(World w) {
|
||||
return map.computeIfAbsent(w, TerraWorld::new);
|
||||
}
|
||||
|
||||
public static synchronized void invalidate() {
|
||||
map.clear();
|
||||
for(WorldConfig config : loaded.values()) {
|
||||
@@ -98,6 +98,10 @@ public class TerraWorld {
|
||||
return map.size();
|
||||
}
|
||||
|
||||
public static boolean isTerraWorld(World w) {
|
||||
return w.getGenerator() instanceof TerraChunkGenerator;
|
||||
}
|
||||
|
||||
public TerraBiomeGrid getGrid() {
|
||||
return grid;
|
||||
}
|
||||
@@ -117,8 +121,4 @@ public class TerraWorld {
|
||||
public boolean isSafe() {
|
||||
return safe;
|
||||
}
|
||||
|
||||
public static boolean isTerraWorld(World w) {
|
||||
return w.getGenerator() instanceof TerraChunkGenerator;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.dfsek.terra.async;
|
||||
|
||||
import com.dfsek.terra.biome.grid.TerraBiomeGrid;
|
||||
import com.dfsek.terra.config.base.ConfigUtil;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -27,11 +28,11 @@ public class AsyncBiomeFinder extends AsyncFeatureFinder<Biome> {
|
||||
*/
|
||||
@Override
|
||||
public boolean isValid(int x, int z, Biome target) {
|
||||
return getGrid().getBiome(x, z, GenerationPhase.POST_GEN).equals(target);
|
||||
return getGrid().getBiome(x * ConfigUtil.biomeSearchRes, z * ConfigUtil.biomeSearchRes, GenerationPhase.POST_GEN).equals(target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vector finalizeVector(Vector orig) {
|
||||
return orig;
|
||||
return orig.multiply(ConfigUtil.biomeSearchRes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.dfsek.terra.async;
|
||||
|
||||
import com.dfsek.terra.TerraWorld;
|
||||
import com.dfsek.terra.biome.UserDefinedBiome;
|
||||
import com.dfsek.terra.biome.grid.TerraBiomeGrid;
|
||||
import com.dfsek.terra.config.genconfig.structure.StructureConfig;
|
||||
@@ -10,6 +9,7 @@ import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.polydev.gaea.util.FastRandom;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.function.Consumer;
|
||||
@@ -33,9 +33,9 @@ public class AsyncStructureFinder extends AsyncFeatureFinder<StructureConfig> {
|
||||
public boolean isValid(int x, int z, StructureConfig target) {
|
||||
World world = getWorld();
|
||||
Location spawn = target.getSpawn().getChunkSpawn(x, z, world.getSeed()).toLocation(world);
|
||||
if(!TerraWorld.getWorld(world).getConfig().getBiome((UserDefinedBiome) getGrid().getBiome(spawn)).getStructures().contains(target))
|
||||
if(!((UserDefinedBiome) getGrid().getBiome(spawn)).getConfig().getStructures().contains(target))
|
||||
return false;
|
||||
Random r2 = new Random(spawn.hashCode());
|
||||
Random r2 = new FastRandom(spawn.hashCode());
|
||||
Structure struc = target.getStructure(r2);
|
||||
Rotation rotation = Rotation.fromDegrees(r2.nextInt(4) * 90);
|
||||
for(int y = target.getSearchStart().get(r2); y > 0; y--) {
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package com.dfsek.terra.biome;
|
||||
|
||||
import com.dfsek.terra.config.genconfig.biome.BiomeConfig;
|
||||
import com.dfsek.terra.config.genconfig.biome.GeneratorOptions;
|
||||
import com.dfsek.terra.generation.UserDefinedDecorator;
|
||||
import com.dfsek.terra.generation.UserDefinedGenerator;
|
||||
import org.bukkit.World;
|
||||
import org.polydev.gaea.biome.Biome;
|
||||
import org.polydev.gaea.biome.Decorator;
|
||||
import org.polydev.gaea.biome.Generator;
|
||||
@@ -13,19 +15,21 @@ import java.util.List;
|
||||
* Class representing a config-defined biome
|
||||
*/
|
||||
public class UserDefinedBiome implements Biome {
|
||||
private final UserDefinedGenerator gen;
|
||||
private final GeneratorOptions gen;
|
||||
private final UserDefinedDecorator decorator;
|
||||
private final org.bukkit.block.Biome vanilla;
|
||||
private final String id;
|
||||
private final BiomeConfig config;
|
||||
private final boolean erode;
|
||||
|
||||
|
||||
public UserDefinedBiome(org.bukkit.block.Biome vanilla, UserDefinedDecorator dec, UserDefinedGenerator gen, boolean erode, String id) {
|
||||
public UserDefinedBiome(org.bukkit.block.Biome vanilla, UserDefinedDecorator dec, GeneratorOptions gen, boolean erode, BiomeConfig config) {
|
||||
this.vanilla = vanilla;
|
||||
this.decorator = dec;
|
||||
this.gen = gen;
|
||||
this.id = id;
|
||||
this.id = config.getID();
|
||||
this.erode = erode;
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -45,7 +49,7 @@ public class UserDefinedBiome implements Biome {
|
||||
*/
|
||||
@Override
|
||||
public Generator getGenerator() {
|
||||
return gen;
|
||||
return gen.getGenerator(0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -75,4 +79,13 @@ public class UserDefinedBiome implements Biome {
|
||||
public boolean isErodible() {
|
||||
return erode;
|
||||
}
|
||||
|
||||
public BiomeConfig getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Generator getGenerator(World w) {
|
||||
return gen.getGenerator(w.getSeed());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
package com.dfsek.terra.biome.failsafe;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.polydev.gaea.biome.Biome;
|
||||
import parsii.tokenizer.ParseException;
|
||||
|
||||
/**
|
||||
* What happens if terrain generation is attempted with an unrecoverable config error.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public enum FailType {
|
||||
/**
|
||||
* Return failover biome, then shut down server to minimize damage.
|
||||
* Generally the safest option.
|
||||
*/
|
||||
SHUTDOWN {
|
||||
@Override
|
||||
public Biome fail() {
|
||||
Bukkit.getServer().shutdown();
|
||||
try {
|
||||
return new FailoverBiome();
|
||||
} catch(ParseException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Returns null, hard crashing the server, but not generating any corrupted terrain.<br>
|
||||
* This option is <b>NOT</b> stable, but it has the least risk of blank chunks being generated.
|
||||
* However, it has the highest risk of corruption!
|
||||
*/
|
||||
CRASH {
|
||||
@Override
|
||||
public Biome fail() {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Returns a failover biome, which generates completely blank chunks.
|
||||
* Recommended for debugging.
|
||||
*/
|
||||
FAILOVER {
|
||||
@Override
|
||||
public Biome fail() {
|
||||
try {
|
||||
return new FailoverBiome();
|
||||
} catch(ParseException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Performs the action specified by the enum type to occur on failure of terrain generation.
|
||||
*
|
||||
* @return Failover biome, if specified, null if not.
|
||||
*/
|
||||
public abstract Biome fail();
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package com.dfsek.terra.biome.failsafe;
|
||||
|
||||
import com.dfsek.terra.biome.UserDefinedBiome;
|
||||
import parsii.tokenizer.ParseException;
|
||||
|
||||
/**
|
||||
* Blank biome to generate in case of a severe config error
|
||||
*/
|
||||
public final class FailoverBiome extends UserDefinedBiome {
|
||||
public FailoverBiome() throws ParseException {
|
||||
super(org.bukkit.block.Biome.PLAINS, new FailoverDecorator(), new FailoverGenerator(), false, "FAILSAFE");
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
package com.dfsek.terra.biome.failsafe;
|
||||
|
||||
import com.dfsek.terra.generation.UserDefinedDecorator;
|
||||
import org.polydev.gaea.math.ProbabilityCollection;
|
||||
|
||||
public final class FailoverDecorator extends UserDefinedDecorator {
|
||||
public FailoverDecorator() {
|
||||
super(new ProbabilityCollection<>(), new ProbabilityCollection<>(), 0, 0);
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package com.dfsek.terra.biome.failsafe;
|
||||
|
||||
import com.dfsek.terra.generation.UserDefinedGenerator;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.polydev.gaea.world.palette.Palette;
|
||||
import org.polydev.gaea.world.palette.RandomPalette;
|
||||
import parsii.tokenizer.ParseException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Random;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public final class FailoverGenerator extends UserDefinedGenerator {
|
||||
private static final TreeMap<Integer, Palette<BlockData>> palette = new TreeMap<>();
|
||||
|
||||
static {
|
||||
palette.put(255, new RandomPalette<BlockData>(new Random(2403)).add(Material.STONE.createBlockData(), 1));
|
||||
}
|
||||
|
||||
public FailoverGenerator() throws ParseException {
|
||||
super("0", null, new HashMap<>(), palette, new TreeMap<>(), false);
|
||||
}
|
||||
}
|
||||
@@ -57,7 +57,7 @@ public class TerraBiomeGrid extends BiomeGrid {
|
||||
if(failNum % 256 == 0)
|
||||
LangUtil.log("error.severe-config", Level.SEVERE, String.valueOf(x), String.valueOf(z));
|
||||
failNum++;
|
||||
return ConfigUtil.failType.fail();
|
||||
return null;
|
||||
}
|
||||
if(erode != null && b.isErodible() && erode.isEroded(xp, zp)) {
|
||||
return erosionGrid.getBiome(xp, zp, phase);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.dfsek.terra.biome.postprocessing;
|
||||
|
||||
import net.jafama.FastMath;
|
||||
import org.polydev.gaea.math.FastNoiseLite;
|
||||
|
||||
/**
|
||||
@@ -27,7 +28,7 @@ public class ErosionNoise {
|
||||
* @return Whether location is eroded
|
||||
*/
|
||||
public boolean isEroded(int x, int z) {
|
||||
double abs = Math.pow(noise.getNoise(x, z), 2);
|
||||
double abs = FastMath.pow(noise.getNoise(x, z), 2);
|
||||
return abs < thresh;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.bukkit.World;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.polydev.gaea.math.FastNoiseLite;
|
||||
import org.polydev.gaea.math.MathUtil;
|
||||
import org.polydev.gaea.util.FastRandom;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
@@ -23,7 +24,7 @@ public class Cavern {
|
||||
|
||||
public VoxelGeometry carveChunk(int chunkX, int chunkZ) {
|
||||
long seedC = MathUtil.getCarverChunkSeed(chunkX, chunkZ, seed);
|
||||
Random chunk = new Random(seedC);
|
||||
Random chunk = new FastRandom(seedC);
|
||||
Vector org = node.getNodeLocation((chunkX << 4) + 8, (chunkZ << 4) + 8).clone().setY(chunk.nextInt(128));
|
||||
VoxelGeometry carve = VoxelGeometry.getBlank();
|
||||
|
||||
@@ -33,7 +34,7 @@ public class Cavern {
|
||||
Bukkit.getLogger().info("Cavern: " + org.toString());
|
||||
carve.merge(new DeformedSphere(org.clone(), chunk.nextInt(4) + 3, 0.75, smpl));
|
||||
|
||||
Vector _00 = new Vector(org.getX() + 16, new Random(MathUtil.getCarverChunkSeed(chunkX + 1, chunkZ, seed)).nextInt(128), org.getZ());
|
||||
Vector _00 = new Vector(org.getX() + 16, new FastRandom(MathUtil.getCarverChunkSeed(chunkX + 1, chunkZ, seed)).nextInt(128), org.getZ());
|
||||
|
||||
carve.merge(new Tube(org, _00, 4));
|
||||
return carve;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.dfsek.terra.carving;
|
||||
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.polydev.gaea.math.FastNoiseLite;
|
||||
@@ -15,7 +16,7 @@ public class SimplexCarver extends Carver {
|
||||
private final FastNoiseLite height;
|
||||
private final FastNoiseLite column;
|
||||
private final FastNoiseLite hasCaves;
|
||||
private final double root2inverse = 1D / Math.sqrt(2);
|
||||
private final double root2inverse = 1D / FastMath.sqrt(2);
|
||||
|
||||
public SimplexCarver(int minY, int maxY) {
|
||||
super(minY, maxY);
|
||||
@@ -40,6 +41,10 @@ public class SimplexCarver extends Carver {
|
||||
hasCaves.setFrequency(0.005f);
|
||||
}
|
||||
|
||||
private static double acot(double x) {
|
||||
return FastMath.PI / 2 - FastMath.atan(x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CarvingData carve(int chunkX, int chunkZ, World w) {
|
||||
CarvingData c = new CarvingData(chunkX, chunkZ);
|
||||
@@ -49,15 +54,15 @@ public class SimplexCarver extends Carver {
|
||||
for(int z = oz; z < oz + 16; z++) {
|
||||
double heightNoise = height.getNoise(x, z);
|
||||
double mainNoise = noise.getNoise(x, z) * 2;
|
||||
double columnNoise = Math.pow(Math.max(column.getNoise(x, z), 0) * 2, 3);
|
||||
double hc = (acot(16 * (hasCaves.getNoise(x, z) - 0.2)) / Math.PI) - 0.1;
|
||||
double columnNoise = FastMath.pow(FastMath.max(column.getNoise(x, z), 0) * 2, 3);
|
||||
double hc = (acot(16 * (hasCaves.getNoise(x, z) - 0.2)) / FastMath.PI) - 0.1;
|
||||
CarvingData.CarvingType type = CarvingData.CarvingType.BOTTOM;
|
||||
double simplex = (Math.pow(mainNoise + root2inverse, 3) / 2 + columnNoise) * hc;
|
||||
double simplex = (FastMath.pow(mainNoise + root2inverse, 3) / 2 + columnNoise) * hc;
|
||||
for(int y = 0; y < 64; y++) {
|
||||
double finalNoise = (-0.05 * Math.abs(y - (heightNoise * 16 + 24)) + 1 - simplex) * hc;
|
||||
double finalNoise = (-0.05 * FastMath.abs(y - (heightNoise * 16 + 24)) + 1 - simplex) * hc;
|
||||
if(finalNoise > 0.5) {
|
||||
c.carve(x - ox, y, z - oz, type);
|
||||
double finalNoiseUp = (-0.05 * Math.abs((y + 1) - (heightNoise * 16 + 24)) + 1 - simplex) * hc;
|
||||
double finalNoiseUp = (-0.05 * FastMath.abs((y + 1) - (heightNoise * 16 + 24)) + 1 - simplex) * hc;
|
||||
if(finalNoiseUp > 0.5) {
|
||||
type = CarvingData.CarvingType.CENTER;
|
||||
} else type = CarvingData.CarvingType.TOP;
|
||||
@@ -68,10 +73,6 @@ public class SimplexCarver extends Carver {
|
||||
return c;
|
||||
}
|
||||
|
||||
private static double acot(double x) {
|
||||
return Math.PI / 2 - Math.atan(x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Worm getWorm(long l, Vector vector) {
|
||||
return null;
|
||||
|
||||
@@ -3,10 +3,12 @@ package com.dfsek.terra.carving;
|
||||
import com.dfsek.terra.TerraWorld;
|
||||
import com.dfsek.terra.biome.UserDefinedBiome;
|
||||
import com.dfsek.terra.config.base.ConfigPack;
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.polydev.gaea.generation.GenerationPhase;
|
||||
import org.polydev.gaea.math.Range;
|
||||
import org.polydev.gaea.util.FastRandom;
|
||||
import org.polydev.gaea.world.carving.Carver;
|
||||
import org.polydev.gaea.world.carving.Worm;
|
||||
|
||||
@@ -39,7 +41,7 @@ public class UserDefinedCarver extends Carver {
|
||||
|
||||
@Override
|
||||
public Worm getWorm(long l, Vector vector) {
|
||||
Random r = new Random(l + hash);
|
||||
Random r = new FastRandom(l + hash);
|
||||
return new UserDefinedWorm(length.get(r) / 2, r, vector, radius.getMax(), topCut, bottomCut);
|
||||
}
|
||||
|
||||
@@ -58,7 +60,7 @@ public class UserDefinedCarver extends Carver {
|
||||
@Override
|
||||
public boolean isChunkCarved(World w, int chunkX, int chunkZ, Random random) {
|
||||
ConfigPack c = TerraWorld.getWorld(w).getConfig();
|
||||
return new Random(random.nextLong() + hash).nextInt(100) < c.getBiome((UserDefinedBiome) TerraWorld.getWorld(w).getGrid().getBiome(chunkX << 4, chunkZ << 4, GenerationPhase.POPULATE)).getCarverChance(this);
|
||||
return new FastRandom(random.nextLong() + hash).nextInt(100) < ((UserDefinedBiome) TerraWorld.getWorld(w).getGrid().getBiome(chunkX << 4, chunkZ << 4, GenerationPhase.POPULATE)).getConfig().getCarverChance(this);
|
||||
}
|
||||
|
||||
private class UserDefinedWorm extends Worm {
|
||||
@@ -81,9 +83,9 @@ public class UserDefinedCarver extends Carver {
|
||||
@Override
|
||||
public void step() {
|
||||
if(steps == nextDirection) {
|
||||
direction.rotateAroundX(Math.toRadians((getRandom().nextGaussian()) * mutate[0] * recalcMagnitude));
|
||||
direction.rotateAroundY(Math.toRadians((getRandom().nextGaussian()) * mutate[1] * recalcMagnitude));
|
||||
direction.rotateAroundZ(Math.toRadians((getRandom().nextGaussian()) * mutate[2] * recalcMagnitude));
|
||||
direction.rotateAroundX(FastMath.toRadians((getRandom().nextGaussian()) * mutate[0] * recalcMagnitude));
|
||||
direction.rotateAroundY(FastMath.toRadians((getRandom().nextGaussian()) * mutate[1] * recalcMagnitude));
|
||||
direction.rotateAroundZ(FastMath.toRadians((getRandom().nextGaussian()) * mutate[2] * recalcMagnitude));
|
||||
currentRotation = new double[] {(getRandom().nextGaussian()) * mutate[0],
|
||||
(getRandom().nextGaussian()) * mutate[1],
|
||||
(getRandom().nextGaussian()) * mutate[2]};
|
||||
@@ -92,10 +94,10 @@ public class UserDefinedCarver extends Carver {
|
||||
steps++;
|
||||
setRadius(new int[] {(int) (runningRadius * radiusMultiplier[0]), (int) (runningRadius * radiusMultiplier[1]), (int) (runningRadius * radiusMultiplier[2])});
|
||||
runningRadius += (getRandom().nextDouble() - 0.5) * mutate[3];
|
||||
runningRadius = Math.max(Math.min(runningRadius, maxRad), 1);
|
||||
direction.rotateAroundX(Math.toRadians(currentRotation[0] * mutate[0]));
|
||||
direction.rotateAroundY(Math.toRadians(currentRotation[1] * mutate[1]));
|
||||
direction.rotateAroundZ(Math.toRadians(currentRotation[2] * mutate[2]));
|
||||
runningRadius = FastMath.max(FastMath.min(runningRadius, maxRad), 1);
|
||||
direction.rotateAroundX(FastMath.toRadians(currentRotation[0] * mutate[0]));
|
||||
direction.rotateAroundY(FastMath.toRadians(currentRotation[1] * mutate[1]));
|
||||
direction.rotateAroundZ(FastMath.toRadians(currentRotation[2] * mutate[2]));
|
||||
getRunning().add(direction);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.dfsek.terra.command;
|
||||
import com.dfsek.terra.TerraWorld;
|
||||
import com.dfsek.terra.config.genconfig.OreConfig;
|
||||
import com.dfsek.terra.config.lang.LangUtil;
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.command.Command;
|
||||
@@ -11,10 +12,10 @@ import org.bukkit.entity.Player;
|
||||
import org.bukkit.util.Vector;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.polydev.gaea.command.WorldCommand;
|
||||
import org.polydev.gaea.util.FastRandom;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
public class OreCommand extends WorldCommand {
|
||||
public OreCommand(org.polydev.gaea.command.Command parent) {
|
||||
@@ -34,8 +35,8 @@ public class OreCommand extends WorldCommand {
|
||||
LangUtil.send("command.ore.out-of-range", sender);
|
||||
return true;
|
||||
}
|
||||
Vector source = new Vector(Math.floorMod(bl.getX(), 16), bl.getY(), Math.floorMod(bl.getZ(), 16));
|
||||
ore.doVein(source, bl.getChunk(), new Random());
|
||||
Vector source = new Vector(FastMath.floorMod(bl.getX(), 16), bl.getY(), FastMath.floorMod(bl.getZ(), 16));
|
||||
ore.doVein(source, bl.getChunk(), new FastRandom());
|
||||
} else {
|
||||
LangUtil.send("command.ore.main-menu", sender);
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ public class BiomeCommand extends WorldCommand {
|
||||
public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args, World w) {
|
||||
TerraBiomeGrid grid = TerraWorld.getWorld(sender.getWorld()).getGrid();
|
||||
UserDefinedBiome biome = (UserDefinedBiome) grid.getBiome(sender.getLocation(), GenerationPhase.POPULATE);
|
||||
LangUtil.send("command.biome.in", sender, TerraWorld.getWorld(w).getConfig().getBiome(biome).getID());
|
||||
LangUtil.send("command.biome.in", sender, biome.getID());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ public class BiomeInfoCommand extends WorldCommand {
|
||||
sender.sendMessage("Erodible: " + b.isErodible());
|
||||
|
||||
|
||||
BiomeConfig bio = cfg.getBiome(b);
|
||||
BiomeConfig bio = b.getConfig();
|
||||
List<StructureConfig> structureConfigs = bio.getStructures();
|
||||
|
||||
if(structureConfigs.size() == 0) sender.sendMessage("No Structures");
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.dfsek.terra.command.structure;
|
||||
|
||||
import com.dfsek.terra.command.structure.load.LoadCommand;
|
||||
import com.dfsek.terra.config.lang.LangUtil;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
package com.dfsek.terra.command.structure.load;
|
||||
|
||||
import com.dfsek.terra.Terra;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.polydev.gaea.command.DebugCommand;
|
||||
import org.polydev.gaea.command.PlayerCommand;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class LoadCommand extends PlayerCommand implements DebugCommand {
|
||||
public LoadCommand(org.polydev.gaea.command.Command parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
public static List<String> getStructureNames() {
|
||||
List<String> names = new ArrayList<>();
|
||||
File structureDir = new File(Terra.getInstance().getDataFolder() + File.separator + "export" + File.separator + "structures");
|
||||
if(!structureDir.exists()) return Collections.emptyList();
|
||||
Path structurePath = structureDir.toPath();
|
||||
|
||||
FilenameFilter filter = (dir, name) -> name.endsWith(".tstructure");
|
||||
for(File f : structureDir.listFiles(filter)) {
|
||||
String path = structurePath.relativize(f.toPath()).toString();
|
||||
names.add(path.substring(0, path.length() - 11));
|
||||
}
|
||||
return names;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "load";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<org.polydev.gaea.command.Command> getSubCommands() {
|
||||
return Arrays.asList(new LoadRawCommand(this), new LoadFullCommand(this, true), new LoadFullCommand(this, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int arguments() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.dfsek.terra.command.structure;
|
||||
package com.dfsek.terra.command.structure.load;
|
||||
|
||||
import com.dfsek.terra.Terra;
|
||||
import com.dfsek.terra.config.lang.LangUtil;
|
||||
@@ -15,14 +15,19 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class LoadCommand extends PlayerCommand implements DebugCommand {
|
||||
public LoadCommand(org.polydev.gaea.command.Command parent) {
|
||||
public class LoadFullCommand extends PlayerCommand implements DebugCommand {
|
||||
private final boolean chunk;
|
||||
|
||||
public LoadFullCommand(org.polydev.gaea.command.Command parent, boolean chunk) {
|
||||
super(parent);
|
||||
this.chunk = chunk;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
|
||||
public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String s, @NotNull String[] args) {
|
||||
try {
|
||||
Rotation r;
|
||||
try {
|
||||
@@ -32,8 +37,8 @@ public class LoadCommand extends PlayerCommand implements DebugCommand {
|
||||
return true;
|
||||
}
|
||||
Structure struc = Structure.load(new File(Terra.getInstance().getDataFolder() + File.separator + "export" + File.separator + "structures", args[0] + ".tstructure"));
|
||||
if("true".equals(args[2])) struc.paste(sender.getLocation(), r);
|
||||
else struc.paste(sender.getLocation(), sender.getLocation().getChunk(), r);
|
||||
if(chunk) struc.paste(sender.getLocation(), sender.getLocation().getChunk(), r);
|
||||
else struc.paste(sender.getLocation(), r);
|
||||
//sender.sendMessage(String.valueOf(struc.checkSpawns(sender.getLocation(), r)));
|
||||
} catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
@@ -44,7 +49,7 @@ public class LoadCommand extends PlayerCommand implements DebugCommand {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "load";
|
||||
return chunk ? "chunk" : "full";
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -54,11 +59,17 @@ public class LoadCommand extends PlayerCommand implements DebugCommand {
|
||||
|
||||
@Override
|
||||
public int arguments() {
|
||||
return 3;
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTabCompletions(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] args) {
|
||||
public List<String> getTabCompletions(@NotNull CommandSender commandSender, @NotNull String s, @NotNull String[] args) {
|
||||
switch(args.length) {
|
||||
case 1:
|
||||
return LoadCommand.getStructureNames().stream().filter(string -> string.toUpperCase().startsWith(args[0].toUpperCase())).collect(Collectors.toList());
|
||||
case 2:
|
||||
return Stream.of("0", "90", "180", "270").filter(string -> string.toUpperCase().startsWith(args[1].toUpperCase())).collect(Collectors.toList());
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
package com.dfsek.terra.command.structure.load;
|
||||
|
||||
import com.dfsek.terra.Terra;
|
||||
import com.dfsek.terra.config.lang.LangUtil;
|
||||
import com.dfsek.terra.structure.Structure;
|
||||
import com.dfsek.terra.structure.StructureContainedBlock;
|
||||
import com.dfsek.terra.structure.StructureInfo;
|
||||
import com.dfsek.terra.structure.StructureSpawnRequirement;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Sign;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.polydev.gaea.command.DebugCommand;
|
||||
import org.polydev.gaea.command.PlayerCommand;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class LoadRawCommand extends PlayerCommand implements DebugCommand {
|
||||
public LoadRawCommand(org.polydev.gaea.command.Command parent) {
|
||||
super(parent);
|
||||
}
|
||||
|
||||
private static void setTerraSign(Sign sign, String data) {
|
||||
sign.setLine(0, "[TERRA]");
|
||||
sign.setLine(2, data.substring(0, 16));
|
||||
sign.setLine(3, data.substring(16));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute(@NotNull Player sender, @NotNull Command command, @NotNull String s, @NotNull String[] args) {
|
||||
try {
|
||||
Structure struc = Structure.load(new File(Terra.getInstance().getDataFolder() + File.separator + "export" + File.separator + "structures", args[0] + ".tstructure"));
|
||||
StructureInfo info = struc.getStructureInfo();
|
||||
int centerX = info.getCenterX();
|
||||
int centerZ = info.getCenterZ();
|
||||
for(StructureContainedBlock[][] level0 : struc.getRawStructure()) {
|
||||
for(StructureContainedBlock[] level1 : level0) {
|
||||
for(StructureContainedBlock block : level1) {
|
||||
Location bLocation = sender.getLocation().add(block.getX() - centerX, block.getY(), block.getZ() - centerZ);
|
||||
if(!block.getPull().equals(StructureContainedBlock.Pull.NONE)) {
|
||||
bLocation.getBlock().setBlockData(Material.OAK_SIGN.createBlockData(), false);
|
||||
Sign sign = (Sign) bLocation.getBlock().getState();
|
||||
sign.setLine(1, "[PULL=" + block.getPull() + "_" + block.getPullOffset() + "]");
|
||||
String data = block.getBlockData().getAsString(true);
|
||||
setTerraSign(sign, data);
|
||||
sign.update();
|
||||
} else if(!block.getRequirement().equals(StructureSpawnRequirement.BLANK)) {
|
||||
bLocation.getBlock().setBlockData(Material.OAK_SIGN.createBlockData(), false);
|
||||
Sign sign = (Sign) bLocation.getBlock().getState();
|
||||
sign.setLine(1, "[SPAWN=" + block.getRequirement() + "]");
|
||||
String data = block.getBlockData().getAsString(true);
|
||||
setTerraSign(sign, data);
|
||||
sign.update();
|
||||
} else {
|
||||
bLocation.getBlock().setBlockData(block.getBlockData(), false);
|
||||
if(block.getState() != null) {
|
||||
block.getState().getState(bLocation.getBlock().getState()).update(true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(int y = 0; y < struc.getStructureInfo().getSizeY(); y++) {
|
||||
StructureContainedBlock block = struc.getRawStructure()[centerX][centerZ][y];
|
||||
if(block.getRequirement().equals(StructureSpawnRequirement.BLANK) && block.getPull().equals(StructureContainedBlock.Pull.NONE)) {
|
||||
Location bLocation = sender.getLocation().add(block.getX() - centerX, block.getY(), block.getZ() - centerZ);
|
||||
bLocation.getBlock().setBlockData(Material.OAK_SIGN.createBlockData(), false);
|
||||
Sign sign = (Sign) bLocation.getBlock().getState();
|
||||
sign.setLine(1, "[CENTER]");
|
||||
String data = block.getBlockData().getAsString(true);
|
||||
setTerraSign(sign, data);
|
||||
sign.update();
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
LangUtil.send("command.structure.invalid", sender, args[0]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "raw";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<org.polydev.gaea.command.Command> getSubCommands() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int arguments() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTabCompletions(@NotNull CommandSender commandSender, @NotNull String s, @NotNull String[] args) {
|
||||
if(args.length == 1) {
|
||||
return LoadCommand.getStructureNames().stream().filter(string -> string.toUpperCase().startsWith(args[0].toUpperCase())).collect(Collectors.toList());
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,6 @@ package com.dfsek.terra.config.base;
|
||||
|
||||
import com.dfsek.terra.Debug;
|
||||
import com.dfsek.terra.Terra;
|
||||
import com.dfsek.terra.biome.UserDefinedBiome;
|
||||
import com.dfsek.terra.carving.UserDefinedCarver;
|
||||
import com.dfsek.terra.config.ConfigLoader;
|
||||
import com.dfsek.terra.config.exception.ConfigException;
|
||||
@@ -15,6 +14,7 @@ import com.dfsek.terra.config.genconfig.PaletteConfig;
|
||||
import com.dfsek.terra.config.genconfig.TreeConfig;
|
||||
import com.dfsek.terra.config.genconfig.biome.AbstractBiomeConfig;
|
||||
import com.dfsek.terra.config.genconfig.biome.BiomeConfig;
|
||||
import com.dfsek.terra.config.genconfig.noise.NoiseConfig;
|
||||
import com.dfsek.terra.config.genconfig.structure.StructureConfig;
|
||||
import com.dfsek.terra.config.lang.LangUtil;
|
||||
import com.dfsek.terra.registry.FloraRegistry;
|
||||
@@ -24,6 +24,7 @@ import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
import parsii.eval.Scope;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -56,8 +57,6 @@ public class ConfigPack extends YamlConfiguration {
|
||||
public final int blendAmp;
|
||||
public final boolean biomeBlend;
|
||||
public final double blendFreq;
|
||||
public final int octaves;
|
||||
public final double frequency;
|
||||
public final boolean vanillaCaves;
|
||||
public final boolean vanillaStructures;
|
||||
public final boolean vanillaDecoration;
|
||||
@@ -75,7 +74,8 @@ public class ConfigPack extends YamlConfiguration {
|
||||
private final TreeRegistry treeRegistry = new TreeRegistry();
|
||||
private final FloraRegistry floraRegistry = new FloraRegistry();
|
||||
private final Set<StructureConfig> allStructures = new HashSet<>();
|
||||
private final Map<String, Double> definedVariables = new HashMap<>();
|
||||
private final Map<String, NoiseConfig> noiseBuilders = new HashMap<>();
|
||||
private final Scope vScope;
|
||||
private final File dataFolder;
|
||||
private final String id;
|
||||
|
||||
@@ -87,6 +87,13 @@ public class ConfigPack extends YamlConfiguration {
|
||||
if(!contains("id")) throw new ConfigException("No ID specified!", "null");
|
||||
this.id = getString("id");
|
||||
|
||||
Map<String, Object> noise = Objects.requireNonNull(getConfigurationSection("noise")).getValues(false);
|
||||
for(Map.Entry<String, Object> entry : noise.entrySet()) {
|
||||
NoiseConfig noiseConfig = new NoiseConfig((ConfigurationSection) entry.getValue());
|
||||
noiseBuilders.put(entry.getKey(), noiseConfig);
|
||||
Debug.info("Loaded noise function " + entry.getKey() + " with type " + noiseConfig.getBuilder().getType());
|
||||
}
|
||||
|
||||
ores = ConfigLoader.load(new File(file, "ores").toPath(), this, OreConfig.class);
|
||||
|
||||
palettes = ConfigLoader.load(new File(file, "palettes").toPath(), this, PaletteConfig.class);
|
||||
@@ -108,11 +115,12 @@ public class ConfigPack extends YamlConfiguration {
|
||||
Debug.info("Overriding Vanilla tree: " + entry.getKey());
|
||||
}
|
||||
|
||||
vScope = new Scope();
|
||||
if(contains("variables")) {
|
||||
Map<String, Object> vars = Objects.requireNonNull(getConfigurationSection("variables")).getValues(false);
|
||||
for(Map.Entry<String, Object> entry : vars.entrySet()) {
|
||||
try {
|
||||
definedVariables.put(entry.getKey(), Double.valueOf(entry.getValue().toString()));
|
||||
vScope.getVariable(entry.getKey()).setValue(Double.parseDouble(entry.getValue().toString()));
|
||||
Debug.info("Registered variable " + entry.getKey() + " with value " + entry.getValue());
|
||||
} catch(ClassCastException | NumberFormatException e) {
|
||||
Debug.stack(e);
|
||||
@@ -141,9 +149,6 @@ public class ConfigPack extends YamlConfiguration {
|
||||
erosionThresh = getDouble("erode.threshold", 0.04);
|
||||
erosionOctaves = getInt("erode.octaves", 3);
|
||||
|
||||
octaves = getInt("noise.octaves", 4);
|
||||
frequency = getDouble("noise.frequency", 1f / 96);
|
||||
|
||||
erosionName = getString("erode.grid");
|
||||
|
||||
vanillaCaves = getBoolean("vanilla.caves", false);
|
||||
@@ -190,26 +195,6 @@ public class ConfigPack extends YamlConfiguration {
|
||||
LangUtil.log("config-pack.loaded", Level.INFO, getID(), String.valueOf((System.nanoTime() - l) / 1000000D));
|
||||
}
|
||||
|
||||
public String getID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Map<String, Double> getDefinedVariables() {
|
||||
return definedVariables;
|
||||
}
|
||||
|
||||
public Map<String, BiomeConfig> getBiomes() {
|
||||
return biomes;
|
||||
}
|
||||
|
||||
public StructureConfig getStructure(String id) {
|
||||
return structures.get(id);
|
||||
}
|
||||
|
||||
public BiomeGridConfig getBiomeGrid(String id) {
|
||||
return grids.get(id);
|
||||
}
|
||||
|
||||
public static synchronized void loadAll(JavaPlugin main) {
|
||||
configs.clear();
|
||||
File file = new File(main.getDataFolder(), "packs");
|
||||
@@ -244,6 +229,30 @@ public class ConfigPack extends YamlConfiguration {
|
||||
return configs.get(id);
|
||||
}
|
||||
|
||||
public String getID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Scope getVariableScope() {
|
||||
return vScope;
|
||||
}
|
||||
|
||||
public Map<String, BiomeConfig> getBiomes() {
|
||||
return biomes;
|
||||
}
|
||||
|
||||
public StructureConfig getStructure(String id) {
|
||||
return structures.get(id);
|
||||
}
|
||||
|
||||
public BiomeGridConfig getBiomeGrid(String id) {
|
||||
return grids.get(id);
|
||||
}
|
||||
|
||||
public Map<String, NoiseConfig> getNoiseBuilders() {
|
||||
return noiseBuilders;
|
||||
}
|
||||
|
||||
public Map<StructureTypeEnum, StructureConfig> getLocatable() {
|
||||
return locatable;
|
||||
}
|
||||
@@ -264,13 +273,6 @@ public class ConfigPack extends YamlConfiguration {
|
||||
return dataFolder;
|
||||
}
|
||||
|
||||
public BiomeConfig getBiome(UserDefinedBiome b) {
|
||||
for(BiomeConfig biome : biomes.values()) {
|
||||
if(biome.getBiome().equals(b)) return biome;
|
||||
}
|
||||
throw new IllegalArgumentException("No BiomeConfig for provided biome.");
|
||||
}
|
||||
|
||||
public BiomeConfig getBiome(String id) {
|
||||
return biomes.get(id);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.dfsek.terra.config.base;
|
||||
import com.dfsek.terra.Debug;
|
||||
import com.dfsek.terra.Terra;
|
||||
import com.dfsek.terra.TerraWorld;
|
||||
import com.dfsek.terra.biome.failsafe.FailType;
|
||||
import com.dfsek.terra.config.exception.ConfigException;
|
||||
import com.dfsek.terra.config.lang.LangUtil;
|
||||
import com.dfsek.terra.util.TagUtil;
|
||||
@@ -18,20 +17,19 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.time.Duration;
|
||||
import java.util.HashSet;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public final class ConfigUtil {
|
||||
public static boolean debug;
|
||||
public static long dataSave; // Period of population data saving, in ticks.
|
||||
public static boolean masterDisableCaves;
|
||||
public static int biomeSearchRes;
|
||||
public static int cacheSize;
|
||||
public static FailType failType;
|
||||
|
||||
public static void loadConfig(JavaPlugin main) {
|
||||
main.saveDefaultConfig();
|
||||
@@ -40,9 +38,10 @@ public final class ConfigUtil {
|
||||
LangUtil.load(config.getString("language", "en_us"), main);
|
||||
|
||||
debug = config.getBoolean("debug", false);
|
||||
cacheSize = config.getInt("cache-size", 3);
|
||||
dataSave = Duration.parse(Objects.requireNonNull(config.getString("data-save", "PT6M"))).toMillis() / 20L;
|
||||
masterDisableCaves = config.getBoolean("master-disable.caves", false);
|
||||
biomeSearchRes = config.getInt("biome-search-resolution", 4);
|
||||
cacheSize = config.getInt("cache-size", 384);
|
||||
|
||||
if(config.getBoolean("dump-default", true)) {
|
||||
try(JarFile jar = new JarFile(new File(Terra.class.getProtectionDomain().getCodeSource().getLocation().toURI()))) {
|
||||
@@ -54,14 +53,6 @@ public final class ConfigUtil {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
String fail = config.getString("fail-type", "SHUTDOWN");
|
||||
try {
|
||||
failType = FailType.valueOf(fail);
|
||||
} catch(IllegalArgumentException e) {
|
||||
LangUtil.log("config.invalid-failover", Level.SEVERE, fail);
|
||||
}
|
||||
|
||||
Logger logger = main.getLogger();
|
||||
logger.info("Loading config values");
|
||||
|
||||
@@ -70,7 +61,7 @@ public final class ConfigUtil {
|
||||
}
|
||||
|
||||
public static Set<Material> toBlockData(List<String> list, String phase, String id) throws InvalidConfigurationException {
|
||||
Set<Material> bl = new HashSet<>();
|
||||
Set<Material> bl = EnumSet.noneOf(Material.class);
|
||||
for(String s : list) {
|
||||
try {
|
||||
if(s.startsWith("#")) {
|
||||
|
||||
@@ -42,7 +42,7 @@ public class WorldConfig {
|
||||
FileConfiguration config = new YamlConfiguration();
|
||||
Debug.info("Loading config " + configID + " for world " + worldID);
|
||||
try { // Load/create world config file
|
||||
if(configID == null || configID.equals(""))
|
||||
if(configID == null || configID.isEmpty())
|
||||
throw new ConfigException("Config pack unspecified in bukkit.yml!", worldID);
|
||||
File configFile = new File(main.getDataFolder() + File.separator + "worlds", worldID + ".yml");
|
||||
if(!configFile.exists()) {
|
||||
|
||||
@@ -15,8 +15,8 @@ import org.polydev.gaea.math.Range;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
@@ -45,8 +45,9 @@ public class CarverConfig extends TerraConfig {
|
||||
@SuppressWarnings("unchecked")
|
||||
public CarverConfig(File file, ConfigPack config) throws IOException, InvalidConfigurationException {
|
||||
super(file, config);
|
||||
if(!yaml.contains("id")) throw new ConfigException("No ID specified for Carver!", "null");
|
||||
id = Objects.requireNonNull(yaml.getString("id"));
|
||||
load(file);
|
||||
if(!contains("id")) throw new ConfigException("No ID specified for Carver!", "null");
|
||||
id = Objects.requireNonNull(getString("id"));
|
||||
|
||||
inner = getBlocks("palette.inner.layers");
|
||||
|
||||
@@ -56,24 +57,24 @@ public class CarverConfig extends TerraConfig {
|
||||
|
||||
bottom = getBlocks("palette.bottom.layers");
|
||||
|
||||
replaceableInner = ConfigUtil.toBlockData(yaml.getStringList("palette.inner.replace"), "replaceable inner", getID());
|
||||
replaceableInner = ConfigUtil.toBlockData(getStringList("palette.inner.replace"), "replaceable inner", getID());
|
||||
|
||||
replaceableOuter = ConfigUtil.toBlockData(yaml.getStringList("palette.outer.replace"), "replaceable outer", getID());
|
||||
replaceableOuter = ConfigUtil.toBlockData(getStringList("palette.outer.replace"), "replaceable outer", getID());
|
||||
|
||||
replaceableTop = ConfigUtil.toBlockData(yaml.getStringList("palette.top.replace"), "replaceable top", getID());
|
||||
replaceableTop = ConfigUtil.toBlockData(getStringList("palette.top.replace"), "replaceable top", getID());
|
||||
|
||||
replaceableBottom = ConfigUtil.toBlockData(yaml.getStringList("palette.bottom.replace"), "replaceable bottom", getID());
|
||||
replaceableBottom = ConfigUtil.toBlockData(getStringList("palette.bottom.replace"), "replaceable bottom", getID());
|
||||
|
||||
update = ConfigUtil.toBlockData(yaml.getStringList("update"), "update", getID());
|
||||
update = ConfigUtil.toBlockData(getStringList("update"), "update", getID());
|
||||
|
||||
updateOcean = yaml.getBoolean("update-liquids", false);
|
||||
updateOcean = getBoolean("update-liquids", false);
|
||||
|
||||
double step = yaml.getDouble("step", 2);
|
||||
Range recalc = new Range(yaml.getInt("recalculate-direction.min", 8), yaml.getInt("recalculate-direction.max", 12));
|
||||
double rm = yaml.getDouble("recalculate-magnitude", 4);
|
||||
double step = getDouble("step", 2);
|
||||
Range recalc = new Range(getInt("recalculate-direction.min", 8), getInt("recalculate-direction.max", 12));
|
||||
double rm = getDouble("recalculate-magnitude", 4);
|
||||
shift = new HashMap<>();
|
||||
for(Map.Entry<String, Object> e : Objects.requireNonNull(yaml.getConfigurationSection("shift")).getValues(false).entrySet()) {
|
||||
Set<Material> l = new HashSet<>();
|
||||
for(Map.Entry<String, Object> e : Objects.requireNonNull(getConfigurationSection("shift")).getValues(false).entrySet()) {
|
||||
Set<Material> l = EnumSet.noneOf(Material.class);
|
||||
for(String s : (List<String>) e.getValue()) {
|
||||
l.add(Bukkit.createBlockData(s).getMaterial());
|
||||
Debug.info("Added " + s + " to shift-able blocks");
|
||||
@@ -82,19 +83,19 @@ public class CarverConfig extends TerraConfig {
|
||||
Debug.info("Added " + e.getKey() + " as master block");
|
||||
}
|
||||
|
||||
replaceIsBlacklistInner = yaml.getBoolean("palette.inner.replace-blacklist", false);
|
||||
replaceIsBlacklistOuter = yaml.getBoolean("palette.outer.replace-blacklist", false);
|
||||
replaceIsBlacklistTop = yaml.getBoolean("palette.top.replace-blacklist", false);
|
||||
replaceIsBlacklistBottom = yaml.getBoolean("palette.bottom.replace-blacklist", false);
|
||||
replaceIsBlacklistInner = getBoolean("palette.inner.replace-blacklist", false);
|
||||
replaceIsBlacklistOuter = getBoolean("palette.outer.replace-blacklist", false);
|
||||
replaceIsBlacklistTop = getBoolean("palette.top.replace-blacklist", false);
|
||||
replaceIsBlacklistBottom = getBoolean("palette.bottom.replace-blacklist", false);
|
||||
|
||||
double[] start = new double[] {yaml.getDouble("start.x"), yaml.getDouble("start.y"), yaml.getDouble("start.z")};
|
||||
double[] mutate = new double[] {yaml.getDouble("mutate.x"), yaml.getDouble("mutate.y"), yaml.getDouble("mutate.z"), yaml.getDouble("mutate.radius")};
|
||||
double[] radiusMultiplier = new double[] {yaml.getDouble("start.radius.multiply.x"), yaml.getDouble("start.radius.multiply.y"), yaml.getDouble("start.radius.multiply.z")};
|
||||
Range length = new Range(yaml.getInt("length.min"), yaml.getInt("length.max"));
|
||||
Range radius = new Range(yaml.getInt("start.radius.min"), yaml.getInt("start.radius.max"));
|
||||
Range height = new Range(yaml.getInt("start.height.min"), yaml.getInt("start.height.max"));
|
||||
double[] start = new double[] {getDouble("start.x"), getDouble("start.y"), getDouble("start.z")};
|
||||
double[] mutate = new double[] {getDouble("mutate.x"), getDouble("mutate.y"), getDouble("mutate.z"), getDouble("mutate.radius")};
|
||||
double[] radiusMultiplier = new double[] {getDouble("start.radius.multiply.x"), getDouble("start.radius.multiply.y"), getDouble("start.radius.multiply.z")};
|
||||
Range length = new Range(getInt("length.min"), getInt("length.max"));
|
||||
Range radius = new Range(getInt("start.radius.min"), getInt("start.radius.max"));
|
||||
Range height = new Range(getInt("start.height.min"), getInt("start.height.max"));
|
||||
|
||||
carver = new UserDefinedCarver(height, radius, length, start, mutate, radiusMultiplier, id.hashCode(), yaml.getInt("cut.top", 0), yaml.getInt("cut.bottom", 0));
|
||||
carver = new UserDefinedCarver(height, radius, length, start, mutate, radiusMultiplier, id.hashCode(), getInt("cut.top", 0), getInt("cut.bottom", 0));
|
||||
carver.setStep(step);
|
||||
carver.setRecalc(recalc);
|
||||
carver.setRecalcMagnitude(rm);
|
||||
@@ -102,9 +103,9 @@ public class CarverConfig extends TerraConfig {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<Integer, ProbabilityCollection<BlockData>> getBlocks(String key) throws InvalidConfigurationException {
|
||||
if(!yaml.contains(key)) throw new ConfigException("Missing Carver Palette!", getID());
|
||||
if(!contains(key)) throw new ConfigException("Missing Carver Palette!", getID());
|
||||
Map<Integer, ProbabilityCollection<BlockData>> result = new TreeMap<>();
|
||||
for(Map<?, ?> m : yaml.getMapList(key)) {
|
||||
for(Map<?, ?> m : getMapList(key)) {
|
||||
try {
|
||||
ProbabilityCollection<BlockData> layer = new ProbabilityCollection<>();
|
||||
for(Map.Entry<String, Integer> type : ((Map<String, Integer>) m.get("materials")).entrySet()) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.dfsek.terra.config.TerraConfig;
|
||||
import com.dfsek.terra.config.base.ConfigPack;
|
||||
import com.dfsek.terra.config.base.ConfigUtil;
|
||||
import com.dfsek.terra.config.exception.ConfigException;
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
@@ -12,6 +13,7 @@ import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.polydev.gaea.math.Range;
|
||||
import org.polydev.gaea.util.FastRandom;
|
||||
import org.polydev.gaea.world.Flora;
|
||||
import org.polydev.gaea.world.palette.Palette;
|
||||
import org.polydev.gaea.world.palette.RandomPalette;
|
||||
@@ -20,7 +22,6 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
public class FloraConfig extends TerraConfig implements Flora {
|
||||
@@ -36,24 +37,25 @@ public class FloraConfig extends TerraConfig implements Flora {
|
||||
|
||||
public FloraConfig(File file, ConfigPack config) throws IOException, InvalidConfigurationException {
|
||||
super(file, config);
|
||||
if(!yaml.contains("id")) throw new ConfigException("Flora ID unspecified!", "null");
|
||||
this.id = yaml.getString("id");
|
||||
if(!yaml.contains("layers")) throw new ConfigException("No blocks defined in custom flora!", getID());
|
||||
if(!yaml.contains("spawnable")) throw new ConfigException("Flora spawnable blocks unspecified!", getID());
|
||||
load(file);
|
||||
if(!contains("id")) throw new ConfigException("Flora ID unspecified!", "null");
|
||||
this.id = getString("id");
|
||||
if(!contains("layers")) throw new ConfigException("No blocks defined in custom flora!", getID());
|
||||
if(!contains("spawnable")) throw new ConfigException("Flora spawnable blocks unspecified!", getID());
|
||||
|
||||
spawnable = ConfigUtil.toBlockData(yaml.getStringList("spawnable"), "spawnable", getID());
|
||||
replaceable = ConfigUtil.toBlockData(yaml.getStringList("replaceable"), "replaceable", getID());
|
||||
spawnable = ConfigUtil.toBlockData(getStringList("spawnable"), "spawnable", getID());
|
||||
replaceable = ConfigUtil.toBlockData(getStringList("replaceable"), "replaceable", getID());
|
||||
|
||||
if(yaml.contains("irrigable")) {
|
||||
irrigable = ConfigUtil.toBlockData(yaml.getStringList("irrigable"), "irrigable", getID());
|
||||
if(contains("irrigable")) {
|
||||
irrigable = ConfigUtil.toBlockData(getStringList("irrigable"), "irrigable", getID());
|
||||
} else irrigable = null;
|
||||
|
||||
physics = yaml.getBoolean("physics", false);
|
||||
ceiling = yaml.getBoolean("ceiling", false);
|
||||
physics = getBoolean("physics", false);
|
||||
ceiling = getBoolean("ceiling", false);
|
||||
|
||||
Palette<BlockData> p = new RandomPalette<>(new Random(yaml.getInt("seed", 4)));
|
||||
Palette<BlockData> p = new RandomPalette<>(new FastRandom(getInt("seed", 4)));
|
||||
|
||||
floraPalette = PaletteConfig.getPalette(yaml.getMapList("layers"), p);
|
||||
floraPalette = PaletteConfig.getPalette(getMapList("layers"), p);
|
||||
}
|
||||
|
||||
public String getID() {
|
||||
@@ -62,26 +64,28 @@ public class FloraConfig extends TerraConfig implements Flora {
|
||||
|
||||
@Override
|
||||
public List<Block> getValidSpawnsAt(Chunk chunk, int x, int z, Range range) {
|
||||
int size = floraPalette.getSize();
|
||||
Block current = chunk.getBlock(x, range.getMin(), z);
|
||||
List<Block> blocks = new ArrayList<>();
|
||||
if(ceiling) for(int y : range) {
|
||||
if(y > 255 || y < 1) continue;
|
||||
Block check = chunk.getBlock(x, y, z);
|
||||
Block other = check.getRelative(BlockFace.DOWN);
|
||||
if(spawnable.contains(check.getType()) && replaceable.contains(other.getType())) {
|
||||
blocks.add(check);
|
||||
}
|
||||
}
|
||||
else for(int y : range) {
|
||||
if(y > 254 || y < 0) continue;
|
||||
Block check = chunk.getBlock(x, y, z);
|
||||
Block other = check.getRelative(BlockFace.UP);
|
||||
if(spawnable.contains(check.getType()) && replaceable.contains(other.getType()) && isIrrigated(check)) {
|
||||
blocks.add(check);
|
||||
for(int y : range) {
|
||||
if(y > 255 || y < 0) continue;
|
||||
current = current.getRelative(BlockFace.UP);
|
||||
if(spawnable.contains(current.getType()) && isIrrigated(current) && valid(size, current)) {
|
||||
blocks.add(current);
|
||||
}
|
||||
}
|
||||
return blocks;
|
||||
}
|
||||
|
||||
private boolean valid(int size, Block block) {
|
||||
for(int i = 0; i < size; i++) { // Down if ceiling, up if floor
|
||||
if(block.getY() + 1 > 255 || block.getY() < 0) return false;
|
||||
block = block.getRelative(ceiling ? BlockFace.DOWN : BlockFace.UP);
|
||||
if(!replaceable.contains(block.getType())) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean isIrrigated(Block b) {
|
||||
if(irrigable == null) return true;
|
||||
return irrigable.contains(b.getRelative(BlockFace.NORTH).getType())
|
||||
@@ -94,12 +98,8 @@ public class FloraConfig extends TerraConfig implements Flora {
|
||||
public boolean plant(Location location) {
|
||||
int size = floraPalette.getSize();
|
||||
int c = ceiling ? -1 : 1;
|
||||
for(int i = 0; Math.abs(i) < size; i += c) { // Down if ceiling, up if floor
|
||||
if(i + 1 > 255) return false;
|
||||
if(!replaceable.contains(location.clone().add(0, i + c, 0).getBlock().getType())) return false;
|
||||
}
|
||||
for(int i = 0; Math.abs(i) < size; i += c) { // Down if ceiling, up if floor
|
||||
int lvl = (Math.abs(i));
|
||||
for(int i = 0; FastMath.abs(i) < size; i += c) { // Down if ceiling, up if floor
|
||||
int lvl = (FastMath.abs(i));
|
||||
location.clone().add(0, i + c, 0).getBlock().setBlockData(floraPalette.get((ceiling ? lvl : size - lvl - 1), location.getBlockX(), location.getBlockZ()), physics);
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.dfsek.terra.config.TerraConfig;
|
||||
import com.dfsek.terra.config.base.ConfigPack;
|
||||
import com.dfsek.terra.config.base.ConfigUtil;
|
||||
import com.dfsek.terra.config.exception.ConfigException;
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Material;
|
||||
@@ -30,34 +31,27 @@ public class OreConfig extends TerraConfig {
|
||||
private final double deformFrequency;
|
||||
private final String id;
|
||||
private final boolean update;
|
||||
private final boolean crossChunks;
|
||||
private final int chunkEdgeOffset;
|
||||
Set<Material> replaceable;
|
||||
|
||||
public OreConfig(File file, ConfigPack config) throws IOException, InvalidConfigurationException {
|
||||
super(file, config);
|
||||
if(!yaml.contains("id")) throw new ConfigException("Ore ID not found!", "null");
|
||||
this.id = yaml.getString("id");
|
||||
if(!yaml.contains("material")) throw new ConfigException("Ore material not found!", getID());
|
||||
if(!yaml.contains("deform")) throw new ConfigException("Ore vein deformation not found!", getID());
|
||||
if(!yaml.contains("replace")) throw new ConfigException("Ore replaceable materials not found!", getID());
|
||||
min = yaml.getInt("radius.min", 1);
|
||||
max = yaml.getInt("radius.max", 1);
|
||||
deform = yaml.getDouble("deform", 0.75);
|
||||
deformFrequency = yaml.getDouble("deform-frequency", 0.1);
|
||||
update = yaml.getBoolean("update", false);
|
||||
crossChunks = yaml.getBoolean("cross-chunks", true);
|
||||
chunkEdgeOffset = yaml.getInt("edge-offset", 1);
|
||||
if(!contains("id")) throw new ConfigException("Ore ID not found!", "null");
|
||||
this.id = getString("id");
|
||||
if(!contains("material")) throw new ConfigException("Ore material not found!", getID());
|
||||
if(!contains("deform")) throw new ConfigException("Ore vein deformation not found!", getID());
|
||||
if(!contains("replace")) throw new ConfigException("Ore replaceable materials not found!", getID());
|
||||
min = getInt("radius.min", 1);
|
||||
max = getInt("radius.max", 1);
|
||||
deform = getDouble("deform", 0.75);
|
||||
deformFrequency = getDouble("deform-frequency", 0.1);
|
||||
update = getBoolean("update", false);
|
||||
|
||||
if(chunkEdgeOffset > 7 || chunkEdgeOffset < 0)
|
||||
throw new ConfigException("Edge offset is too high/low!", getID());
|
||||
|
||||
replaceable = ConfigUtil.toBlockData(yaml.getStringList("replace"), "replaceable", getID());
|
||||
replaceable = ConfigUtil.toBlockData(getStringList("replace"), "replaceable", getID());
|
||||
|
||||
try {
|
||||
oreData = Bukkit.createBlockData(Objects.requireNonNull(yaml.getString("material")));
|
||||
oreData = Bukkit.createBlockData(Objects.requireNonNull(getString("material")));
|
||||
} catch(NullPointerException | IllegalArgumentException e) {
|
||||
throw new ConfigException("Invalid ore material: " + yaml.getString("material"), getID());
|
||||
throw new ConfigException("Invalid ore material: " + getString("material"), getID());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,9 +74,9 @@ public class OreConfig extends TerraConfig {
|
||||
Vector source = l.clone().add(new Vector(x, y, z));
|
||||
if(oreLoc.getBlockY() > 255 || oreLoc.getBlockY() < 0) continue;
|
||||
if(source.distance(l) < (rad + 0.5) * ((ore.getNoise(x, y, z) + 1) * deform)) {
|
||||
ChunkCoordinate coord = new ChunkCoordinate(Math.floorDiv(oreLoc.getBlockX(), 16), Math.floorDiv(oreLoc.getBlockZ(), 16), chunk.getWorld().getUID());
|
||||
ChunkCoordinate coord = new ChunkCoordinate(FastMath.floorDiv(oreLoc.getBlockX(), 16), FastMath.floorDiv(oreLoc.getBlockZ(), 16), chunk.getWorld().getUID());
|
||||
Block b = chunks.computeIfAbsent(coord, k -> chunk.getWorld().getChunkAt(oreLoc.toLocation(chunk.getWorld())))
|
||||
.getBlock(Math.floorMod(source.getBlockX(), 16), source.getBlockY(), Math.floorMod(source.getBlockZ(), 16)); // Chunk caching conditional computation
|
||||
.getBlock(FastMath.floorMod(source.getBlockX(), 16), source.getBlockY(), FastMath.floorMod(source.getBlockZ(), 16)); // Chunk caching conditional computation
|
||||
if(replaceable.contains(b.getType()) && b.getLocation().getY() >= 0)
|
||||
b.setBlockData(oreData, update);
|
||||
}
|
||||
@@ -120,12 +114,4 @@ public class OreConfig extends TerraConfig {
|
||||
public String toString() {
|
||||
return "Ore with ID " + getID();
|
||||
}
|
||||
|
||||
public boolean crossChunks() {
|
||||
return crossChunks;
|
||||
}
|
||||
|
||||
public int getChunkEdgeOffset() {
|
||||
return chunkEdgeOffset;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.polydev.gaea.math.FastNoiseLite;
|
||||
import org.polydev.gaea.math.ProbabilityCollection;
|
||||
import org.polydev.gaea.util.FastRandom;
|
||||
import org.polydev.gaea.world.palette.Palette;
|
||||
import org.polydev.gaea.world.palette.RandomPalette;
|
||||
import org.polydev.gaea.world.palette.SimplexPalette;
|
||||
@@ -17,7 +18,6 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
public class PaletteConfig extends TerraConfig {
|
||||
private final Palette<BlockData> palette;
|
||||
@@ -26,18 +26,18 @@ public class PaletteConfig extends TerraConfig {
|
||||
|
||||
public PaletteConfig(File file, ConfigPack config) throws IOException, InvalidConfigurationException {
|
||||
super(file, config);
|
||||
if(!yaml.contains("id")) throw new ConfigException("Palette ID unspecified!", "null");
|
||||
this.paletteID = yaml.getString("id");
|
||||
if(!contains("id")) throw new ConfigException("Palette ID unspecified!", "null");
|
||||
this.paletteID = getString("id");
|
||||
Palette<BlockData> pal;
|
||||
if(yaml.getBoolean("simplex", false)) {
|
||||
if(getBoolean("simplex", false)) {
|
||||
useNoise = true;
|
||||
FastNoiseLite pNoise = new FastNoiseLite(yaml.getInt("seed", 2403));
|
||||
FastNoiseLite pNoise = new FastNoiseLite(getInt("seed", 2403));
|
||||
pNoise.setNoiseType(FastNoiseLite.NoiseType.OpenSimplex2);
|
||||
pNoise.setFractalOctaves(4);
|
||||
pNoise.setFrequency(yaml.getDouble("frequency", 0.02));
|
||||
pNoise.setFrequency(getDouble("frequency", 0.02));
|
||||
pal = new SimplexPalette<>(pNoise);
|
||||
} else pal = new RandomPalette<>(new Random(yaml.getInt("seed", 2403)));
|
||||
palette = getPalette(yaml.getMapList("layers"), pal);
|
||||
} else pal = new RandomPalette<>(new FastRandom(getInt("seed", 2403)));
|
||||
palette = getPalette(getMapList("layers"), pal);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
@@ -6,8 +6,12 @@ import com.dfsek.terra.config.base.ConfigPack;
|
||||
import com.dfsek.terra.config.base.ConfigUtil;
|
||||
import com.dfsek.terra.config.exception.ConfigException;
|
||||
import com.dfsek.terra.config.exception.NotFoundException;
|
||||
import com.dfsek.terra.procgen.math.Vector2;
|
||||
import com.dfsek.terra.structure.Rotation;
|
||||
import com.dfsek.terra.structure.Structure;
|
||||
import com.dfsek.terra.structure.StructureContainedBlock;
|
||||
import com.dfsek.terra.structure.StructureInfo;
|
||||
import com.dfsek.terra.util.structure.RotationUtil;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
@@ -73,4 +77,28 @@ public class TreeConfig extends TerraConfig implements Tree {
|
||||
struc.paste(mut, rotation);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean plantBlockCheck(Location location, Random random) {
|
||||
location.subtract(0, 1, 0);
|
||||
Location mut = location.clone().subtract(0, yOffset, 0);
|
||||
if(!spawnable.contains(location.getBlock().getType())) return false;
|
||||
Structure struc = structure.get(random);
|
||||
Rotation rotation = Rotation.fromDegrees(random.nextInt(4) * 90);
|
||||
StructureInfo info = struc.getStructureInfo();
|
||||
for(StructureContainedBlock spawn : struc.getSpawns()) {
|
||||
Vector2 rot = RotationUtil.getRotatedCoords(new Vector2(spawn.getX() - info.getCenterX(), spawn.getZ() - info.getCenterZ()), rotation);
|
||||
int x = (int) rot.getX();
|
||||
int z = (int) rot.getZ();
|
||||
switch(spawn.getRequirement()) {
|
||||
case AIR:
|
||||
if(!mut.clone().add(x, spawn.getY() - 1, z).getBlock().isPassable()) return false;
|
||||
break;
|
||||
case LAND:
|
||||
if(!mut.clone().add(x, spawn.getY() - 1, z).getBlock().getType().isSolid()) return false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
struc.paste(mut, rotation);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import com.dfsek.terra.config.exception.ConfigException;
|
||||
import com.dfsek.terra.config.exception.NotFoundException;
|
||||
import com.dfsek.terra.config.genconfig.structure.StructureConfig;
|
||||
import com.dfsek.terra.generation.UserDefinedDecorator;
|
||||
import com.dfsek.terra.generation.UserDefinedGenerator;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.polydev.gaea.math.Range;
|
||||
@@ -45,36 +44,36 @@ public class BiomeConfig extends TerraConfig {
|
||||
|
||||
public BiomeConfig(File file, ConfigPack config) throws InvalidConfigurationException, IOException {
|
||||
super(file, config);
|
||||
load(file);
|
||||
this.config = config;
|
||||
if(!yaml.contains("id")) throw new ConfigException("Biome ID unspecified!", "null");
|
||||
this.biomeID = yaml.getString("id");
|
||||
if(!contains("id")) throw new ConfigException("Biome ID unspecified!", "null");
|
||||
this.biomeID = getString("id");
|
||||
|
||||
AbstractBiomeConfig abstractBiome = null;
|
||||
// Whether an abstract biome is to be extended. Default to false.
|
||||
boolean extending = false;
|
||||
// Check if biome extends an abstract biome, load abstract biome if so.
|
||||
if(yaml.contains("extends")) {
|
||||
if(contains("extends")) {
|
||||
try {
|
||||
abstractBiome = config.getAbstractBiomes().get(yaml.getString("extends"));
|
||||
if(abstractBiome == null)
|
||||
throw new NotFoundException("Abstract Biome", yaml.getString("extends"), getID());
|
||||
abstractBiome = config.getAbstractBiomes().get(getString("extends"));
|
||||
if(abstractBiome == null) throw new NotFoundException("Abstract Biome", getString("extends"), getID());
|
||||
extending = true;
|
||||
Debug.info("Extending biome " + yaml.getString("extends"));
|
||||
Debug.info("Extending biome " + getString("extends"));
|
||||
} catch(NullPointerException e) {
|
||||
throw new NotFoundException("Abstract Biome", yaml.getString("extends"), getID());
|
||||
throw new NotFoundException("Abstract Biome", getString("extends"), getID());
|
||||
}
|
||||
}
|
||||
|
||||
// Get various simple values using getOrDefault config methods.
|
||||
try {
|
||||
eq = yaml.getString("noise-equation", Objects.requireNonNull(abstractBiome).getEquation());
|
||||
eq = getString("noise-equation", Objects.requireNonNull(abstractBiome).getEquation());
|
||||
} catch(NullPointerException e) {
|
||||
eq = yaml.getString("noise-equation", null);
|
||||
eq = getString("noise-equation", null);
|
||||
}
|
||||
|
||||
BiomePaletteConfig palette;
|
||||
// Check if biome is extending abstract biome, only use abstract biome's palette if palette is NOT defined for current biome.
|
||||
if(extending && abstractBiome.getPaletteData() != null && !yaml.contains("palette")) {
|
||||
if(extending && abstractBiome.getPaletteData() != null && !contains("palette")) {
|
||||
palette = abstractBiome.getPaletteData();
|
||||
Debug.info("Using super palette");
|
||||
} else palette = new BiomePaletteConfig(this, "palette");
|
||||
@@ -84,31 +83,31 @@ public class BiomeConfig extends TerraConfig {
|
||||
throw new ConfigException("No Palette specified in biome or super biome.", getID());
|
||||
|
||||
// Check if carving should be handled by super biome.
|
||||
if(extending && abstractBiome.getCarving() != null && !yaml.contains("carving")) {
|
||||
if(extending && abstractBiome.getCarving() != null && !contains("carving")) {
|
||||
carver = abstractBiome.getCarving();
|
||||
Debug.info("Using super carvers");
|
||||
} else carver = new BiomeCarverConfig(this);
|
||||
|
||||
// Check if flora should be handled by super biome.
|
||||
if(extending && abstractBiome.getFlora() != null && !yaml.contains("flora")) {
|
||||
if(extending && abstractBiome.getFlora() != null && !contains("flora")) {
|
||||
flora = abstractBiome.getFlora();
|
||||
Debug.info("Using super flora (" + flora.getFlora().size() + " entries, " + flora.getFloraChance() + " % chance)");
|
||||
} else flora = new BiomeFloraConfig(this);
|
||||
|
||||
// Check if trees should be handled by super biome.
|
||||
if(extending && abstractBiome.getTrees() != null && !yaml.contains("trees")) {
|
||||
if(extending && abstractBiome.getTrees() != null && !contains("trees")) {
|
||||
tree = abstractBiome.getTrees();
|
||||
Debug.info("Using super trees");
|
||||
} else tree = new BiomeTreeConfig(this);
|
||||
|
||||
// Check if ores should be handled by super biome.
|
||||
if(extending && abstractBiome.getOres() != null && !yaml.contains("ores")) {
|
||||
if(extending && abstractBiome.getOres() != null && !contains("ores")) {
|
||||
ore = abstractBiome.getOres();
|
||||
Debug.info("Using super ores");
|
||||
} else ore = new BiomeOreConfig(this);
|
||||
|
||||
// Get slab stuff
|
||||
if(extending && abstractBiome.getSlabs() != null && !yaml.contains("slabs")) {
|
||||
if(extending && abstractBiome.getSlabs() != null && !contains("slabs")) {
|
||||
slab = abstractBiome.getSlabs();
|
||||
Debug.info("Using super slabs");
|
||||
} else slab = new BiomeSlabConfig(this);
|
||||
@@ -127,17 +126,17 @@ public class BiomeConfig extends TerraConfig {
|
||||
|
||||
// Get slant stuff
|
||||
TreeMap<Integer, Palette<BlockData>> slant = new TreeMap<>();
|
||||
if(yaml.contains("slant")) {
|
||||
String slantS = yaml.getString("slant.palette");
|
||||
if(contains("slant")) {
|
||||
String slantS = getString("slant.palette");
|
||||
slant = new BiomePaletteConfig(this, "slant.palette").getPaletteMap();
|
||||
Debug.info("Using slant palette: " + slantS);
|
||||
if(slant == null) throw new NotFoundException("Slant Palette", slantS, getID());
|
||||
}
|
||||
ySlantOffsetTop = yaml.getDouble("slant.y-offset.top", 0.25);
|
||||
ySlantOffsetBottom = yaml.getDouble("slant.y-offset.bottom", 0.25);
|
||||
ySlantOffsetTop = getDouble("slant.y-offset.top", 0.25);
|
||||
ySlantOffsetBottom = getDouble("slant.y-offset.bottom", 0.25);
|
||||
|
||||
//Make sure equation is non-null
|
||||
if(eq == null || eq.equals(""))
|
||||
if(eq == null || eq.isEmpty())
|
||||
throw new ConfigException("Could not find noise equation! Biomes must include a noise equation, or extend an abstract biome with one.", getID());
|
||||
|
||||
// Create decorator for this config.
|
||||
@@ -146,10 +145,10 @@ public class BiomeConfig extends TerraConfig {
|
||||
// Get Vanilla biome, throw exception if it is invalid/unspecified.
|
||||
org.bukkit.block.Biome vanillaBiome;
|
||||
try {
|
||||
if(!yaml.contains("vanilla")) throw new ConfigException("Vanilla Biome unspecified!", getID());
|
||||
vanillaBiome = org.bukkit.block.Biome.valueOf(yaml.getString("vanilla"));
|
||||
if(!contains("vanilla")) throw new ConfigException("Vanilla Biome unspecified!", getID());
|
||||
vanillaBiome = org.bukkit.block.Biome.valueOf(getString("vanilla"));
|
||||
} catch(IllegalArgumentException e) {
|
||||
throw new ConfigException("Invalid Vanilla biome: \"" + yaml.getString("vanilla") + "\"", getID());
|
||||
throw new ConfigException("Invalid Vanilla biome: \"" + getString("vanilla") + "\"", getID());
|
||||
}
|
||||
|
||||
// Structure stuff
|
||||
@@ -157,7 +156,7 @@ public class BiomeConfig extends TerraConfig {
|
||||
List<String> st = new ArrayList<>();
|
||||
if(abstractBiome != null && abstractBiome.getStructureConfigs() != null)
|
||||
st = abstractBiome.getStructureConfigs();
|
||||
if(yaml.contains("structures")) st = yaml.getStringList("structures");
|
||||
if(contains("structures")) st = getStringList("structures");
|
||||
for(String s : st) {
|
||||
try {
|
||||
structures.add(Objects.requireNonNull(config.getStructure(s)));
|
||||
@@ -166,14 +165,13 @@ public class BiomeConfig extends TerraConfig {
|
||||
}
|
||||
}
|
||||
|
||||
String elevation = yaml.getString("elevation.equation", null);
|
||||
boolean doElevationInterpolation = yaml.getBoolean("elevation.interpolation", true);
|
||||
String elevation = getString("elevation.equation", null);
|
||||
boolean doElevationInterpolation = getBoolean("elevation.interpolation", true);
|
||||
|
||||
try {
|
||||
// Get UserDefinedBiome instance representing this config.
|
||||
UserDefinedGenerator gen = new UserDefinedGenerator(eq, elevation, config.getDefinedVariables(), palette.getPaletteMap(), slant, yaml.getBoolean("prevent-smooth", false));
|
||||
gen.setElevationInterpolation(doElevationInterpolation);
|
||||
this.biome = new UserDefinedBiome(vanillaBiome, dec, gen, yaml.getBoolean("erodible", false), biomeID);
|
||||
GeneratorOptions gen = new GeneratorOptions(eq, elevation, config.getVariableScope(), palette.getPaletteMap(), slant, config.getNoiseBuilders(), getBoolean("prevent-smooth", false), doElevationInterpolation);
|
||||
this.biome = new UserDefinedBiome(vanillaBiome, dec, gen, getBoolean("erodible", false), this);
|
||||
} catch(ParseException e) {
|
||||
e.printStackTrace();
|
||||
throw new ConfigException("Unable to parse noise equation!", getID());
|
||||
|
||||
@@ -10,13 +10,12 @@ import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.polydev.gaea.math.ProbabilityCollection;
|
||||
import org.polydev.gaea.util.FastRandom;
|
||||
import org.polydev.gaea.world.palette.Palette;
|
||||
import org.polydev.gaea.world.palette.RandomPalette;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public class BiomeOceanConfig extends TerraConfigSection {
|
||||
private static final Palette<BlockData> oceanDefault = new RandomPalette<BlockData>(new Random(0)).add(Material.WATER.createBlockData(), 1);
|
||||
private static final Palette<BlockData> oceanDefault = new RandomPalette<BlockData>(new FastRandom(0)).add(Material.WATER.createBlockData(), 1);
|
||||
private final Palette<BlockData> ocean;
|
||||
private final int seaLevel;
|
||||
|
||||
@@ -27,7 +26,7 @@ public class BiomeOceanConfig extends TerraConfigSection {
|
||||
if(oceanN != null) {
|
||||
if(oceanN.startsWith("BLOCK:")) {
|
||||
try {
|
||||
ocean = new RandomPalette<BlockData>(new Random(0)).add(new ProbabilityCollection<BlockData>().add(Bukkit.createBlockData(oceanN.substring(6)), 1), 1);
|
||||
ocean = new RandomPalette<BlockData>(new FastRandom(0)).add(new ProbabilityCollection<BlockData>().add(Bukkit.createBlockData(oceanN.substring(6)), 1), 1);
|
||||
} catch(IllegalArgumentException ex) {
|
||||
throw new ConfigException("BlockData \"" + oceanN + "\" is invalid! (Ocean Palette)", parent.getID());
|
||||
}
|
||||
|
||||
@@ -8,12 +8,12 @@ import org.bukkit.Bukkit;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.polydev.gaea.math.ProbabilityCollection;
|
||||
import org.polydev.gaea.util.FastRandom;
|
||||
import org.polydev.gaea.world.palette.Palette;
|
||||
import org.polydev.gaea.world.palette.RandomPalette;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class BiomePaletteConfig extends TerraConfigSection {
|
||||
@@ -29,7 +29,7 @@ public class BiomePaletteConfig extends TerraConfigSection {
|
||||
try {
|
||||
if(((String) entry.getKey()).startsWith("BLOCK:")) {
|
||||
try {
|
||||
paletteMap.put((Integer) entry.getValue(), new RandomPalette<BlockData>(new Random(0)).add(new ProbabilityCollection<BlockData>().add(Bukkit.createBlockData(((String) entry.getKey()).substring(6)), 1), 1));
|
||||
paletteMap.put((Integer) entry.getValue(), new RandomPalette<BlockData>(new FastRandom(0)).add(new ProbabilityCollection<BlockData>().add(Bukkit.createBlockData(((String) entry.getKey()).substring(6)), 1), 1));
|
||||
} catch(IllegalArgumentException ex) {
|
||||
throw new ConfigException("BlockData " + entry.getKey() + " is invalid! (Palettes)", parent.getID());
|
||||
}
|
||||
|
||||
@@ -11,13 +11,14 @@ import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.configuration.InvalidConfigurationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.polydev.gaea.math.ProbabilityCollection;
|
||||
import org.polydev.gaea.util.FastRandom;
|
||||
import org.polydev.gaea.world.palette.Palette;
|
||||
import org.polydev.gaea.world.palette.RandomPalette;
|
||||
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
public class BiomeSlabConfig extends TerraConfigSection {
|
||||
private final Map<Material, Palette<BlockData>> slabs;
|
||||
@@ -34,7 +35,7 @@ public class BiomeSlabConfig extends TerraConfigSection {
|
||||
}
|
||||
|
||||
protected Map<Material, Palette<BlockData>> getSlabPalettes(List<Map<?, ?>> paletteConfigSection) throws InvalidConfigurationException {
|
||||
Map<Material, Palette<BlockData>> paletteMap = new HashMap<>();
|
||||
Map<Material, Palette<BlockData>> paletteMap = new EnumMap<>(Material.class);
|
||||
|
||||
for(Map<?, ?> e : paletteConfigSection) {
|
||||
for(Map.Entry<?, ?> entry : e.entrySet()) {
|
||||
@@ -42,7 +43,7 @@ public class BiomeSlabConfig extends TerraConfigSection {
|
||||
if(((String) entry.getValue()).startsWith("BLOCK:")) {
|
||||
try {
|
||||
Debug.info("Adding slab palette with single material " + entry.getKey());
|
||||
paletteMap.put(Bukkit.createBlockData((String) entry.getKey()).getMaterial(), new RandomPalette<BlockData>(new Random(0)).add(new ProbabilityCollection<BlockData>().add(Bukkit.createBlockData(((String) entry.getValue()).substring(6)), 1), 1));
|
||||
paletteMap.put(Bukkit.createBlockData((String) entry.getKey()).getMaterial(), new RandomPalette<BlockData>(new FastRandom(0)).add(new ProbabilityCollection<BlockData>().add(Bukkit.createBlockData(((String) entry.getValue()).substring(6)), 1), 1));
|
||||
} catch(IllegalArgumentException ex) {
|
||||
throw new ConfigException("Invalid BlockData in slab configuration: " + ex.getMessage(), getParent().getConfig().getID());
|
||||
}
|
||||
|
||||
@@ -12,12 +12,14 @@ import java.util.Map;
|
||||
|
||||
public class BiomeSnowConfig extends TerraConfigSection {
|
||||
private final int[] snowHeights;
|
||||
private final boolean physics;
|
||||
private boolean doSnow = false;
|
||||
|
||||
public BiomeSnowConfig(TerraConfig parent) throws InvalidConfigurationException {
|
||||
super(parent);
|
||||
snowHeights = new int[256];
|
||||
List<Map<?, ?>> maps = parent.getYaml().getMapList("snow");
|
||||
List<Map<?, ?>> maps = parent.getMapList("snow");
|
||||
this.physics = getParent().getBoolean("snow-physics", false);
|
||||
if(maps.size() == 0) return;
|
||||
try {
|
||||
for(Map<?, ?> e : maps) {
|
||||
@@ -41,4 +43,8 @@ public class BiomeSnowConfig extends TerraConfigSection {
|
||||
public boolean doSnow() {
|
||||
return doSnow;
|
||||
}
|
||||
|
||||
public boolean doPhysics() {
|
||||
return physics;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
package com.dfsek.terra.config.genconfig.biome;
|
||||
|
||||
import com.dfsek.terra.config.genconfig.noise.NoiseConfig;
|
||||
import com.dfsek.terra.generation.config.WorldGenerator;
|
||||
import com.dfsek.terra.math.BlankFunction;
|
||||
import com.dfsek.terra.util.DataUtil;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.polydev.gaea.world.palette.Palette;
|
||||
import parsii.eval.Parser;
|
||||
import parsii.eval.Scope;
|
||||
import parsii.tokenizer.ParseException;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class GeneratorOptions {
|
||||
|
||||
private final Map<Long, WorldGenerator> generators = new HashMap<>();
|
||||
|
||||
private final boolean preventSmooth;
|
||||
@SuppressWarnings({"unchecked", "rawtypes", "RedundantSuppression"})
|
||||
private final Palette<BlockData>[] palettes = new Palette[256];
|
||||
@SuppressWarnings({"unchecked", "rawtypes", "RedundantSuppression"})
|
||||
private final Palette<BlockData>[] slantPalettes = new Palette[256];
|
||||
|
||||
|
||||
private final String equation;
|
||||
private final String elevationEquation;
|
||||
private final Scope userVariables;
|
||||
private final Map<String, NoiseConfig> noiseBuilders;
|
||||
|
||||
private final boolean elevationInterpolation;
|
||||
|
||||
public GeneratorOptions(String equation, @Nullable String elevateEquation, Scope userVariables, Map<Integer, Palette<BlockData>> paletteMap, Map<Integer, Palette<BlockData>> slantPaletteMap, Map<String, NoiseConfig> noiseBuilders, boolean preventSmooth, boolean elevationInterpolation)
|
||||
throws ParseException {
|
||||
this.equation = equation;
|
||||
this.elevationEquation = elevateEquation;
|
||||
this.userVariables = userVariables;
|
||||
this.noiseBuilders = noiseBuilders;
|
||||
this.preventSmooth = preventSmooth;
|
||||
|
||||
Scope s = new Scope().withParent(userVariables);
|
||||
Parser p = new Parser();
|
||||
for(Map.Entry<String, NoiseConfig> e : noiseBuilders.entrySet()) {
|
||||
int dimensions = e.getValue().getDimensions();
|
||||
if(dimensions == 2 || dimensions == 3) p.registerFunction(e.getKey(), new BlankFunction(dimensions));
|
||||
}
|
||||
p.parse(equation, s); // Validate equation at config load time to prevent error during world load.
|
||||
if(elevateEquation != null) p.parse(elevateEquation, s);
|
||||
|
||||
|
||||
for(int y = 0; y < 256; y++) {
|
||||
Palette<BlockData> d = DataUtil.BLANK_PALETTE;
|
||||
for(Map.Entry<Integer, Palette<BlockData>> e : paletteMap.entrySet()) {
|
||||
if(e.getKey() >= y) {
|
||||
d = e.getValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
palettes[y] = d;
|
||||
Palette<BlockData> slantPalette = null;
|
||||
for(Map.Entry<Integer, Palette<BlockData>> e : slantPaletteMap.entrySet()) {
|
||||
if(e.getKey() >= y) {
|
||||
slantPalette = e.getValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
slantPalettes[y] = slantPalette;
|
||||
}
|
||||
this.elevationInterpolation = elevationInterpolation;
|
||||
}
|
||||
|
||||
public WorldGenerator getGenerator(long seed) {
|
||||
return generators.computeIfAbsent(seed, s -> new WorldGenerator(seed, equation, elevationEquation, userVariables, noiseBuilders, palettes, slantPalettes, preventSmooth)
|
||||
.setElevationInterpolation(elevationInterpolation));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.dfsek.terra.config.genconfig.noise;
|
||||
|
||||
import com.dfsek.terra.config.exception.ConfigException;
|
||||
import com.dfsek.terra.generation.config.NoiseBuilder;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.polydev.gaea.math.FastNoiseLite;
|
||||
|
||||
public class NoiseConfig {
|
||||
private final NoiseBuilder builder;
|
||||
private final int dimensions;
|
||||
|
||||
public NoiseConfig(ConfigurationSection section) throws ConfigException {
|
||||
NoiseBuilder builder = new NoiseBuilder();
|
||||
try {
|
||||
builder.setType(FastNoiseLite.NoiseType.valueOf(section.getString("type", "OpenSimplex2")))
|
||||
.setFrequency(section.getDouble("frequency", 0.02D))
|
||||
.setRotationType3D(FastNoiseLite.RotationType3D.valueOf(section.getString("rotation", "None")))
|
||||
.setSeedOffset(section.getInt("offset", 0));
|
||||
|
||||
dimensions = section.getInt("dimensions", 3);
|
||||
if(dimensions != 2 && dimensions != 3)
|
||||
throw new ConfigException("Invalid number of dimensions: " + dimensions, "Noise");
|
||||
|
||||
|
||||
if(section.contains("fractal")) {
|
||||
builder.setFractalType(FastNoiseLite.FractalType.valueOf(section.getString("fractal.type", "FBm")))
|
||||
.setOctaves(section.getInt("fractal.octaves", 1))
|
||||
.setFractalGain(section.getDouble("fractal.gain", 0.5D))
|
||||
.setFractalLacunarity(section.getDouble("fractal.lacunarity", 2.0D))
|
||||
.setPingPong(section.getDouble("fractal.ping-pong", 2.0D))
|
||||
.setWeightedStrength(section.getDouble("fractal.weighted-strength", 0.0D));
|
||||
}
|
||||
|
||||
if(section.contains("cellular")) {
|
||||
builder.setCellularDistanceFunction(FastNoiseLite.CellularDistanceFunction.valueOf(section.getString("cellular.distance", "EuclideanSq")))
|
||||
.setCellularReturnType(FastNoiseLite.CellularReturnType.valueOf(section.getString("cellular.return", "Distance")));
|
||||
}
|
||||
|
||||
if(section.contains("warp")) {
|
||||
builder.setDomainWarpType(FastNoiseLite.DomainWarpType.valueOf(section.getString("warp.type", "OpenSimplex2")))
|
||||
.setDomainWarpAmp(section.getDouble("warp.amplitude", 1.0D));
|
||||
}
|
||||
this.builder = builder;
|
||||
} catch(IllegalArgumentException | ClassCastException e) {
|
||||
throw new ConfigException(e.getMessage(), "Noise");
|
||||
}
|
||||
}
|
||||
|
||||
public NoiseBuilder getBuilder() {
|
||||
return builder;
|
||||
}
|
||||
|
||||
public int getDimensions() {
|
||||
return dimensions;
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,6 @@ public class EntityFeatureConfig implements FeatureConfig {
|
||||
throw new InvalidConfigurationException("Error in Entity Configuration!");
|
||||
}
|
||||
|
||||
int attempts = (Integer) items.get("attempts");
|
||||
int height = (Integer) items.get("in-height");
|
||||
|
||||
Range amount;
|
||||
@@ -52,7 +51,7 @@ public class EntityFeatureConfig implements FeatureConfig {
|
||||
Set<Material> on = ConfigUtil.toBlockData((List<String>) items.get("spawnable-on"), "SpawnableOn", "");
|
||||
Set<Material> in = ConfigUtil.toBlockData((List<String>) items.get("spawnable-in"), "SpawnableIn", "");
|
||||
|
||||
this.feature = new EntityFeature(type, amount, attempts, on, in, height);
|
||||
this.feature = new EntityFeature(type, amount, on, in, height);
|
||||
Debug.info("Loaded EntityFeature with type: " + type);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.dfsek.terra.TerraWorld;
|
||||
import com.dfsek.terra.biome.UserDefinedBiome;
|
||||
import com.dfsek.terra.generation.TerraChunkGenerator;
|
||||
import com.dfsek.terra.image.ImageLoader;
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.polydev.gaea.generation.GenerationPhase;
|
||||
@@ -33,14 +34,14 @@ public class DebugFrame extends JFrame implements ActionListener {
|
||||
super.paintComponents(g);
|
||||
for(Player p : Bukkit.getOnlinePlayers()) {
|
||||
if(!(p.getWorld().getGenerator() instanceof TerraChunkGenerator)) break;
|
||||
int xp = (int) (((double) Math.floorMod(p.getLocation().getBlockX() - (img.getWidth() / 2), x) / x) * getWidth());
|
||||
int zp = (int) (((double) Math.floorMod(p.getLocation().getBlockZ() - (img.getHeight() / 2), z) / z) * getHeight());
|
||||
int xp = (int) (((double) FastMath.floorMod(p.getLocation().getBlockX() - (img.getWidth() / 2), x) / x) * getWidth());
|
||||
int zp = (int) (((double) FastMath.floorMod(p.getLocation().getBlockZ() - (img.getHeight() / 2), z) / z) * getHeight());
|
||||
ImageLoader loader = TerraWorld.getWorld(p.getWorld()).getWorldConfig().imageLoader;
|
||||
if(loader != null && loader.getAlign().equals(ImageLoader.Align.NONE)) {
|
||||
xp = (int) (((double) Math.floorMod(p.getLocation().getBlockX(), x) / x) * getWidth());
|
||||
zp = (int) (((double) Math.floorMod(p.getLocation().getBlockZ(), z) / z) * getHeight());
|
||||
xp = (int) (((double) FastMath.floorMod(p.getLocation().getBlockX(), x) / x) * getWidth());
|
||||
zp = (int) (((double) FastMath.floorMod(p.getLocation().getBlockZ(), z) / z) * getHeight());
|
||||
}
|
||||
String str = TerraWorld.getWorld(p.getWorld()).getConfig().getBiome((UserDefinedBiome) TerraWorld.getWorld(p.getWorld()).getGrid().getBiome(p.getLocation(), GenerationPhase.POPULATE)).getID();
|
||||
String str = ((UserDefinedBiome) TerraWorld.getWorld(p.getWorld()).getGrid().getBiome(p.getLocation(), GenerationPhase.POPULATE)).getID();
|
||||
g.setColor(new Color(255, 255, 255, 128));
|
||||
g.fillRect(xp + 13, zp - 13, (int) (8 + 8.25 * str.length()), 33);
|
||||
g.setColor(Color.BLACK);
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
package com.dfsek.terra.generation;
|
||||
|
||||
import com.dfsek.terra.math.NoiseFunction2;
|
||||
import org.polydev.gaea.math.FastNoiseLite;
|
||||
import parsii.eval.Expression;
|
||||
import parsii.eval.Parser;
|
||||
import parsii.eval.Scope;
|
||||
import parsii.eval.Variable;
|
||||
import parsii.tokenizer.ParseException;
|
||||
|
||||
public class ElevationEquation {
|
||||
private static final Object noiseLock = new Object();
|
||||
private final Expression delegate;
|
||||
private final Scope s = new Scope();
|
||||
private final NoiseFunction2 n2 = new NoiseFunction2();
|
||||
|
||||
private final Variable xVar = s.getVariable("x");
|
||||
private final Variable zVar = s.getVariable("z");
|
||||
|
||||
public ElevationEquation(String equation) throws ParseException {
|
||||
Parser p = new Parser();
|
||||
p.registerFunction("noise2", n2);
|
||||
delegate = p.parse(equation, s);
|
||||
}
|
||||
|
||||
public double getNoise(double x, double z, FastNoiseLite noiseLite) {
|
||||
synchronized(noiseLock) {
|
||||
xVar.setValue(x);
|
||||
zVar.setValue(z);
|
||||
|
||||
n2.setNoise(noiseLite);
|
||||
return delegate.evaluate();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,34 +1,31 @@
|
||||
package com.dfsek.terra.generation;
|
||||
|
||||
import com.dfsek.terra.biome.grid.TerraBiomeGrid;
|
||||
import org.bukkit.World;
|
||||
import com.dfsek.terra.generation.config.WorldGenerator;
|
||||
import org.polydev.gaea.generation.GenerationPhase;
|
||||
import org.polydev.gaea.math.FastNoiseLite;
|
||||
import org.polydev.gaea.math.Interpolator;
|
||||
|
||||
public class ElevationInterpolator {
|
||||
private final UserDefinedGenerator[][] gens = new UserDefinedGenerator[10][10];
|
||||
private final WorldGenerator[][] gens = new WorldGenerator[10][10];
|
||||
private final double[][] values = new double[18][18];
|
||||
private final FastNoiseLite noise;
|
||||
private final int xOrigin;
|
||||
private final int zOrigin;
|
||||
private final TerraBiomeGrid grid;
|
||||
|
||||
public ElevationInterpolator(World w, int chunkX, int chunkZ, TerraBiomeGrid grid, FastNoiseLite noise) {
|
||||
public ElevationInterpolator(int chunkX, int chunkZ, TerraBiomeGrid grid) {
|
||||
this.xOrigin = chunkX << 4;
|
||||
this.zOrigin = chunkZ << 4;
|
||||
this.noise = noise;
|
||||
this.grid = grid;
|
||||
|
||||
for(int x = -2; x < 8; x++) {
|
||||
for(int z = -2; z < 8; z++) {
|
||||
gens[x + 2][z + 2] = (UserDefinedGenerator) grid.getBiome(xOrigin + x * 4, zOrigin + z * 4, GenerationPhase.BASE).getGenerator();
|
||||
gens[x + 2][z + 2] = (WorldGenerator) grid.getBiome(xOrigin + (x << 2), zOrigin + (z << 2), GenerationPhase.BASE).getGenerator();
|
||||
}
|
||||
}
|
||||
|
||||
for(byte x = -1; x <= 16; x++) {
|
||||
for(byte z = -1; z <= 16; z++) {
|
||||
UserDefinedGenerator generator = getGenerator(x, z);
|
||||
WorldGenerator generator = getGenerator(x, z);
|
||||
if(compareGens((x / 4), (z / 4)) && generator.interpolateElevation()) {
|
||||
Interpolator interpolator = new Interpolator(biomeAvg(x / 4, z / 4),
|
||||
biomeAvg((x / 4) + 1, z / 4),
|
||||
@@ -41,16 +38,16 @@ public class ElevationInterpolator {
|
||||
}
|
||||
}
|
||||
|
||||
private UserDefinedGenerator getGenerator(int x, int z) {
|
||||
return (UserDefinedGenerator) grid.getBiome(xOrigin + x, zOrigin + z, GenerationPhase.BASE).getGenerator();
|
||||
private WorldGenerator getGenerator(int x, int z) {
|
||||
return (WorldGenerator) grid.getBiome(xOrigin + x, zOrigin + z, GenerationPhase.BASE).getGenerator();
|
||||
}
|
||||
|
||||
private UserDefinedGenerator getStoredGen(int x, int z) {
|
||||
private WorldGenerator getStoredGen(int x, int z) {
|
||||
return gens[x + 2][z + 2];
|
||||
}
|
||||
|
||||
private boolean compareGens(int x, int z) {
|
||||
UserDefinedGenerator comp = getStoredGen(x, z);
|
||||
WorldGenerator comp = getStoredGen(x, z);
|
||||
|
||||
for(int xi = x - 2; xi <= x + 2; xi++) {
|
||||
for(int zi = z - 2; zi <= z + 2; zi++) {
|
||||
@@ -61,20 +58,19 @@ public class ElevationInterpolator {
|
||||
}
|
||||
|
||||
private double biomeAvg(int x, int z) {
|
||||
return (elevate(getStoredGen(x + 1, z), x * 4 + 4 + xOrigin, z * 4 + zOrigin)
|
||||
+ elevate(getStoredGen(x - 1, z), x * 4 - 4 + xOrigin, z * 4 + zOrigin)
|
||||
+ elevate(getStoredGen(x, z + 1), x * 4 + xOrigin, z * 4 + 4 + zOrigin)
|
||||
+ elevate(getStoredGen(x, z - 1), x * 4 + xOrigin, z * 4 - 4 + zOrigin)
|
||||
+ elevate(getStoredGen(x, z), x * 4 + xOrigin, z * 4 + zOrigin)
|
||||
+ elevate(getStoredGen(x - 1, z - 1), x * 4 + xOrigin, z * 4 + zOrigin)
|
||||
+ elevate(getStoredGen(x - 1, z + 1), x * 4 + xOrigin, z * 4 + zOrigin)
|
||||
+ elevate(getStoredGen(x + 1, z - 1), x * 4 + xOrigin, z * 4 + zOrigin)
|
||||
+ elevate(getStoredGen(x + 1, z + 1), x * 4 + xOrigin, z * 4 + zOrigin)) / 9D;
|
||||
return (elevate(getStoredGen(x + 1, z), (x << 2) + 4 + xOrigin, (z << 2) + zOrigin)
|
||||
+ elevate(getStoredGen(x - 1, z), (x << 2) - 4 + xOrigin, (z << 2) + zOrigin)
|
||||
+ elevate(getStoredGen(x, z + 1), (x << 2) + xOrigin, (z << 2) + 4 + zOrigin)
|
||||
+ elevate(getStoredGen(x, z - 1), (x << 2) + xOrigin, (z << 2) - 4 + zOrigin)
|
||||
+ elevate(getStoredGen(x, z), (x << 2) + xOrigin, (z << 2) + zOrigin)
|
||||
+ elevate(getStoredGen(x - 1, z - 1), (x << 2) + xOrigin, (z << 2) + zOrigin)
|
||||
+ elevate(getStoredGen(x - 1, z + 1), (x << 2) + xOrigin, (z << 2) + zOrigin)
|
||||
+ elevate(getStoredGen(x + 1, z - 1), (x << 2) + xOrigin, (z << 2) + zOrigin)
|
||||
+ elevate(getStoredGen(x + 1, z + 1), (x << 2) + xOrigin, (z << 2) + zOrigin)) / 9D;
|
||||
}
|
||||
|
||||
private double elevate(UserDefinedGenerator g, int x, int z) {
|
||||
if(g.getElevationEquation() != null) return g.getElevationEquation().getNoise(x, z, noise);
|
||||
return 0;
|
||||
private double elevate(WorldGenerator g, int x, int z) {
|
||||
return g.getElevation(x, z);
|
||||
}
|
||||
|
||||
public double getElevation(int x, int z) {
|
||||
|
||||
@@ -9,11 +9,13 @@ import com.dfsek.terra.config.base.ConfigPack;
|
||||
import com.dfsek.terra.config.genconfig.biome.BiomeConfig;
|
||||
import com.dfsek.terra.config.genconfig.biome.BiomeSlabConfig;
|
||||
import com.dfsek.terra.config.lang.LangUtil;
|
||||
import com.dfsek.terra.generation.config.WorldGenerator;
|
||||
import com.dfsek.terra.population.CavePopulator;
|
||||
import com.dfsek.terra.population.FloraPopulator;
|
||||
import com.dfsek.terra.population.OrePopulator;
|
||||
import com.dfsek.terra.population.SnowPopulator;
|
||||
import com.dfsek.terra.population.StructurePopulator;
|
||||
import com.dfsek.terra.population.TreePopulator;
|
||||
import com.dfsek.terra.util.DataUtil;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Material;
|
||||
@@ -55,8 +57,9 @@ public class TerraChunkGenerator extends GaeaChunkGenerator {
|
||||
public TerraChunkGenerator(ConfigPack c) {
|
||||
super(ChunkInterpolator.InterpolationType.TRILINEAR);
|
||||
this.configPack = c;
|
||||
popMan.attach(new FloraPopulator());
|
||||
popMan.attach(new OrePopulator());
|
||||
popMan.attach(new TreePopulator());
|
||||
popMan.attach(new FloraPopulator());
|
||||
popMan.attach(new SnowPopulator());
|
||||
}
|
||||
|
||||
@@ -76,26 +79,22 @@ public class TerraChunkGenerator extends GaeaChunkGenerator {
|
||||
popMap.get(c.getWorld()).checkNeighbors(c.getX(), c.getZ(), c.getWorld());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attachProfiler(WorldProfiler p) {
|
||||
super.attachProfiler(p);
|
||||
popMan.attachProfiler(p);
|
||||
}
|
||||
|
||||
private static Palette<BlockData> getPalette(int x, int y, int z, BiomeConfig c, ChunkInterpolator interpolator, ElevationInterpolator elevationInterpolator) {
|
||||
Palette<BlockData> slant = ((UserDefinedGenerator) c.getBiome().getGenerator()).getSlantPalette(y);
|
||||
Palette<BlockData> slant = ((WorldGenerator) c.getBiome().getGenerator()).getSlantPalette(y);
|
||||
if(slant != null) {
|
||||
boolean north = interpolator.getNoise(x, y - elevationInterpolator.getElevation(x, z + 1), z + 1) > 0;
|
||||
boolean south = interpolator.getNoise(x, y - elevationInterpolator.getElevation(x, z - 1), z - 1) > 0;
|
||||
boolean east = interpolator.getNoise(x + 1, y - elevationInterpolator.getElevation(x + 1, z), z) > 0;
|
||||
boolean west = interpolator.getNoise(x - 1, y - elevationInterpolator.getElevation(x - 1, z), z) > 0;
|
||||
|
||||
double ySlantOffsetTop = c.getYSlantOffsetTop();
|
||||
double ySlantOffsetBottom = c.getYSlantOffsetBottom();
|
||||
boolean top = interpolator.getNoise(x, y + ySlantOffsetTop - elevationInterpolator.getElevation(x, z), z) > 0;
|
||||
boolean bottom = interpolator.getNoise(x, y - ySlantOffsetBottom - elevationInterpolator.getElevation(x, z), z) > 0;
|
||||
|
||||
if((top && bottom) && (north || south || east || west) && (!(north && south && east && west))) return slant;
|
||||
if(top && bottom) {
|
||||
boolean north = interpolator.getNoise(x, y - elevationInterpolator.getElevation(x, z + 1), z + 1) > 0;
|
||||
boolean south = interpolator.getNoise(x, y - elevationInterpolator.getElevation(x, z - 1), z - 1) > 0;
|
||||
boolean east = interpolator.getNoise(x + 1, y - elevationInterpolator.getElevation(x + 1, z), z) > 0;
|
||||
boolean west = interpolator.getNoise(x - 1, y - elevationInterpolator.getElevation(x - 1, z), z) > 0;
|
||||
|
||||
if((north || south || east || west) && (!(north && south && east && west))) return slant;
|
||||
}
|
||||
}
|
||||
return c.getBiome().getGenerator().getPalette(y);
|
||||
}
|
||||
@@ -109,10 +108,10 @@ public class TerraChunkGenerator extends GaeaChunkGenerator {
|
||||
if(stairPalette != null) {
|
||||
BlockData stair = stairPalette.get(0, block.getBlockX(), block.getBlockZ());
|
||||
Stairs stairNew = (Stairs) stair.clone();
|
||||
double elevationN = elevationInterpolator.getElevation(block.getBlockX(), block.getBlockZ() - 1); // Northern elevation
|
||||
double elevationS = elevationInterpolator.getElevation(block.getBlockX(), block.getBlockZ() + 1); // Southern elevation
|
||||
double elevationE = elevationInterpolator.getElevation(block.getBlockX() + 1, block.getBlockZ()); // Eastern elevation
|
||||
double elevationW = elevationInterpolator.getElevation(block.getBlockX() - 1, block.getBlockZ()); // Western elevation
|
||||
int elevationN = (int) elevationInterpolator.getElevation(block.getBlockX(), block.getBlockZ() - 1); // Northern elevation
|
||||
int elevationS = (int) elevationInterpolator.getElevation(block.getBlockX(), block.getBlockZ() + 1); // Southern elevation
|
||||
int elevationE = (int) elevationInterpolator.getElevation(block.getBlockX() + 1, block.getBlockZ()); // Eastern elevation
|
||||
int elevationW = (int) elevationInterpolator.getElevation(block.getBlockX() - 1, block.getBlockZ()); // Western elevation
|
||||
if(interpolator.getNoise(block.getBlockX() - 0.5, block.getBlockY() - elevationW, block.getBlockZ()) > thresh) {
|
||||
stairNew.setFacing(BlockFace.WEST);
|
||||
} else if(interpolator.getNoise(block.getBlockX(), block.getBlockY() - elevationN, block.getBlockZ() - 0.5) > thresh) {
|
||||
@@ -137,6 +136,12 @@ public class TerraChunkGenerator extends GaeaChunkGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attachProfiler(WorldProfiler p) {
|
||||
super.attachProfiler(p);
|
||||
popMan.attachProfiler(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("try")
|
||||
public ChunkData generateBase(@NotNull World world, @NotNull Random random, int chunkX, int chunkZ, ChunkInterpolator interpolator) {
|
||||
@@ -144,14 +149,13 @@ public class TerraChunkGenerator extends GaeaChunkGenerator {
|
||||
ChunkData chunk = createChunkData(world);
|
||||
TerraWorld tw = TerraWorld.getWorld(world);
|
||||
if(!tw.isSafe()) return chunk;
|
||||
ConfigPack config = tw.getConfig();
|
||||
int xOrig = (chunkX << 4);
|
||||
int zOrig = (chunkZ << 4);
|
||||
org.polydev.gaea.biome.BiomeGrid grid = getBiomeGrid(world);
|
||||
|
||||
ElevationInterpolator elevationInterpolator;
|
||||
try(ProfileFuture ignore = TerraProfiler.fromWorld(world).measure("ElevationTime")) {
|
||||
elevationInterpolator = new ElevationInterpolator(world, chunkX, chunkZ, tw.getGrid(), getNoiseGenerator());
|
||||
elevationInterpolator = new ElevationInterpolator(chunkX, chunkZ, tw.getGrid());
|
||||
}
|
||||
|
||||
for(byte x = 0; x < 16; x++) {
|
||||
@@ -162,7 +166,7 @@ public class TerraChunkGenerator extends GaeaChunkGenerator {
|
||||
int cz = zOrig + z;
|
||||
|
||||
Biome b = grid.getBiome(xOrig + x, zOrig + z, GenerationPhase.PALETTE_APPLY);
|
||||
BiomeConfig c = config.getBiome((UserDefinedBiome) b);
|
||||
BiomeConfig c = ((UserDefinedBiome) b).getConfig();
|
||||
|
||||
double elevate = elevationInterpolator.getElevation(x, z);
|
||||
|
||||
@@ -203,12 +207,12 @@ public class TerraChunkGenerator extends GaeaChunkGenerator {
|
||||
|
||||
@Override
|
||||
public int getNoiseOctaves(World world) {
|
||||
return configPack.octaves;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getNoiseFrequency(World world) {
|
||||
return configPack.frequency;
|
||||
return 0.02;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,152 +0,0 @@
|
||||
package com.dfsek.terra.generation;
|
||||
|
||||
import com.dfsek.terra.Debug;
|
||||
import com.dfsek.terra.math.NoiseFunction2;
|
||||
import com.dfsek.terra.math.NoiseFunction3;
|
||||
import com.dfsek.terra.util.DataUtil;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.polydev.gaea.biome.Generator;
|
||||
import org.polydev.gaea.math.FastNoiseLite;
|
||||
import org.polydev.gaea.math.Interpolator;
|
||||
import org.polydev.gaea.world.palette.Palette;
|
||||
import parsii.eval.Expression;
|
||||
import parsii.eval.Parser;
|
||||
import parsii.eval.Scope;
|
||||
import parsii.eval.Variable;
|
||||
import parsii.tokenizer.ParseException;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public class UserDefinedGenerator extends Generator {
|
||||
private static final Object noiseLock = new Object();
|
||||
private final Expression noiseExp;
|
||||
private final Scope s = new Scope();
|
||||
private final Variable xVar = s.getVariable("x");
|
||||
private final Variable yVar = s.getVariable("y");
|
||||
private final Variable zVar = s.getVariable("z");
|
||||
@SuppressWarnings({"unchecked", "rawtypes", "RedundantSuppression"})
|
||||
private final Palette<BlockData>[] palettes = new Palette[256];
|
||||
@SuppressWarnings({"unchecked", "rawtypes", "RedundantSuppression"})
|
||||
private final Palette<BlockData>[] slantPalettes = new Palette[256];
|
||||
private final NoiseFunction2 n2 = new NoiseFunction2();
|
||||
private final NoiseFunction3 n3 = new NoiseFunction3();
|
||||
private final ElevationEquation elevationEquation;
|
||||
private final boolean preventSmooth;
|
||||
private boolean elevationInterpolation;
|
||||
|
||||
|
||||
public UserDefinedGenerator(String equation, @Nullable String elevateEquation, Map<String, Double> userVariables, Map<Integer, Palette<BlockData>> paletteMap, Map<Integer, Palette<BlockData>> slantPaletteMap, boolean preventSmooth)
|
||||
throws ParseException {
|
||||
for(Map.Entry<String, Double> entry : userVariables.entrySet()) {
|
||||
s.getVariable(entry.getKey()).setValue(entry.getValue()); // Define all user variables.
|
||||
}
|
||||
Parser p = new Parser();
|
||||
p.registerFunction("noise2", n2);
|
||||
p.registerFunction("noise3", n3);
|
||||
for(int y = 0; y < 256; y++) {
|
||||
Palette<BlockData> d = DataUtil.BLANK_PALETTE;
|
||||
for(Map.Entry<Integer, Palette<BlockData>> e : paletteMap.entrySet()) {
|
||||
if(e.getKey() >= y) {
|
||||
d = e.getValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
palettes[y] = d;
|
||||
Palette<BlockData> slantPalette = null;
|
||||
for(Map.Entry<Integer, Palette<BlockData>> e : slantPaletteMap.entrySet()) {
|
||||
if(e.getKey() >= y) {
|
||||
slantPalette = e.getValue();
|
||||
break;
|
||||
}
|
||||
}
|
||||
slantPalettes[y] = slantPalette;
|
||||
}
|
||||
if(elevateEquation != null) {
|
||||
Debug.info("Using elevation equation");
|
||||
this.elevationEquation = new ElevationEquation(elevateEquation);
|
||||
} else this.elevationEquation = null;
|
||||
this.noiseExp = p.parse(equation, s);
|
||||
this.preventSmooth = preventSmooth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the 2D noise at a pair of coordinates using the provided FastNoiseLite instance.
|
||||
*
|
||||
* @param gen - The FastNoiseLite instance to use.
|
||||
* @param x - The x coordinate.
|
||||
* @param z - The z coordinate.
|
||||
* @return double - Noise value at the specified coordinates.
|
||||
*/
|
||||
@Override
|
||||
public double getNoise(FastNoiseLite gen, World w, int x, int z) {
|
||||
synchronized(noiseLock) {
|
||||
xVar.setValue(x);
|
||||
yVar.setValue(0);
|
||||
zVar.setValue(z);
|
||||
n2.setNoise(gen);
|
||||
n3.setNoise(gen);
|
||||
return noiseExp.evaluate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the 3D noise at a pair of coordinates using the provided FastNoiseLite instance.
|
||||
*
|
||||
* @param gen - The FastNoiseLite instance to use.
|
||||
* @param x - The x coordinate.
|
||||
* @param y - The y coordinate.
|
||||
* @param z - The z coordinate.
|
||||
* @return double - Noise value at the specified coordinates.
|
||||
*/
|
||||
@Override
|
||||
public double getNoise(FastNoiseLite gen, World w, int x, int y, int z) {
|
||||
synchronized(noiseLock) {
|
||||
xVar.setValue(x);
|
||||
yVar.setValue(y);
|
||||
zVar.setValue(z);
|
||||
n2.setNoise(gen);
|
||||
n3.setNoise(gen);
|
||||
return noiseExp.evaluate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the BlocPalette to generate the biome with.
|
||||
*
|
||||
* @return BlocPalette - The biome's palette.
|
||||
*/
|
||||
@Override
|
||||
public Palette<BlockData> getPalette(int y) {
|
||||
return palettes[y];
|
||||
}
|
||||
|
||||
public Palette<BlockData> getSlantPalette(int y) {
|
||||
return slantPalettes[y];
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean useMinimalInterpolation() {
|
||||
return preventSmooth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Interpolator.Type getInterpolationType() {
|
||||
return Interpolator.Type.LINEAR;
|
||||
}
|
||||
|
||||
public ElevationEquation getElevationEquation() {
|
||||
return elevationEquation;
|
||||
}
|
||||
|
||||
public boolean interpolateElevation() {
|
||||
return elevationInterpolation;
|
||||
}
|
||||
|
||||
public void setElevationInterpolation(boolean elevationInterpolation) {
|
||||
this.elevationInterpolation = elevationInterpolation;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,186 @@
|
||||
package com.dfsek.terra.generation.config;
|
||||
|
||||
import org.polydev.gaea.math.FastNoiseLite;
|
||||
|
||||
public class NoiseBuilder {
|
||||
private FastNoiseLite.NoiseType type = FastNoiseLite.NoiseType.OpenSimplex2;
|
||||
private int octaves = 1;
|
||||
private FastNoiseLite.FractalType fractalType = FastNoiseLite.FractalType.None;
|
||||
private double frequency = 0.02D;
|
||||
private double fractalGain = 0.5D;
|
||||
private double fractalLacunarity = 2.0D;
|
||||
private double pingPong = 2.0D;
|
||||
private double weightedStrength = 0.0D;
|
||||
private int seedOffset = 0;
|
||||
|
||||
private FastNoiseLite.CellularDistanceFunction cellularDistanceFunction = FastNoiseLite.CellularDistanceFunction.EuclideanSq;
|
||||
private FastNoiseLite.CellularReturnType cellularReturnType = FastNoiseLite.CellularReturnType.Distance;
|
||||
private double cellularJitter = 1.0D;
|
||||
|
||||
private FastNoiseLite.DomainWarpType domainWarpType = FastNoiseLite.DomainWarpType.OpenSimplex2;
|
||||
private double domainWarpAmp = 1.0D;
|
||||
|
||||
private FastNoiseLite.RotationType3D rotationType3D = FastNoiseLite.RotationType3D.None;
|
||||
|
||||
public FastNoiseLite build(int seed) {
|
||||
FastNoiseLite noise = new FastNoiseLite(seed + seedOffset);
|
||||
if(!fractalType.equals(FastNoiseLite.FractalType.None)) {
|
||||
noise.setFractalType(fractalType);
|
||||
noise.setFractalOctaves(octaves);
|
||||
noise.setFractalGain(fractalGain);
|
||||
noise.setFractalLacunarity(fractalLacunarity);
|
||||
if(fractalType.equals(FastNoiseLite.FractalType.PingPong)) noise.setFractalPingPongStrength(pingPong);
|
||||
noise.setFractalWeightedStrength(weightedStrength);
|
||||
}
|
||||
if(type.equals(FastNoiseLite.NoiseType.Cellular)) {
|
||||
noise.setCellularDistanceFunction(cellularDistanceFunction);
|
||||
noise.setCellularReturnType(cellularReturnType);
|
||||
noise.setCellularJitter(cellularJitter);
|
||||
}
|
||||
|
||||
noise.setNoiseType(type);
|
||||
|
||||
noise.setDomainWarpType(domainWarpType);
|
||||
noise.setDomainWarpAmp(domainWarpAmp);
|
||||
|
||||
noise.setRotationType3D(rotationType3D);
|
||||
|
||||
noise.setFrequency(frequency);
|
||||
return noise;
|
||||
}
|
||||
|
||||
public FastNoiseLite.NoiseType getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public NoiseBuilder setType(FastNoiseLite.NoiseType type) {
|
||||
this.type = type;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getSeedOffset() {
|
||||
return seedOffset;
|
||||
}
|
||||
|
||||
public void setSeedOffset(int seedOffset) {
|
||||
this.seedOffset = seedOffset;
|
||||
}
|
||||
|
||||
public FastNoiseLite.CellularDistanceFunction getCellularDistanceFunction() {
|
||||
return cellularDistanceFunction;
|
||||
}
|
||||
|
||||
public NoiseBuilder setCellularDistanceFunction(FastNoiseLite.CellularDistanceFunction cellularDistanceFunction) {
|
||||
this.cellularDistanceFunction = cellularDistanceFunction;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FastNoiseLite.CellularReturnType getCellularReturnType() {
|
||||
return cellularReturnType;
|
||||
}
|
||||
|
||||
public NoiseBuilder setCellularReturnType(FastNoiseLite.CellularReturnType cellularReturnType) {
|
||||
this.cellularReturnType = cellularReturnType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FastNoiseLite.DomainWarpType getDomainWarpType() {
|
||||
return domainWarpType;
|
||||
}
|
||||
|
||||
public NoiseBuilder setDomainWarpType(FastNoiseLite.DomainWarpType domainWarpType) {
|
||||
this.domainWarpType = domainWarpType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public double getCellularJitter() {
|
||||
return cellularJitter;
|
||||
}
|
||||
|
||||
public NoiseBuilder setCellularJitter(double cellularJitter) {
|
||||
this.cellularJitter = cellularJitter;
|
||||
return this;
|
||||
}
|
||||
|
||||
public double getDomainWarpAmp() {
|
||||
return domainWarpAmp;
|
||||
}
|
||||
|
||||
public NoiseBuilder setDomainWarpAmp(double domainWarpAmp) {
|
||||
this.domainWarpAmp = domainWarpAmp;
|
||||
return this;
|
||||
}
|
||||
|
||||
public double getFractalGain() {
|
||||
return fractalGain;
|
||||
}
|
||||
|
||||
public NoiseBuilder setFractalGain(double fractalGain) {
|
||||
this.fractalGain = fractalGain;
|
||||
return this;
|
||||
}
|
||||
|
||||
public double getFractalLacunarity() {
|
||||
return fractalLacunarity;
|
||||
}
|
||||
|
||||
public NoiseBuilder setFractalLacunarity(double fractalLacunarity) {
|
||||
this.fractalLacunarity = fractalLacunarity;
|
||||
return this;
|
||||
}
|
||||
|
||||
public double getFrequency() {
|
||||
return frequency;
|
||||
}
|
||||
|
||||
public NoiseBuilder setFrequency(double frequency) {
|
||||
this.frequency = frequency;
|
||||
return this;
|
||||
}
|
||||
|
||||
public double getPingPong() {
|
||||
return pingPong;
|
||||
}
|
||||
|
||||
public NoiseBuilder setPingPong(double pingPong) {
|
||||
this.pingPong = pingPong;
|
||||
return this;
|
||||
}
|
||||
|
||||
public double getWeightedStrength() {
|
||||
return weightedStrength;
|
||||
}
|
||||
|
||||
public NoiseBuilder setWeightedStrength(double weightedStrength) {
|
||||
this.weightedStrength = weightedStrength;
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getOctaves() {
|
||||
return octaves;
|
||||
}
|
||||
|
||||
public NoiseBuilder setOctaves(int octaves) {
|
||||
this.octaves = octaves;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FastNoiseLite.FractalType getFractalType() {
|
||||
return fractalType;
|
||||
}
|
||||
|
||||
public NoiseBuilder setFractalType(FastNoiseLite.FractalType fractalType) {
|
||||
this.fractalType = fractalType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public FastNoiseLite.RotationType3D getRotationType3D() {
|
||||
return rotationType3D;
|
||||
}
|
||||
|
||||
public NoiseBuilder setRotationType3D(FastNoiseLite.RotationType3D rotationType3D) {
|
||||
this.rotationType3D = rotationType3D;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
package com.dfsek.terra.generation.config;
|
||||
|
||||
import com.dfsek.terra.config.genconfig.noise.NoiseConfig;
|
||||
import com.dfsek.terra.math.NoiseFunction2;
|
||||
import com.dfsek.terra.math.NoiseFunction3;
|
||||
import com.dfsek.terra.math.RandomFunction;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.polydev.gaea.biome.Generator;
|
||||
import org.polydev.gaea.math.FastNoiseLite;
|
||||
import org.polydev.gaea.math.Interpolator;
|
||||
import org.polydev.gaea.world.palette.Palette;
|
||||
import parsii.eval.Expression;
|
||||
import parsii.eval.Parser;
|
||||
import parsii.eval.Scope;
|
||||
import parsii.eval.Variable;
|
||||
import parsii.tokenizer.ParseException;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class WorldGenerator extends Generator {
|
||||
@SuppressWarnings({"unchecked", "rawtypes", "RedundantSuppression"})
|
||||
private final Palette<BlockData>[] palettes;
|
||||
@SuppressWarnings({"unchecked", "rawtypes", "RedundantSuppression"})
|
||||
private final Palette<BlockData>[] slantPalettes;
|
||||
|
||||
private final boolean preventSmooth;
|
||||
private final Expression noiseExp;
|
||||
private final Expression elevationExp;
|
||||
private final Variable xVar;
|
||||
private final Variable yVar;
|
||||
private final Variable zVar;
|
||||
private final Variable elevationXVar;
|
||||
private final Variable elevationZVar;
|
||||
private boolean elevationInterpolation = true;
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public WorldGenerator(long seed, String equation, String elevateEquation, Scope vScope, Map<String, NoiseConfig> noiseBuilders, Palette[] palettes, Palette[] slantPalettes, boolean preventSmooth) {
|
||||
Parser p = new Parser();
|
||||
p.registerFunction("rand", new RandomFunction());
|
||||
Parser ep = new Parser();
|
||||
ep.registerFunction("rand", new RandomFunction());
|
||||
|
||||
Scope s = new Scope().withParent(vScope);
|
||||
xVar = s.create("x");
|
||||
yVar = s.create("y");
|
||||
zVar = s.create("z");
|
||||
s.create("seed").setValue(seed);
|
||||
|
||||
this.preventSmooth = preventSmooth;
|
||||
|
||||
this.palettes = palettes;
|
||||
this.slantPalettes = slantPalettes;
|
||||
|
||||
for(Map.Entry<String, NoiseConfig> e : noiseBuilders.entrySet()) {
|
||||
switch(e.getValue().getDimensions()) {
|
||||
case 2:
|
||||
p.registerFunction(e.getKey(), new NoiseFunction2(seed, e.getValue().getBuilder()));
|
||||
ep.registerFunction(e.getKey(), new NoiseFunction2(seed, e.getValue().getBuilder()));
|
||||
break;
|
||||
case 3:
|
||||
p.registerFunction(e.getKey(), new NoiseFunction3(seed, e.getValue().getBuilder()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
try {
|
||||
this.noiseExp = p.parse(equation, s).simplify();
|
||||
if(elevateEquation != null) {
|
||||
Scope es = new Scope().withParent(vScope);
|
||||
es.create("seed").setValue(seed);
|
||||
this.elevationXVar = es.create("x");
|
||||
this.elevationZVar = es.create("z");
|
||||
this.elevationExp = ep.parse(elevateEquation, es).simplify();
|
||||
} else {
|
||||
this.elevationExp = null;
|
||||
this.elevationXVar = null;
|
||||
this.elevationZVar = null;
|
||||
}
|
||||
} catch(ParseException e) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized double getElevation(int x, int z) {
|
||||
if(elevationExp == null) return 0;
|
||||
elevationXVar.setValue(x);
|
||||
elevationZVar.setValue(z);
|
||||
return elevationExp.evaluate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized double getNoise(FastNoiseLite fastNoiseLite, World world, int x, int z) {
|
||||
xVar.setValue(x);
|
||||
yVar.setValue(0);
|
||||
zVar.setValue(z);
|
||||
return noiseExp.evaluate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized double getNoise(FastNoiseLite fastNoiseLite, World world, int x, int y, int z) {
|
||||
xVar.setValue(x);
|
||||
yVar.setValue(y);
|
||||
zVar.setValue(z);
|
||||
return noiseExp.evaluate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the BlockPalette to generate the biome with.
|
||||
*
|
||||
* @return BlockPalette - The biome's palette.
|
||||
*/
|
||||
@Override
|
||||
public Palette<BlockData> getPalette(int y) {
|
||||
return palettes[y];
|
||||
}
|
||||
|
||||
public Palette<BlockData> getSlantPalette(int y) {
|
||||
return slantPalettes[y];
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean useMinimalInterpolation() {
|
||||
return preventSmooth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Interpolator.Type getInterpolationType() {
|
||||
return Interpolator.Type.LINEAR;
|
||||
}
|
||||
|
||||
public boolean interpolateElevation() {
|
||||
return elevationInterpolation;
|
||||
}
|
||||
|
||||
public WorldGenerator setElevationInterpolation(boolean elevationInterpolation) {
|
||||
this.elevationInterpolation = elevationInterpolation;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import com.dfsek.terra.biome.BiomeZone;
|
||||
import com.dfsek.terra.biome.grid.TerraBiomeGrid;
|
||||
import com.dfsek.terra.config.base.ConfigUtil;
|
||||
import com.dfsek.terra.debug.gui.DebugGUI;
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.World;
|
||||
import org.polydev.gaea.biome.NormalizationUtil;
|
||||
|
||||
@@ -108,12 +109,12 @@ public class ImageLoader {
|
||||
NONE {
|
||||
@Override
|
||||
public int getRGB(BufferedImage image, int x, int y) {
|
||||
return image.getRGB(Math.floorMod(x, image.getWidth()), Math.floorMod(y, image.getHeight()));
|
||||
return image.getRGB(FastMath.floorMod(x, image.getWidth()), FastMath.floorMod(y, image.getHeight()));
|
||||
}
|
||||
};
|
||||
|
||||
private static int getRGBNoAlign(BufferedImage image, int x, int y) {
|
||||
return image.getRGB(Math.floorMod(x, image.getWidth()), Math.floorMod(y, image.getHeight()));
|
||||
return image.getRGB(FastMath.floorMod(x, image.getWidth()), FastMath.floorMod(y, image.getHeight()));
|
||||
}
|
||||
|
||||
public abstract int getRGB(BufferedImage image, int x, int y);
|
||||
|
||||
29
src/main/java/com/dfsek/terra/math/BlankFunction.java
Normal file
29
src/main/java/com/dfsek/terra/math/BlankFunction.java
Normal file
@@ -0,0 +1,29 @@
|
||||
package com.dfsek.terra.math;
|
||||
|
||||
import parsii.eval.Expression;
|
||||
import parsii.eval.Function;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class BlankFunction implements Function {
|
||||
private final int args;
|
||||
|
||||
public BlankFunction(int args) {
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumberOfArguments() {
|
||||
return args;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double eval(List<Expression> list) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNaturalFunction() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
6
src/main/java/com/dfsek/terra/math/NoiseFunction.java
Normal file
6
src/main/java/com/dfsek/terra/math/NoiseFunction.java
Normal file
@@ -0,0 +1,6 @@
|
||||
package com.dfsek.terra.math;
|
||||
|
||||
import parsii.eval.Function;
|
||||
|
||||
public interface NoiseFunction extends Function {
|
||||
}
|
||||
@@ -1,15 +1,20 @@
|
||||
package com.dfsek.terra.math;
|
||||
|
||||
import com.dfsek.terra.config.base.ConfigUtil;
|
||||
import com.dfsek.terra.generation.config.NoiseBuilder;
|
||||
import com.dfsek.terra.util.hash.HashMapDoubleDouble;
|
||||
import org.polydev.gaea.math.FastNoiseLite;
|
||||
import parsii.eval.Expression;
|
||||
import parsii.eval.Function;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class NoiseFunction2 implements Function {
|
||||
public class NoiseFunction2 implements NoiseFunction {
|
||||
private final FastNoiseLite gen;
|
||||
private final Cache cache = new Cache();
|
||||
private FastNoiseLite gen;
|
||||
|
||||
public NoiseFunction2(long seed, NoiseBuilder builder) {
|
||||
this.gen = builder.build((int) seed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumberOfArguments() {
|
||||
@@ -18,7 +23,17 @@ public class NoiseFunction2 implements Function {
|
||||
|
||||
@Override
|
||||
public double eval(List<Expression> list) {
|
||||
return cache.get(list.get(0).evaluate(), list.get(1).evaluate());
|
||||
return cache.get(gen, list.get(0).evaluate(), list.get(1).evaluate());
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate without cache. For testing.
|
||||
*
|
||||
* @param list Parameters.
|
||||
* @return Result.
|
||||
*/
|
||||
public double evalNoCache(List<Expression> list) {
|
||||
return gen.getNoise(list.get(0).evaluate(), list.get(1).evaluate());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -26,28 +41,24 @@ public class NoiseFunction2 implements Function {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setNoise(FastNoiseLite gen) {
|
||||
this.gen = gen;
|
||||
}
|
||||
private static class Cache extends HashMapDoubleDouble {
|
||||
private static final long serialVersionUID = 8915092734723467010L;
|
||||
private static final int cacheSize = ConfigUtil.cacheSize;
|
||||
|
||||
private final class Cache {
|
||||
private final double[] cacheX = new double[ConfigUtil.cacheSize];
|
||||
private final double[] cacheZ = new double[ConfigUtil.cacheSize];
|
||||
private final double[] cacheValues = new double[ConfigUtil.cacheSize];
|
||||
public double get(FastNoiseLite noise, double x, double z) {
|
||||
double xx = x >= 0 ? x * 2 : x * -2 - 1;
|
||||
double zz = z >= 0 ? z * 2 : z * -2 - 1;
|
||||
double key = (xx >= zz) ? (xx * xx + xx + zz) : (zz * zz + xx);
|
||||
double value = this.get(key);
|
||||
if(this.size() > cacheSize) {
|
||||
this.clear();
|
||||
}
|
||||
return (value == 4.9E-324D ? addAndReturn(noise.getNoise(x, z), key) : value);
|
||||
}
|
||||
|
||||
public double get(double x, double z) {
|
||||
for(int i = 0; i < cacheX.length; i++) {
|
||||
if(cacheX[i] == x && cacheZ[i] == z) return cacheValues[i];
|
||||
}
|
||||
cacheX[0] = x;
|
||||
cacheZ[0] = z;
|
||||
cacheValues[0] = gen.getNoise(x, z);
|
||||
for(int i = 0; i < cacheX.length - 1; i++) {
|
||||
cacheX[i + 1] = cacheX[i];
|
||||
cacheZ[i + 1] = cacheZ[i];
|
||||
cacheValues[i + 1] = cacheValues[i];
|
||||
}
|
||||
return cacheValues[0];
|
||||
private double addAndReturn(double value, double key) {
|
||||
this.put(key, value);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
package com.dfsek.terra.math;
|
||||
|
||||
import com.dfsek.terra.generation.config.NoiseBuilder;
|
||||
import org.polydev.gaea.math.FastNoiseLite;
|
||||
import parsii.eval.Expression;
|
||||
import parsii.eval.Function;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class NoiseFunction3 implements Function {
|
||||
private FastNoiseLite gen;
|
||||
public class NoiseFunction3 implements NoiseFunction {
|
||||
private final FastNoiseLite gen;
|
||||
|
||||
public NoiseFunction3(long seed, NoiseBuilder builder) {
|
||||
this.gen = builder.build((int) seed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumberOfArguments() {
|
||||
@@ -23,8 +27,4 @@ public class NoiseFunction3 implements Function {
|
||||
public boolean isNaturalFunction() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setNoise(FastNoiseLite gen) {
|
||||
this.gen = gen;
|
||||
}
|
||||
}
|
||||
|
||||
30
src/main/java/com/dfsek/terra/math/RandomFunction.java
Normal file
30
src/main/java/com/dfsek/terra/math/RandomFunction.java
Normal file
@@ -0,0 +1,30 @@
|
||||
package com.dfsek.terra.math;
|
||||
|
||||
import org.polydev.gaea.util.FastRandom;
|
||||
import parsii.eval.Expression;
|
||||
import parsii.eval.Function;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Provides access to a PRNG ({@link org.polydev.gaea.util.FastRandom})
|
||||
* <p>
|
||||
* Takes 1 argument, which sets the seed
|
||||
*/
|
||||
public class RandomFunction implements Function {
|
||||
@Override
|
||||
public int getNumberOfArguments() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double eval(List<Expression> list) {
|
||||
long seed = (long) list.get(0).evaluate();
|
||||
return new FastRandom(seed).nextDouble();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNaturalFunction() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import com.dfsek.terra.TerraWorld;
|
||||
import com.dfsek.terra.config.base.ConfigPack;
|
||||
import com.dfsek.terra.config.base.ConfigUtil;
|
||||
import com.dfsek.terra.config.genconfig.CarverConfig;
|
||||
import com.dfsek.terra.util.PopulationUtil;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
@@ -30,9 +31,10 @@ public class CavePopulator extends BlockPopulator {
|
||||
|
||||
@SuppressWarnings("try")
|
||||
@Override
|
||||
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) {
|
||||
public void populate(@NotNull World world, @NotNull Random r, @NotNull Chunk chunk) {
|
||||
if(ConfigUtil.masterDisableCaves) return;
|
||||
try(ProfileFuture ignored = TerraProfiler.fromWorld(world).measure("CaveTime")) {
|
||||
Random random = PopulationUtil.getRandom(chunk);
|
||||
TerraWorld tw = TerraWorld.getWorld(world);
|
||||
if(!tw.isSafe()) return;
|
||||
ConfigPack config = tw.getConfig();
|
||||
@@ -70,24 +72,23 @@ public class CavePopulator extends BlockPopulator {
|
||||
updateNeeded.add(b);
|
||||
}
|
||||
}
|
||||
for(Location l : shiftCandidate.keySet()) {
|
||||
for(Map.Entry<Location, Material> entry : shiftCandidate.entrySet()) {
|
||||
Location l = entry.getKey();
|
||||
Location mut = l.clone();
|
||||
Material orig = l.getBlock().getType();
|
||||
do mut.subtract(0, 1, 0);
|
||||
while(mut.getBlock().getType().equals(orig));
|
||||
try {
|
||||
if(c.getShiftedBlocks().get(shiftCandidate.get(l)).contains(mut.getBlock().getType())) {
|
||||
mut.getBlock().setBlockData(shiftStorage.computeIfAbsent(shiftCandidate.get(l), Material::createBlockData), false);
|
||||
if(c.getShiftedBlocks().get(entry.getValue()).contains(mut.getBlock().getType())) {
|
||||
mut.getBlock().setBlockData(shiftStorage.computeIfAbsent(entry.getValue(), Material::createBlockData), false);
|
||||
}
|
||||
} catch(NullPointerException ignore) {
|
||||
}
|
||||
}
|
||||
try(ProfileFuture ignore = TerraProfiler.fromWorld(world).measure("CaveBlockUpdate")) {
|
||||
for(Block b : updateNeeded) {
|
||||
BlockData orig = b.getBlockData();
|
||||
b.setBlockData(AIR, false);
|
||||
b.setBlockData(orig, true);
|
||||
}
|
||||
for(Block b : updateNeeded) {
|
||||
BlockData orig = b.getBlockData();
|
||||
b.setBlockData(AIR, false);
|
||||
b.setBlockData(orig, true);
|
||||
}
|
||||
/*for(Map.Entry<Vector, CarvingData.CarvingType> e : new SimplexCarver(chunk.getX(), chunk.getZ()).carve(chunk.getX(), chunk.getZ(), world).getCarvedBlocks().entrySet()) {
|
||||
Vector v = e.getKey();
|
||||
|
||||
@@ -1,29 +1,20 @@
|
||||
package com.dfsek.terra.population;
|
||||
|
||||
import com.dfsek.terra.Terra;
|
||||
import com.dfsek.terra.TerraProfiler;
|
||||
import com.dfsek.terra.TerraWorld;
|
||||
import com.dfsek.terra.biome.UserDefinedBiome;
|
||||
import com.dfsek.terra.biome.grid.TerraBiomeGrid;
|
||||
import com.dfsek.terra.config.base.ConfigPack;
|
||||
import com.dfsek.terra.config.genconfig.biome.BiomeConfig;
|
||||
import com.dfsek.terra.config.genconfig.biome.BiomeFloraConfig;
|
||||
import com.dfsek.terra.event.TreeGenerateEvent;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.polydev.gaea.generation.GenerationPhase;
|
||||
import org.polydev.gaea.math.Range;
|
||||
import org.polydev.gaea.population.GaeaBlockPopulator;
|
||||
import org.polydev.gaea.profiler.ProfileFuture;
|
||||
import org.polydev.gaea.tree.Tree;
|
||||
import org.polydev.gaea.world.Flora;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
@@ -39,21 +30,12 @@ public class FloraPopulator extends GaeaBlockPopulator {
|
||||
int originX = chunk.getX() << 4;
|
||||
int originZ = chunk.getZ() << 4;
|
||||
TerraBiomeGrid grid = tw.getGrid();
|
||||
ConfigPack config = tw.getConfig();
|
||||
for(int x = 0; x < 16; x++) {
|
||||
for(int z = 0; z < 16; z++) {
|
||||
UserDefinedBiome biome = (UserDefinedBiome) grid.getBiome((chunk.getX() << 4) + x, (chunk.getZ() << 4) + z, GenerationPhase.POPULATE);
|
||||
if((x & 1) == 0 && (z & 1) == 0) {
|
||||
int treeChance = biome.getDecorator().getTreeDensity();
|
||||
if(random.nextInt(1000) < treeChance) {
|
||||
int xt = offset(random, x);
|
||||
int zt = offset(random, z);
|
||||
if(doTrees(biome, tw, random, chunk, xt, zt)) continue;
|
||||
}
|
||||
}
|
||||
if(biome.getDecorator().getFloraChance() <= 0) continue;
|
||||
try {
|
||||
BiomeConfig c = config.getBiome(biome);
|
||||
BiomeConfig c = biome.getConfig();
|
||||
BiomeFloraConfig f = c.getFlora();
|
||||
for(int i = 0; i < f.getFloraAttempts(); i++) {
|
||||
Flora item;
|
||||
@@ -71,34 +53,4 @@ public class FloraPopulator extends GaeaBlockPopulator {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean doTrees(@NotNull UserDefinedBiome biome, TerraWorld world, @NotNull Random random, @NotNull Chunk chunk, int x, int z) {
|
||||
for(Block block : getValidTreeSpawnsAt(chunk, x, z, new Range(0, 254))) {
|
||||
Tree tree = biome.getDecorator().getTrees().get(random);
|
||||
Range range = world.getConfig().getBiome(biome).getTreeRange(tree);
|
||||
if(!range.isInRange(block.getY())) continue;
|
||||
try {
|
||||
Location l = block.getLocation();
|
||||
TreeGenerateEvent event = new TreeGenerateEvent(world, l, tree);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
if(!event.isCancelled()) tree.plant(l, random, Terra.getInstance());
|
||||
} catch(NullPointerException ignore) {
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static List<Block> getValidTreeSpawnsAt(Chunk chunk, int x, int z, Range check) {
|
||||
List<Block> blocks = new ArrayList<>();
|
||||
for(int y : check) {
|
||||
if(chunk.getBlock(x, y, z).getType().isSolid() && chunk.getBlock(x, y + 1, z).getType().isAir()) {
|
||||
blocks.add(chunk.getBlock(x, y + 1, z));
|
||||
}
|
||||
}
|
||||
return blocks;
|
||||
}
|
||||
|
||||
private static int offset(Random r, int i) {
|
||||
return Math.min(Math.max(i + r.nextInt(3) - 1, 0), 15);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.dfsek.terra.population;
|
||||
import com.dfsek.terra.TerraProfiler;
|
||||
import com.dfsek.terra.TerraWorld;
|
||||
import com.dfsek.terra.biome.UserDefinedBiome;
|
||||
import com.dfsek.terra.config.base.ConfigPack;
|
||||
import com.dfsek.terra.config.genconfig.OreConfig;
|
||||
import com.dfsek.terra.config.genconfig.biome.BiomeOreConfig;
|
||||
import com.dfsek.terra.event.OreVeinGenerateEvent;
|
||||
@@ -24,28 +23,29 @@ import java.util.Random;
|
||||
public class OrePopulator extends GaeaBlockPopulator {
|
||||
@SuppressWarnings("try")
|
||||
@Override
|
||||
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) {
|
||||
public void populate(@NotNull World world, @NotNull Random r, @NotNull Chunk chunk) {
|
||||
try(ProfileFuture ignored = TerraProfiler.fromWorld(world).measure("OreTime")) {
|
||||
TerraWorld tw = TerraWorld.getWorld(world);
|
||||
if(!tw.isSafe()) return;
|
||||
ConfigPack config = tw.getConfig();
|
||||
Biome b = TerraWorld.getWorld(world).getGrid().getBiome((chunk.getX() << 4) + 8, (chunk.getZ() << 4) + 8, GenerationPhase.POPULATE);
|
||||
BiomeOreConfig ores = config.getBiome((UserDefinedBiome) b).getOres();
|
||||
for(Map.Entry<OreConfig, Range> e : ores.getOres().entrySet()) {
|
||||
int num = e.getValue().get(random);
|
||||
OreConfig ore = e.getKey();
|
||||
int edgeOffset = ore.getChunkEdgeOffset();
|
||||
for(int i = 0; i < num; i++) {
|
||||
int x = random.nextInt(16 - edgeOffset * 2) + edgeOffset;
|
||||
int z = random.nextInt(16 - edgeOffset * 2) + edgeOffset;
|
||||
int y = ores.getOreHeights().get(ore).get(random);
|
||||
for(int cx = -1; cx <= 1; cx++) {
|
||||
for(int cz = -1; cz <= 1; cz++) {
|
||||
Biome b = TerraWorld.getWorld(world).getGrid().getBiome(((chunk.getX() + cx) << 4) + 8, ((chunk.getZ() + cz) << 4) + 8, GenerationPhase.POPULATE);
|
||||
BiomeOreConfig ores = ((UserDefinedBiome) b).getConfig().getOres();
|
||||
for(Map.Entry<OreConfig, Range> e : ores.getOres().entrySet()) {
|
||||
int num = e.getValue().get(r);
|
||||
OreConfig ore = e.getKey();
|
||||
for(int i = 0; i < num; i++) {
|
||||
int x = r.nextInt(16) + cx * 16;
|
||||
int z = r.nextInt(16) + cz * 16;
|
||||
int y = ores.getOreHeights().get(ore).get(r);
|
||||
|
||||
Vector v = new Vector(x, y, z);
|
||||
OreVeinGenerateEvent event = new OreVeinGenerateEvent(tw, v.toLocation(world), ore);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
if(!event.isCancelled()) {
|
||||
if(ore.crossChunks()) ore.doVein(v, chunk, random);
|
||||
else ore.doVeinSingle(new Vector(x, y, z), chunk, random);
|
||||
Vector v = new Vector(x, y, z);
|
||||
OreVeinGenerateEvent event = new OreVeinGenerateEvent(tw, v.toLocation(world), ore);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
if(!event.isCancelled()) {
|
||||
ore.doVeinSingle(new Vector(x, y, z), chunk, r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,9 @@ import org.bukkit.Chunk;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.Snowable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.polydev.gaea.generation.GenerationPhase;
|
||||
import org.polydev.gaea.population.GaeaBlockPopulator;
|
||||
@@ -55,7 +58,7 @@ public class SnowPopulator extends GaeaBlockPopulator {
|
||||
TerraBiomeGrid g = w.getGrid();
|
||||
for(int x = 0; x < 16; x++) {
|
||||
for(int z = 0; z < 16; z++) {
|
||||
BiomeConfig biome = w.getConfig().getBiome((UserDefinedBiome) g.getBiome(origX + x, origZ + z, GenerationPhase.PALETTE_APPLY));
|
||||
BiomeConfig biome = ((UserDefinedBiome) g.getBiome(origX + x, origZ + z, GenerationPhase.PALETTE_APPLY)).getConfig();
|
||||
if(!biome.getSnow().doSnow()) continue;
|
||||
int y;
|
||||
Block b = null;
|
||||
@@ -66,7 +69,13 @@ public class SnowPopulator extends GaeaBlockPopulator {
|
||||
if(random.nextInt(100) >= biome.getSnow().getSnowChance(y))
|
||||
continue;
|
||||
if(blacklistSpawn.contains(b.getType()) || b.isPassable()) continue;
|
||||
chunk.getBlock(x, ++y, z).setBlockData(DataUtil.SNOW);
|
||||
boolean phys = biome.getSnow().doPhysics();
|
||||
if(!phys) {
|
||||
BlockData data = b.getBlockData();
|
||||
if(data instanceof Snowable) phys = true;
|
||||
}
|
||||
b.getRelative(BlockFace.UP).setBlockData(DataUtil.SNOW, phys);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,9 @@ import com.dfsek.terra.structure.Rotation;
|
||||
import com.dfsek.terra.structure.Structure;
|
||||
import com.dfsek.terra.structure.StructureContainedInventory;
|
||||
import com.dfsek.terra.structure.features.Feature;
|
||||
import com.dfsek.terra.util.PopulationUtil;
|
||||
import com.dfsek.terra.util.structure.RotationUtil;
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
@@ -21,6 +23,7 @@ import org.bukkit.inventory.BlockInventoryHolder;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.polydev.gaea.profiler.ProfileFuture;
|
||||
import org.polydev.gaea.structures.loot.LootTable;
|
||||
import org.polydev.gaea.util.FastRandom;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
@@ -28,8 +31,9 @@ public class StructurePopulator extends BlockPopulator {
|
||||
|
||||
@SuppressWarnings("try")
|
||||
@Override
|
||||
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) {
|
||||
public void populate(@NotNull World world, @NotNull Random r, @NotNull Chunk chunk) {
|
||||
try(ProfileFuture ignored = TerraProfiler.fromWorld(world).measure("StructureTime")) {
|
||||
Random random = PopulationUtil.getRandom(chunk);
|
||||
int cx = (chunk.getX() << 4);
|
||||
int cz = (chunk.getZ() << 4);
|
||||
TerraWorld tw = TerraWorld.getWorld(world);
|
||||
@@ -39,8 +43,8 @@ public class StructurePopulator extends BlockPopulator {
|
||||
structure:
|
||||
for(StructureConfig conf : config.getAllStructures()) {
|
||||
Location spawn = conf.getSpawn().getNearestSpawn(cx + 8, cz + 8, world.getSeed()).toLocation(world);
|
||||
if(!config.getBiome((UserDefinedBiome) grid.getBiome(spawn)).getStructures().contains(conf)) continue;
|
||||
Random r2 = new Random(spawn.hashCode());
|
||||
if(!((UserDefinedBiome) grid.getBiome(spawn)).getConfig().getStructures().contains(conf)) continue;
|
||||
Random r2 = new FastRandom(spawn.hashCode());
|
||||
Structure struc = conf.getStructure(r2);
|
||||
Rotation rotation = Rotation.fromDegrees(r2.nextInt(4) * 90);
|
||||
for(int y = conf.getSearchStart().get(r2); y > 0; y--) {
|
||||
@@ -48,15 +52,15 @@ public class StructurePopulator extends BlockPopulator {
|
||||
spawn.setY(y);
|
||||
if(!struc.checkSpawns(spawn, rotation)) continue;
|
||||
double horizontal = struc.getStructureInfo().getMaxHorizontal();
|
||||
if(Math.abs((cx + 8) - spawn.getBlockX()) <= horizontal && Math.abs((cz + 8) - spawn.getBlockZ()) <= horizontal) {
|
||||
if(FastMath.abs((cx + 8) - spawn.getBlockX()) <= horizontal && FastMath.abs((cz + 8) - spawn.getBlockZ()) <= horizontal) {
|
||||
struc.paste(spawn, chunk, rotation);
|
||||
for(StructureContainedInventory i : struc.getInventories()) {
|
||||
try {
|
||||
Debug.info("Attempting to populate loot: " + i.getUid());
|
||||
Vector2 lootCoords = RotationUtil.getRotatedCoords(new Vector2(i.getX() - struc.getStructureInfo().getCenterX(), i.getZ() - struc.getStructureInfo().getCenterZ()), rotation.inverse());
|
||||
Location inv = spawn.clone().add(lootCoords.getX(), i.getY(), lootCoords.getZ());
|
||||
Debug.info(Math.floorDiv(inv.getBlockX(), 16) + ":" + chunk.getX() + ", " + Math.floorDiv(inv.getBlockZ(), 16) + ":" + chunk.getZ());
|
||||
if(Math.floorDiv(inv.getBlockX(), 16) != chunk.getX() || Math.floorDiv(inv.getBlockZ(), 16) != chunk.getZ())
|
||||
Debug.info(FastMath.floorDiv(inv.getBlockX(), 16) + ":" + chunk.getX() + ", " + FastMath.floorDiv(inv.getBlockZ(), 16) + ":" + chunk.getZ());
|
||||
if(FastMath.floorDiv(inv.getBlockX(), 16) != chunk.getX() || FastMath.floorDiv(inv.getBlockZ(), 16) != chunk.getZ())
|
||||
continue;
|
||||
Debug.info("Target is in chunk.");
|
||||
Debug.info(spawn.toString() + " became: " + inv.toString() + " (" + rotation + ", " + inv.getBlock().getType() + ")");
|
||||
@@ -69,7 +73,7 @@ public class StructurePopulator extends BlockPopulator {
|
||||
Debug.stack(e);
|
||||
}
|
||||
}
|
||||
for(Feature f : conf.getFeatures()) f.apply(struc, spawn, chunk); // Apply features.
|
||||
for(Feature f : conf.getFeatures()) f.apply(struc, rotation, spawn, chunk); // Apply features.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
77
src/main/java/com/dfsek/terra/population/TreePopulator.java
Normal file
77
src/main/java/com/dfsek/terra/population/TreePopulator.java
Normal file
@@ -0,0 +1,77 @@
|
||||
package com.dfsek.terra.population;
|
||||
|
||||
import com.dfsek.terra.Terra;
|
||||
import com.dfsek.terra.TerraProfiler;
|
||||
import com.dfsek.terra.TerraWorld;
|
||||
import com.dfsek.terra.biome.UserDefinedBiome;
|
||||
import com.dfsek.terra.biome.grid.TerraBiomeGrid;
|
||||
import com.dfsek.terra.event.TreeGenerateEvent;
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.polydev.gaea.generation.GenerationPhase;
|
||||
import org.polydev.gaea.math.Range;
|
||||
import org.polydev.gaea.population.GaeaBlockPopulator;
|
||||
import org.polydev.gaea.profiler.ProfileFuture;
|
||||
import org.polydev.gaea.tree.Tree;
|
||||
import org.polydev.gaea.util.GlueList;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
|
||||
public class TreePopulator extends GaeaBlockPopulator {
|
||||
private static void doTrees(@NotNull UserDefinedBiome biome, TerraWorld world, @NotNull Random random, @NotNull Chunk chunk, int x, int z) {
|
||||
for(Block block : getValidTreeSpawnsAt(chunk, x, z, new Range(0, 254))) {
|
||||
Tree tree = biome.getDecorator().getTrees().get(random);
|
||||
Range range = biome.getConfig().getTreeRange(tree);
|
||||
if(!range.isInRange(block.getY())) continue;
|
||||
try {
|
||||
Location l = block.getLocation();
|
||||
TreeGenerateEvent event = new TreeGenerateEvent(world, l, tree);
|
||||
Bukkit.getPluginManager().callEvent(event);
|
||||
if(!event.isCancelled()) tree.plant(l, random, Terra.getInstance());
|
||||
} catch(NullPointerException ignore) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static List<Block> getValidTreeSpawnsAt(Chunk chunk, int x, int z, Range check) {
|
||||
List<Block> blocks = new GlueList<>();
|
||||
for(int y : check) {
|
||||
if(chunk.getBlock(x, y, z).getType().isSolid() && chunk.getBlock(x, y + 1, z).isPassable()) {
|
||||
blocks.add(chunk.getBlock(x, y + 1, z));
|
||||
}
|
||||
}
|
||||
return blocks;
|
||||
}
|
||||
|
||||
private static int offset(Random r, int i) {
|
||||
return FastMath.min(FastMath.max(i + r.nextInt(3) - 1, 0), 15);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("try")
|
||||
public void populate(@NotNull World world, @NotNull Random random, @NotNull Chunk chunk) {
|
||||
try(ProfileFuture ignored = TerraProfiler.fromWorld(world).measure("TreeTime")) {
|
||||
TerraWorld tw = TerraWorld.getWorld(world);
|
||||
if(!tw.isSafe()) return;
|
||||
TerraBiomeGrid grid = tw.getGrid();
|
||||
for(int x = 0; x < 16; x += 2) {
|
||||
for(int z = 0; z < 16; z += 2) {
|
||||
UserDefinedBiome biome = (UserDefinedBiome) grid.getBiome((chunk.getX() << 4) + x, (chunk.getZ() << 4) + z, GenerationPhase.POPULATE);
|
||||
int treeChance = biome.getDecorator().getTreeDensity();
|
||||
if(random.nextInt(1000) < treeChance) {
|
||||
int xt = offset(random, x);
|
||||
int zt = offset(random, z);
|
||||
doTrees(biome, tw, random, chunk, xt, zt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,9 @@ package com.dfsek.terra.procgen;
|
||||
|
||||
import org.bukkit.util.Vector;
|
||||
import org.polydev.gaea.math.MathUtil;
|
||||
import org.polydev.gaea.util.FastRandom;
|
||||
import org.polydev.gaea.util.GlueList;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
@@ -30,7 +31,7 @@ public class GridSpawn {
|
||||
public Vector getNearestSpawn(int x, int z, long seed) {
|
||||
int structureChunkX = x / (width + 2 * separation);
|
||||
int structureChunkZ = z / (width + 2 * separation);
|
||||
List<Vector> zones = new ArrayList<>();
|
||||
List<Vector> zones = new GlueList<>();
|
||||
for(int xi = structureChunkX - 1; xi <= structureChunkX + 1; xi++) {
|
||||
for(int zi = structureChunkZ - 1; zi <= structureChunkZ + 1; zi++) {
|
||||
zones.add(getChunkSpawn(xi, zi, seed));
|
||||
@@ -53,7 +54,7 @@ public class GridSpawn {
|
||||
* @return Vector representing spawnpoint
|
||||
*/
|
||||
public Vector getChunkSpawn(int structureChunkX, int structureChunkZ, long seed) {
|
||||
Random r = new Random(MathUtil.getCarverChunkSeed(structureChunkX, structureChunkZ, seed));
|
||||
Random r = new FastRandom(MathUtil.getCarverChunkSeed(structureChunkX, structureChunkZ, seed));
|
||||
int offsetX = r.nextInt(width);
|
||||
int offsetZ = r.nextInt(width);
|
||||
int sx = structureChunkX * (width + 2 * separation) + offsetX;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.dfsek.terra.procgen.math;
|
||||
|
||||
import net.jafama.FastMath;
|
||||
|
||||
/**
|
||||
* oh yeah
|
||||
*/
|
||||
@@ -111,7 +113,7 @@ public class Vector2 implements Cloneable {
|
||||
* @return length
|
||||
*/
|
||||
public double length() {
|
||||
return Math.sqrt(lengthSquared());
|
||||
return FastMath.sqrt(lengthSquared());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -130,7 +132,7 @@ public class Vector2 implements Cloneable {
|
||||
* @return Distance between vectors
|
||||
*/
|
||||
public double distance(Vector2 other) {
|
||||
return Math.sqrt(distanceSquared(other));
|
||||
return FastMath.sqrt(distanceSquared(other));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.dfsek.terra.procgen.pixel;
|
||||
|
||||
import com.dfsek.terra.procgen.math.Vector2;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
@@ -11,8 +12,8 @@ public class Rectangle extends Polygon {
|
||||
private final Vector2 max;
|
||||
|
||||
public Rectangle(Vector2 min, Vector2 max) {
|
||||
this.max = new Vector2(Math.min(min.getX(), max.getX()), Math.min(min.getZ(), max.getZ()));
|
||||
this.min = new Vector2(Math.max(min.getX(), max.getX()), Math.max(min.getZ(), max.getZ()));
|
||||
this.max = new Vector2(FastMath.min(min.getX(), max.getX()), FastMath.min(min.getZ(), max.getZ()));
|
||||
this.min = new Vector2(FastMath.max(min.getX(), max.getX()), FastMath.max(min.getZ(), max.getZ()));
|
||||
}
|
||||
|
||||
public Rectangle(Vector2 center, double xRadius, double zRadius) {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package com.dfsek.terra.procgen.voxel;
|
||||
|
||||
import org.bukkit.util.Vector;
|
||||
import org.polydev.gaea.util.GlueList;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class VoxelGeometry {
|
||||
private final List<Vector> geometry = new ArrayList<>();
|
||||
private final List<Vector> geometry = new GlueList<>();
|
||||
|
||||
public static VoxelGeometry getBlank() {
|
||||
return new VoxelGeometry() {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.dfsek.terra.structure;
|
||||
|
||||
import net.jafama.FastMath;
|
||||
|
||||
public enum Rotation {
|
||||
CW_90(90), CW_180(180), CCW_90(270), NONE(0);
|
||||
private final int degrees;
|
||||
@@ -9,7 +11,7 @@ public enum Rotation {
|
||||
}
|
||||
|
||||
public static Rotation fromDegrees(int deg) {
|
||||
switch(Math.floorMod(deg, 360)) {
|
||||
switch(FastMath.floorMod(deg, 360)) {
|
||||
case 0:
|
||||
return Rotation.NONE;
|
||||
case 90:
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.dfsek.terra.structure;
|
||||
import com.dfsek.terra.Debug;
|
||||
import com.dfsek.terra.procgen.math.Vector2;
|
||||
import com.dfsek.terra.util.structure.RotationUtil;
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
@@ -144,6 +145,16 @@ public class Structure implements Serializable {
|
||||
return (Structure) o;
|
||||
}
|
||||
|
||||
private static void toFile(@NotNull Serializable o, @NotNull File f) throws IOException {
|
||||
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(f));
|
||||
oos.writeObject(o);
|
||||
oos.close();
|
||||
}
|
||||
|
||||
public StructureContainedBlock[][][] getRawStructure() {
|
||||
return structure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Paste the structure at a Location, ignoring chunk boundaries.
|
||||
*
|
||||
@@ -188,7 +199,7 @@ public class Structure implements Serializable {
|
||||
}
|
||||
int offset = block.getPullOffset();
|
||||
if(offset != 0)
|
||||
worldBlock = worldBlock.getRelative((offset > 0) ? BlockFace.UP : BlockFace.DOWN, Math.abs(offset));
|
||||
worldBlock = worldBlock.getRelative((offset > 0) ? BlockFace.UP : BlockFace.DOWN, FastMath.abs(offset));
|
||||
|
||||
RotationUtil.rotateBlockData(data, r);
|
||||
|
||||
@@ -255,9 +266,9 @@ public class Structure implements Serializable {
|
||||
Vector2 max = getRotatedCoords(new Vector2(x.getMax(), z.getMax()).subtract(center), r.inverse()).add(center);
|
||||
|
||||
if(a.equals(Rotation.Axis.X))
|
||||
return new Range((int) Math.floor(Math.min(min.getX(), max.getX())), (int) Math.ceil(Math.max(min.getX(), max.getX())) + 1);
|
||||
return new Range((int) FastMath.floor(FastMath.min(min.getX(), max.getX())), (int) FastMath.ceil(FastMath.max(min.getX(), max.getX())) + 1);
|
||||
else
|
||||
return new Range((int) Math.floor(Math.min(min.getZ(), max.getZ())), (int) Math.ceil(Math.max(min.getZ(), max.getZ())) + 1);
|
||||
return new Range((int) FastMath.floor(FastMath.min(min.getZ(), max.getZ())), (int) FastMath.ceil(FastMath.max(min.getZ(), max.getZ())) + 1);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -283,6 +294,10 @@ public class Structure implements Serializable {
|
||||
return true;
|
||||
}
|
||||
|
||||
public HashSet<StructureContainedBlock> getSpawns() {
|
||||
return spawns;
|
||||
}
|
||||
|
||||
public HashSet<StructureContainedInventory> getInventories() {
|
||||
return inventories;
|
||||
}
|
||||
@@ -324,12 +339,6 @@ public class Structure implements Serializable {
|
||||
toFile(this, f);
|
||||
}
|
||||
|
||||
private static void toFile(@NotNull Serializable o, @NotNull File f) throws IOException {
|
||||
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(f));
|
||||
oos.writeObject(o);
|
||||
oos.close();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getId() {
|
||||
return id;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.dfsek.terra.structure;
|
||||
|
||||
import com.dfsek.terra.procgen.math.Vector2;
|
||||
import net.jafama.FastMath;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@@ -41,6 +42,6 @@ public class StructureInfo implements Serializable {
|
||||
}
|
||||
|
||||
public double getMaxHorizontal() {
|
||||
return Math.sqrt(Math.pow(sizeX, 2) + Math.pow(sizeZ, 2));
|
||||
return FastMath.sqrt(FastMath.pow(sizeX, 2) + FastMath.pow(sizeZ, 2));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package com.dfsek.terra.structure.features;
|
||||
|
||||
import com.dfsek.terra.Debug;
|
||||
import com.dfsek.terra.structure.Rotation;
|
||||
import com.dfsek.terra.structure.Structure;
|
||||
import com.dfsek.terra.structure.StructureInfo;
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
@@ -11,105 +13,83 @@ import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.polydev.gaea.math.MathUtil;
|
||||
import org.polydev.gaea.math.Range;
|
||||
import org.polydev.gaea.util.FastRandom;
|
||||
import org.polydev.gaea.util.GlueList;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
public class EntityFeature implements Feature {
|
||||
private final EntityType type;
|
||||
private final Range amount;
|
||||
private final int attempts;
|
||||
private final Set<Material> in;
|
||||
private final Set<Material> stand;
|
||||
private final int inSize;
|
||||
|
||||
public EntityFeature(EntityType type, Range amount, int attempts, Set<Material> stand, Set<Material> in, int inSize) {
|
||||
public EntityFeature(EntityType type, Range amount, Set<Material> stand, Set<Material> in, int inSize) {
|
||||
this.type = type;
|
||||
this.amount = amount;
|
||||
this.attempts = attempts;
|
||||
this.in = in;
|
||||
this.stand = stand;
|
||||
this.inSize = inSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(Structure structure, Location l, Chunk chunk) {
|
||||
Random random = new Random(MathUtil.getCarverChunkSeed(chunk.getX(), chunk.getZ(), chunk.getWorld().getSeed()));
|
||||
|
||||
int amountSpawn = amount.get(random);
|
||||
private static boolean isInChunk(Chunk c, Location l) {
|
||||
return FastMath.floorDiv(l.getBlockX(), 16) == c.getX() && FastMath.floorDiv(l.getBlockZ(), 16) == c.getZ();
|
||||
}
|
||||
|
||||
private static List<Location> getLocations(Structure structure, Rotation r, Location origin, Random random, int number) {
|
||||
StructureInfo info = structure.getStructureInfo();
|
||||
Range x = new Range(0, info.getSizeZ());
|
||||
Range y = new Range(0, info.getSizeY());
|
||||
Range z = new Range(0, info.getSizeZ());
|
||||
Range x = structure.getRange(Rotation.Axis.X, r);
|
||||
Range y = structure.getRange(Rotation.Axis.Y, r);
|
||||
Range z = structure.getRange(Rotation.Axis.Z, r);
|
||||
|
||||
int cx = info.getCenterX();
|
||||
int cz = info.getCenterZ();
|
||||
List<Location> locations = new GlueList<>();
|
||||
for(int i = 0; i < number; i++)
|
||||
locations.add(origin.clone().add(x.get(random) - cx, y.get(random), z.get(random) - cz));
|
||||
return locations;
|
||||
}
|
||||
|
||||
for(int i = 0; i < amountSpawn && i < attempts; i++) {
|
||||
int yv = y.get(random);
|
||||
Location attempt = l.clone().add(x.get(random) - cx, yv, z.get(random) - cz);
|
||||
@Override
|
||||
public void apply(Structure structure, Rotation r, Location l, Chunk chunk) {
|
||||
Random random = new FastRandom(MathUtil.getCarverChunkSeed(chunk.getX(), chunk.getZ(), chunk.getWorld().getSeed()));
|
||||
for(Location attempt : getLocations(structure, r, l, random, amount.get(random))) {
|
||||
if(!isInChunk(chunk, attempt)) continue; // Don't attempt spawn if not in current chunk.
|
||||
|
||||
boolean canSpawn = false;
|
||||
while(yv >= 0 && attempt.getBlockY() >= l.getBlockY()) { // Go down, see if valid spawns exist.
|
||||
canSpawn = true;
|
||||
Block on = attempt.getBlock();
|
||||
attempt.subtract(0, 1, 0);
|
||||
yv--;
|
||||
|
||||
if(!stand.contains(on.getType())) continue;
|
||||
|
||||
for(int j = 1; j < inSize + 1; j++)
|
||||
if(!in.contains(on.getRelative(BlockFace.UP, j).getType())) canSpawn = false;
|
||||
|
||||
if(canSpawn) break;
|
||||
}
|
||||
if(canSpawn) {
|
||||
Debug.info("Spawning entity at " + attempt);
|
||||
chunk.getWorld().spawnEntity(attempt.add(0.5, 2, 0.5), type); // Add 0.5 to X & Z so entity spawns in center of block.
|
||||
}
|
||||
attemptSpawn(attempt, l);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isInChunk(Chunk c, Location l) {
|
||||
return Math.floorDiv(l.getBlockX(), 16) == c.getX() && Math.floorDiv(l.getBlockZ(), 16) == c.getZ();
|
||||
private void attemptSpawn(Location attempt, Location origin) {
|
||||
boolean canSpawn = false;
|
||||
while(attempt.getBlockY() >= origin.getBlockY()) { // Go down, see if valid spawns exist.
|
||||
canSpawn = true;
|
||||
Block on = attempt.getBlock();
|
||||
attempt.subtract(0, 1, 0);
|
||||
|
||||
if(!stand.contains(on.getType())) {
|
||||
canSpawn = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
for(int j = 1; j < inSize + 1; j++)
|
||||
if(!in.contains(on.getRelative(BlockFace.UP, j).getType())) canSpawn = false;
|
||||
|
||||
if(canSpawn) break;
|
||||
}
|
||||
if(canSpawn) {
|
||||
Debug.info("Spawning entity at " + attempt);
|
||||
Objects.requireNonNull(attempt.getWorld()).spawnEntity(attempt.add(0.5, 2, 0.5), type); // Add 0.5 to X & Z so entity spawns in center of block.
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(Structure structure, Location l, Random random) {
|
||||
int amountSpawn = amount.get(random);
|
||||
|
||||
StructureInfo info = structure.getStructureInfo();
|
||||
Range x = new Range(0, info.getSizeZ());
|
||||
Range y = new Range(0, info.getSizeY());
|
||||
Range z = new Range(0, info.getSizeZ());
|
||||
|
||||
int cx = info.getCenterX();
|
||||
int cz = info.getCenterZ();
|
||||
|
||||
for(int i = 0; i < amountSpawn && i < attempts; i++) {
|
||||
int yv = y.get(random);
|
||||
Location attempt = l.clone().add(x.get(random) - cx, yv, z.get(random) - cz);
|
||||
|
||||
boolean canSpawn = false;
|
||||
while(yv >= 0 && attempt.getBlockY() >= l.getBlockY()) { // Go down, see if valid spawns exist.
|
||||
canSpawn = true;
|
||||
Block on = attempt.getBlock();
|
||||
attempt.subtract(0, 1, 0);
|
||||
yv--;
|
||||
|
||||
if(!stand.contains(on.getType())) continue;
|
||||
|
||||
for(int j = 1; j < inSize + 1; j++)
|
||||
if(!in.contains(on.getRelative(BlockFace.UP, j).getType())) canSpawn = false;
|
||||
|
||||
if(canSpawn) break;
|
||||
}
|
||||
if(canSpawn) {
|
||||
Debug.info("Spawning entity at " + attempt);
|
||||
l.getWorld().spawnEntity(attempt.add(0.5, 1, 0.5), type); // Add 0.5 to X & Z so entity spawns in center of block.
|
||||
}
|
||||
public void apply(Structure structure, Rotation r, Location l, Random random) {
|
||||
for(Location attempt : getLocations(structure, r, l, random, amount.get(random))) {
|
||||
attemptSpawn(attempt, l);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.dfsek.terra.structure.features;
|
||||
|
||||
import com.dfsek.terra.structure.Rotation;
|
||||
import com.dfsek.terra.structure.Structure;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Location;
|
||||
@@ -7,7 +8,7 @@ import org.bukkit.Location;
|
||||
import java.util.Random;
|
||||
|
||||
public interface Feature {
|
||||
void apply(Structure structure, Location l, Chunk chunk);
|
||||
void apply(Structure structure, Rotation r, Location l, Chunk chunk);
|
||||
|
||||
void apply(Structure structure, Location l, Random random);
|
||||
void apply(Structure structure, Rotation r, Location l, Random random);
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@ package com.dfsek.terra.structure.spawn;
|
||||
|
||||
import com.dfsek.terra.TerraWorld;
|
||||
import com.dfsek.terra.biome.UserDefinedBiome;
|
||||
import com.dfsek.terra.config.base.ConfigPack;
|
||||
import com.dfsek.terra.config.genconfig.biome.BiomeConfig;
|
||||
import com.dfsek.terra.generation.config.WorldGenerator;
|
||||
import org.bukkit.World;
|
||||
import org.polydev.gaea.generation.GenerationPhase;
|
||||
|
||||
@@ -15,10 +15,10 @@ public class AirSpawn extends Requirement {
|
||||
@Override
|
||||
public boolean matches(int x, int y, int z) {
|
||||
TerraWorld tw = TerraWorld.getWorld(getWorld());
|
||||
ConfigPack wc = tw.getConfig();
|
||||
UserDefinedBiome b = (UserDefinedBiome) tw.getGrid().getBiome(x, z, GenerationPhase.POPULATE);
|
||||
BiomeConfig c = wc.getBiome(b);
|
||||
BiomeConfig c = b.getConfig();
|
||||
if(y <= c.getOcean().getSeaLevel()) return false;
|
||||
return b.getGenerator().getNoise(getNoise(), getWorld(), x, y, z) <= 0;
|
||||
int yf = (int) (y - ((WorldGenerator) b.getGenerator()).getElevation(x, z));
|
||||
return b.getGenerator().getNoise(getNoise(), getWorld(), x, yf, z) <= 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.dfsek.terra.structure.spawn;
|
||||
|
||||
import com.dfsek.terra.TerraWorld;
|
||||
import com.dfsek.terra.biome.UserDefinedBiome;
|
||||
import com.dfsek.terra.generation.config.WorldGenerator;
|
||||
import org.bukkit.World;
|
||||
import org.polydev.gaea.generation.GenerationPhase;
|
||||
|
||||
@@ -14,6 +15,7 @@ public class LandSpawn extends Requirement {
|
||||
public boolean matches(int x, int y, int z) {
|
||||
TerraWorld tw = TerraWorld.getWorld(getWorld());
|
||||
UserDefinedBiome b = (UserDefinedBiome) tw.getGrid().getBiome(x, z, GenerationPhase.POPULATE);
|
||||
return b.getGenerator().getNoise(getNoise(), getWorld(), x, y, z) > 0;
|
||||
int yf = (int) (y - ((WorldGenerator) b.getGenerator()).getElevation(x, z));
|
||||
return b.getGenerator().getNoise(getNoise(), getWorld(), x, yf, z) > 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.dfsek.terra.structure.spawn;
|
||||
import com.dfsek.terra.TerraWorld;
|
||||
import com.dfsek.terra.biome.UserDefinedBiome;
|
||||
import com.dfsek.terra.config.genconfig.biome.BiomeConfig;
|
||||
import com.dfsek.terra.generation.config.WorldGenerator;
|
||||
import org.bukkit.World;
|
||||
import org.polydev.gaea.generation.GenerationPhase;
|
||||
|
||||
@@ -15,8 +16,9 @@ public class OceanSpawn extends Requirement {
|
||||
public boolean matches(int x, int y, int z) {
|
||||
TerraWorld tw = TerraWorld.getWorld(getWorld());
|
||||
UserDefinedBiome b = (UserDefinedBiome) tw.getGrid().getBiome(x, z, GenerationPhase.POPULATE);
|
||||
BiomeConfig c = tw.getConfig().getBiome(b);
|
||||
BiomeConfig c = b.getConfig();
|
||||
if(y > c.getOcean().getSeaLevel()) return false;
|
||||
return b.getGenerator().getNoise(getNoise(), getWorld(), x, y, z) <= 0;
|
||||
int yf = (int) (y - ((WorldGenerator) b.getGenerator()).getElevation(x, z));
|
||||
return b.getGenerator().getNoise(getNoise(), getWorld(), x, yf, z) <= 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,15 +2,14 @@ package com.dfsek.terra.util;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.polydev.gaea.util.FastRandom;
|
||||
import org.polydev.gaea.world.palette.Palette;
|
||||
import org.polydev.gaea.world.palette.RandomPalette;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
public final class DataUtil {
|
||||
public static final BlockData STONE = Material.STONE.createBlockData();
|
||||
public static final BlockData SNOW = Material.SNOW.createBlockData();
|
||||
public static final BlockData WATER = Material.WATER.createBlockData();
|
||||
public static final BlockData AIR = Material.AIR.createBlockData();
|
||||
public static final Palette<BlockData> BLANK_PALETTE = new RandomPalette<BlockData>(new Random(2403)).add(AIR, 1);
|
||||
public static final Palette<BlockData> BLANK_PALETTE = new RandomPalette<BlockData>(new FastRandom(2403)).add(AIR, 1);
|
||||
}
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
package com.dfsek.terra.util;
|
||||
|
||||
import com.dfsek.terra.config.lang.LangUtil;
|
||||
import io.papermc.lib.PaperLib;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.util.logging.Level;
|
||||
import static io.papermc.lib.PaperLib.suggestPaper;
|
||||
|
||||
public final class PaperUtil {
|
||||
public static void checkPaper(JavaPlugin main) {
|
||||
Bukkit.getScheduler().scheduleSyncDelayedTask(main, () -> {
|
||||
if(!PaperLib.isPaper()) {
|
||||
LangUtil.log("use-paper", Level.WARNING);
|
||||
suggestPaper(main);
|
||||
}
|
||||
}, 100L);
|
||||
}
|
||||
|
||||
11
src/main/java/com/dfsek/terra/util/PopulationUtil.java
Normal file
11
src/main/java/com/dfsek/terra/util/PopulationUtil.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package com.dfsek.terra.util;
|
||||
|
||||
import org.bukkit.Chunk;
|
||||
import org.polydev.gaea.math.MathUtil;
|
||||
import org.polydev.gaea.util.FastRandom;
|
||||
|
||||
public final class PopulationUtil {
|
||||
public static FastRandom getRandom(Chunk c) {
|
||||
return new FastRandom(MathUtil.getCarverChunkSeed(c.getX(), c.getZ(), c.getWorld().getSeed()));
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class TagUtil {
|
||||
public final class TagUtil {
|
||||
private static final Map<String, Set<Material>> tagMap;
|
||||
|
||||
static {
|
||||
|
||||
118
src/main/java/com/dfsek/terra/util/hash/HashIntrinsic.java
Normal file
118
src/main/java/com/dfsek/terra/util/hash/HashIntrinsic.java
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
Copyright 2009 Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
|
||||
retains certain rights in this software.
|
||||
|
||||
BSD Open Source License.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of Sandia National Laboratories nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.util.hash;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public abstract class HashIntrinsic implements Serializable {
|
||||
public static final int FLOAT_EXP_BIT_MASK = 2139095040;
|
||||
public static final int FLOAT_SIGNIF_BIT_MASK = 8388607;
|
||||
public static final long DOUBLE_EXP_BIT_MASK = 9218868437227405312L;
|
||||
public static final long DOUBLE_SIGNIF_BIT_MASK = 4503599627370495L;
|
||||
protected static final int DEFAULT_INITIAL_CAPACITY = 16;
|
||||
protected static final int MAXIMUM_CAPACITY = 1073741824;
|
||||
protected static final float DEFAULT_LOAD_FACTOR = 0.75F;
|
||||
private static final long serialVersionUID = 8058099372006904458L;
|
||||
protected int size;
|
||||
protected int threshold;
|
||||
protected float loadFactor;
|
||||
protected int capMinus1;
|
||||
|
||||
protected HashIntrinsic(int initialCapacity, float loadFactor) {
|
||||
if(initialCapacity <= 0) {
|
||||
throw new IllegalArgumentException("Illegal initial capacity: " + initialCapacity);
|
||||
} else if(!(loadFactor <= 0.0F) && !Float.isNaN(loadFactor)) {
|
||||
if(initialCapacity > 1073741824) {
|
||||
initialCapacity = 1073741824;
|
||||
}
|
||||
|
||||
int capacity;
|
||||
for(capacity = 1; capacity < initialCapacity; capacity <<= 1) {
|
||||
}
|
||||
|
||||
this.capMinus1 = capacity - 1;
|
||||
this.loadFactor = loadFactor;
|
||||
this.threshold = (int) ((float) capacity * loadFactor);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Illegal load factor: " + loadFactor);
|
||||
}
|
||||
}
|
||||
|
||||
protected static int hashCodeLong(long value) {
|
||||
return (int) (value ^ value >>> 32);
|
||||
}
|
||||
|
||||
protected static int hashCodeFloat(float value) {
|
||||
return floatToIntBits(value);
|
||||
}
|
||||
|
||||
protected static int hashCodeDouble(double value) {
|
||||
long bits = doubleToLongBits(value);
|
||||
return (int) (bits ^ bits >>> 32);
|
||||
}
|
||||
|
||||
public static int floatToIntBits(float value) {
|
||||
int result = Float.floatToRawIntBits(value);
|
||||
if((result & 2139095040) == 2139095040 && (result & 8388607) != 0) {
|
||||
result = 2143289344;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static long doubleToLongBits(double value) {
|
||||
long result = Double.doubleToRawLongBits(value);
|
||||
if((result & 9218868437227405312L) == 9218868437227405312L && (result & 4503599627370495L) != 0L) {
|
||||
result = 9221120237041090560L;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected static int tableIndex(int hc, int lm1) {
|
||||
hc ^= hc >>> 20 ^ hc >>> 12;
|
||||
hc ^= hc >>> 7 ^ hc >>> 4;
|
||||
return hc & lm1;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return this.size;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return this.size == 0;
|
||||
}
|
||||
|
||||
public abstract void clear();
|
||||
}
|
||||
291
src/main/java/com/dfsek/terra/util/hash/HashMapDoubleDouble.java
Normal file
291
src/main/java/com/dfsek/terra/util/hash/HashMapDoubleDouble.java
Normal file
@@ -0,0 +1,291 @@
|
||||
/*
|
||||
Copyright 2009 Sandia Corporation. Under the terms of Contract
|
||||
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
|
||||
retains certain rights in this software.
|
||||
|
||||
BSD Open Source License.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of Sandia National Laboratories nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.dfsek.terra.util.hash;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
public class HashMapDoubleDouble extends HashIntrinsic {
|
||||
private static final long serialVersionUID = 2109458761298324234L;
|
||||
private HashMapDoubleDouble.Entry[] table;
|
||||
|
||||
public HashMapDoubleDouble(int initialCapacity, float loadFactor) {
|
||||
super(initialCapacity, loadFactor);
|
||||
this.table = this.createTable(this.capMinus1 + 1);
|
||||
}
|
||||
|
||||
public HashMapDoubleDouble(int initialCapacity) {
|
||||
this(initialCapacity, 0.75F);
|
||||
}
|
||||
|
||||
public HashMapDoubleDouble() {
|
||||
this(16, 0.75F);
|
||||
}
|
||||
|
||||
public final boolean contains(double key) {
|
||||
int i = tableIndex(hashCodeDouble(key), this.capMinus1);
|
||||
|
||||
for(HashMapDoubleDouble.Entry e = this.table[i]; e != null; e = e.next) {
|
||||
if(e.key == key) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean containsValue(double value) {
|
||||
for(int i = 0; i < this.table.length; ++i) {
|
||||
for(HashMapDoubleDouble.Entry e = this.table[i]; e != null; e = e.next) {
|
||||
if(value == e.value) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public double get(double key) {
|
||||
int i = tableIndex(hashCodeDouble(key), this.capMinus1);
|
||||
|
||||
for(HashMapDoubleDouble.Entry e = this.table[i]; e != null; e = e.next) {
|
||||
if(key == e.key) {
|
||||
return e.value;
|
||||
}
|
||||
}
|
||||
|
||||
return 4.9E-324D;
|
||||
}
|
||||
|
||||
public HashMapDoubleDouble.Entry getEntry(double key) {
|
||||
int i = tableIndex(hashCodeDouble(key), this.capMinus1);
|
||||
|
||||
for(HashMapDoubleDouble.Entry e = this.table[i]; e != null; e = e.next) {
|
||||
if(key == e.key) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public double put(double key, double value) {
|
||||
int i = tableIndex(hashCodeDouble(key), this.capMinus1);
|
||||
|
||||
for(HashMapDoubleDouble.Entry e = this.table[i]; e != null; e = e.next) {
|
||||
if(key == e.key) {
|
||||
double oldValue = e.value;
|
||||
e.value = value;
|
||||
return oldValue;
|
||||
}
|
||||
}
|
||||
|
||||
this.addEntry(key, value, i);
|
||||
return 4.9E-324D;
|
||||
}
|
||||
|
||||
private void addEntry(double key, double value, int index) {
|
||||
HashMapDoubleDouble.Entry e = this.table[index];
|
||||
this.table[index] = new HashMapDoubleDouble.Entry(key, value, e);
|
||||
if(this.size++ >= this.threshold) {
|
||||
this.resize(2 * this.table.length);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void resize(int newCapacity) {
|
||||
int oldCapacity = this.table.length;
|
||||
if(oldCapacity == 1073741824) {
|
||||
this.threshold = 2147483647;
|
||||
} else {
|
||||
HashMapDoubleDouble.Entry[] newTable = this.createTable(newCapacity);
|
||||
this.capMinus1 = newCapacity - 1;
|
||||
this.transfer(newTable);
|
||||
this.table = newTable;
|
||||
this.threshold = (int) ((float) newCapacity * this.loadFactor);
|
||||
}
|
||||
}
|
||||
|
||||
private void transfer(HashMapDoubleDouble.Entry[] newTable) {
|
||||
for(int j = 0; j < this.table.length; ++j) {
|
||||
HashMapDoubleDouble.Entry e = this.table[j];
|
||||
if(e != null) {
|
||||
this.table[j] = null;
|
||||
|
||||
HashMapDoubleDouble.Entry next;
|
||||
do {
|
||||
next = e.next;
|
||||
int i = tableIndex(hashCodeDouble(e.key), this.capMinus1);
|
||||
e.next = newTable[i];
|
||||
newTable[i] = e;
|
||||
e = next;
|
||||
} while(next != null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final HashMapDoubleDouble.Entry remove(double key) {
|
||||
int i = tableIndex(hashCodeDouble(key), this.capMinus1);
|
||||
HashMapDoubleDouble.Entry prev = this.table[i];
|
||||
|
||||
HashMapDoubleDouble.Entry e;
|
||||
HashMapDoubleDouble.Entry next;
|
||||
for(e = prev; e != null; e = next) {
|
||||
next = e.next;
|
||||
if(key == e.key) {
|
||||
--this.size;
|
||||
if(prev == e) {
|
||||
this.table[i] = next;
|
||||
} else {
|
||||
prev.next = next;
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
prev = e;
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
for(int i = 0; i < this.table.length; ++i) {
|
||||
this.table[i] = null;
|
||||
}
|
||||
|
||||
this.size = 0;
|
||||
}
|
||||
|
||||
private HashMapDoubleDouble.Entry[] createTable(int capacity) {
|
||||
return new HashMapDoubleDouble.Entry[capacity];
|
||||
}
|
||||
|
||||
public long memoryEstimate(int ptrsize) {
|
||||
return (long) ptrsize * (long) (this.capMinus1 + this.size + 1) + (long) (this.size * 64 / 4);
|
||||
}
|
||||
|
||||
public HashMapDoubleDouble.Iterator iterator() {
|
||||
return new HashMapDoubleDouble.Iterator();
|
||||
}
|
||||
|
||||
public static class Entry implements Serializable {
|
||||
private static final long serialVersionUID = 7972173983741231238L;
|
||||
private final double key;
|
||||
private double value;
|
||||
private HashMapDoubleDouble.Entry next;
|
||||
|
||||
public Entry(double key, double val, HashMapDoubleDouble.Entry n) {
|
||||
this.key = key;
|
||||
this.value = val;
|
||||
this.next = n;
|
||||
}
|
||||
|
||||
public final double getKey() {
|
||||
return this.key;
|
||||
}
|
||||
|
||||
public final double getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public final double setValue(double newValue) {
|
||||
double oldValue = this.value;
|
||||
this.value = newValue;
|
||||
return oldValue;
|
||||
}
|
||||
|
||||
public final boolean equals(Object o) {
|
||||
HashMapDoubleDouble.Entry e = (HashMapDoubleDouble.Entry) o;
|
||||
return this.key == e.key && this.value == e.value;
|
||||
}
|
||||
|
||||
public final String toString() {
|
||||
return this.key + " = " + this.value;
|
||||
}
|
||||
|
||||
public final int hashCode() {
|
||||
return hashCodeDouble(key) + hashCodeDouble(value);
|
||||
}
|
||||
}
|
||||
|
||||
public class Iterator {
|
||||
HashMapDoubleDouble.Entry next;
|
||||
int index;
|
||||
HashMapDoubleDouble.Entry current;
|
||||
|
||||
Iterator() {
|
||||
if(HashMapDoubleDouble.this.size > 0) {
|
||||
while(this.index < HashMapDoubleDouble.this.table.length && (this.next = HashMapDoubleDouble.this.table[this.index++]) == null) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final boolean hasNext() {
|
||||
return this.next != null;
|
||||
}
|
||||
|
||||
public HashMapDoubleDouble.Entry nextEntry() {
|
||||
HashMapDoubleDouble.Entry e = this.next;
|
||||
if(e == null) {
|
||||
throw new NoSuchElementException();
|
||||
} else {
|
||||
if((this.next = e.next) == null) {
|
||||
while(this.index < HashMapDoubleDouble.this.table.length && (this.next = HashMapDoubleDouble.this.table[this.index++]) == null) {
|
||||
}
|
||||
}
|
||||
|
||||
this.current = e;
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
public double next() {
|
||||
return this.nextEntry().value;
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
if(this.current == null) {
|
||||
throw new IllegalStateException();
|
||||
} else {
|
||||
double k = this.current.key;
|
||||
this.current = null;
|
||||
HashMapDoubleDouble.this.remove(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@ package com.dfsek.terra.util.structure;
|
||||
|
||||
import com.dfsek.terra.procgen.math.Vector2;
|
||||
import com.dfsek.terra.structure.Rotation;
|
||||
import net.jafama.FastMath;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.Directional;
|
||||
@@ -11,7 +12,7 @@ import org.bukkit.block.data.Rail;
|
||||
import org.bukkit.block.data.Rotatable;
|
||||
import org.bukkit.block.data.type.RedstoneWire;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
|
||||
public final class RotationUtil {
|
||||
@@ -107,7 +108,7 @@ public final class RotationUtil {
|
||||
* @return BlockFace represented by integer.
|
||||
*/
|
||||
public static BlockFace fromRotation(int r) {
|
||||
switch(Math.floorMod(r, 16)) {
|
||||
switch(FastMath.floorMod(r, 16)) {
|
||||
case 0:
|
||||
return BlockFace.NORTH;
|
||||
case 1:
|
||||
@@ -251,7 +252,7 @@ public final class RotationUtil {
|
||||
((Directional) data).setFacing(rt);
|
||||
} else if(data instanceof MultipleFacing) {
|
||||
MultipleFacing mfData = (MultipleFacing) data;
|
||||
Map<BlockFace, Boolean> faces = new HashMap<>();
|
||||
Map<BlockFace, Boolean> faces = new EnumMap<>(BlockFace.class);
|
||||
for(BlockFace f : mfData.getAllowedFaces()) {
|
||||
faces.put(f, mfData.hasFace(f));
|
||||
}
|
||||
@@ -265,7 +266,7 @@ public final class RotationUtil {
|
||||
org.bukkit.Axis newAxis = getRotatedAxis(((Orientable) data).getAxis(), r);
|
||||
((Orientable) data).setAxis(newAxis);
|
||||
} else if(data instanceof RedstoneWire) {
|
||||
Map<BlockFace, RedstoneWire.Connection> connections = new HashMap<>();
|
||||
Map<BlockFace, RedstoneWire.Connection> connections = new EnumMap<>(BlockFace.class);
|
||||
RedstoneWire rData = (RedstoneWire) data;
|
||||
for(BlockFace f : rData.getAllowedFaces()) {
|
||||
connections.put(f, rData.getFace(f));
|
||||
|
||||
@@ -3,6 +3,7 @@ data-save: PT6M
|
||||
language: "en_us"
|
||||
fail-type: SHUTDOWN
|
||||
dump-default: true
|
||||
cache-size: 8
|
||||
biome-search-resolution: 4
|
||||
cache-size: 384
|
||||
master-disable:
|
||||
caves: false
|
||||
@@ -1,3 +1,4 @@
|
||||
import net.jafama.FastMath;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.polydev.gaea.math.FastNoiseLite;
|
||||
|
||||
@@ -26,8 +27,8 @@ class DistributionTest {
|
||||
long l = System.nanoTime();
|
||||
for(int i = 0; i < 1000000; i++) {
|
||||
double n = noise.getNoise(0, i);
|
||||
max = Math.max(max, n);
|
||||
min = Math.min(min, n);
|
||||
max = FastMath.max(max, n);
|
||||
min = FastMath.min(min, n);
|
||||
numbers[normalize(n, attempts)]++;
|
||||
}
|
||||
long l2 = System.nanoTime() - l;
|
||||
@@ -36,8 +37,8 @@ class DistributionTest {
|
||||
l = System.nanoTime();
|
||||
for(int i = 0; i < 1000000; i++) {
|
||||
double n = noise.getNoise(0, i);
|
||||
max = Math.max(max, n);
|
||||
min = Math.min(min, n);
|
||||
max = FastMath.max(max, n);
|
||||
min = FastMath.min(min, n);
|
||||
}
|
||||
l2 = System.nanoTime() - l;
|
||||
System.out.println("Took " + (double) l2 / 1000000 + "ms (" + ((double) l2 / 1000000) + "ns per.");
|
||||
@@ -61,22 +62,22 @@ class DistributionTest {
|
||||
int end = normalMap.length - 1;
|
||||
while(start + 1 < end) {
|
||||
int mid = start + (end - start) / 2;
|
||||
if (normalMap[mid] <= d) {
|
||||
if(normalMap[mid] <= d) {
|
||||
start = mid;
|
||||
} else {
|
||||
end = mid;
|
||||
}
|
||||
}
|
||||
double left = Math.abs(normalMap[start] - d);
|
||||
double right = Math.abs(normalMap[end] - d);
|
||||
if (left <= right) {
|
||||
double left = FastMath.abs(normalMap[start] - d);
|
||||
double right = FastMath.abs(normalMap[end] - d);
|
||||
if(left <= right) {
|
||||
return start * (num) / (normalMap.length);
|
||||
}
|
||||
return end * (num) / (normalMap.length);
|
||||
}
|
||||
|
||||
public static int normal(double d, int max) {
|
||||
double ranged = Math.max(0, Math.min((d + 1) / 2D, 1));
|
||||
double ranged = FastMath.max(0, FastMath.min((d + 1) / 2D, 1));
|
||||
return (int) (ranged * max);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import net.jafama.FastMath;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.polydev.gaea.math.FastNoiseLite;
|
||||
import org.polydev.gaea.util.GlueList;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -12,7 +14,7 @@ class LookupGenerator {
|
||||
static void main(String[] args) throws InterruptedException {
|
||||
int dist = 4096;
|
||||
|
||||
List<Double> vals = new ArrayList<>();
|
||||
List<Double> vals = new GlueList<>();
|
||||
FastNoiseLite noise = new FastNoiseLite();
|
||||
noise.setNoiseType(FastNoiseLite.NoiseType.OpenSimplex2);
|
||||
noise.setFrequency(0.02f);
|
||||
@@ -25,10 +27,10 @@ class LookupGenerator {
|
||||
|
||||
int workerAmount = 16;
|
||||
|
||||
List<Worker> workers = new ArrayList<>();
|
||||
List<Worker> workers = new GlueList<>();
|
||||
|
||||
for(int i = 0; i < workerAmount; i++) {
|
||||
workers.add(new Worker(new ArrayList<>(), 5000000, noise));
|
||||
workers.add(new Worker(new GlueList<>(), 5000000, noise));
|
||||
}
|
||||
|
||||
for(Worker w : workers) {
|
||||
@@ -98,6 +100,12 @@ class LookupGenerator {
|
||||
return lookup.length - 1;
|
||||
}
|
||||
|
||||
public static int normalize(double i, int n) {
|
||||
i *= 1.42; // Magic simplex value (sqrt(2) plus a little)
|
||||
i = FastMath.min(FastMath.max(i, -1), 1);
|
||||
return FastMath.min((int) FastMath.floor((i + 1) * ((double) n / 2)), n - 1);
|
||||
}
|
||||
|
||||
private static class Worker extends Thread {
|
||||
private final List<Double> l;
|
||||
private final int searches;
|
||||
@@ -120,5 +128,9 @@ class LookupGenerator {
|
||||
public List<Double> getResult() {
|
||||
return l;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return "Generating values. " + l.size() + "/" + searches + " (" + ((long) l.size() * 100L) / searches + "%)";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
52
src/test/java/NoiseTest.java
Normal file
52
src/test/java/NoiseTest.java
Normal file
@@ -0,0 +1,52 @@
|
||||
import com.dfsek.terra.generation.config.NoiseBuilder;
|
||||
import com.dfsek.terra.math.NoiseFunction2;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import parsii.eval.Expression;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class NoiseTest {
|
||||
@Test
|
||||
public void noise() {
|
||||
NoiseFunction2 noiseFunction = new NoiseFunction2(12345, new NoiseBuilder());
|
||||
System.out.println("Cache:");
|
||||
int a = 0;
|
||||
for(int i = 0; i < 200; i++) {
|
||||
long l = System.nanoTime();
|
||||
for(int j = 0; j < 1000; j++) {
|
||||
for(int x = 0; x < 4; x++) {
|
||||
for(int y = 0; y < 64; y++) {
|
||||
for(int z = 0; z < 4; z++) {
|
||||
noiseFunction.eval(Arrays.asList(get(j * 16 + (x * 4)), get(i * 16 + (z * 4))));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
double n = System.nanoTime() - l;
|
||||
System.out.print((long) n / 1000000 + "ms" + ((a % 10 == 0) ? "\n" : " "));
|
||||
a++;
|
||||
}
|
||||
System.out.println();
|
||||
System.out.println();
|
||||
System.out.println("No Cache:");
|
||||
for(int i = 0; i < 200; i++) {
|
||||
long l = System.nanoTime();
|
||||
for(int j = 0; j < 1000; j++) {
|
||||
for(int x = 0; x < 4; x++) {
|
||||
for(int y = 0; y < 64; y++) {
|
||||
for(int z = 0; z < 4; z++) {
|
||||
noiseFunction.evalNoCache(Arrays.asList(get(j * 16 + (x * 4)), get(i * 16 + (z * 4))));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
double n = System.nanoTime() - l;
|
||||
System.out.print((long) n / 1000000 + "ms" + ((a % 10 == 0) ? "\n" : " "));
|
||||
a++;
|
||||
}
|
||||
}
|
||||
|
||||
private Expression get(double val) {
|
||||
return () -> val;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user