Compare commits

..

9 Commits

Author SHA1 Message Date
Zoë Gidiere 0efb0916e6 Initial Bukkit Biome Config 2023-11-17 16:16:18 -07:00
Zoë Gidiere 82fbf796da Refractor BiomeUtil 2023-11-17 15:26:53 -07:00
Zoë Gidiere 94bf67d09d fix dev env by having fabric api at runtime 2023-11-17 14:57:14 -07:00
Zoë Gidiere f86d4bae32 remove old bukkit versions 2023-11-17 13:22:10 -07:00
Zoë Gidiere c7cecaebe6 Merge remote-tracking branch 'origin/dev/biome2' into ver/6.5.0 2023-11-17 13:21:39 -07:00
Zoë Gidiere 70b1c3bbf3 warning 2023-09-30 12:06:21 -06:00
Zoë Gidiere e9b145b6c3 unbreaking via deprecation 2023-09-30 11:50:15 -06:00
Zoë 99d848b394 UX tweaks to biome config 2023-09-30 11:42:05 -06:00
Zoë Gidiere 4828d51da4 Merge branch 'dev/physics' into dev/biome2 2023-09-30 11:38:18 -06:00
156 changed files with 1443 additions and 2193 deletions
+12 -6
View File
@@ -1,13 +1,19 @@
# Global owners, automatically request review when pull request is submitted
* @dfsek @solonovamax @duplexsystem @Astrashh @justaureus
* @dfsek @solonovamax
# Platforms
/platforms/ @dfsek @solonovamax @duplexsystem @justaureus
## dfsek wrote the majority of the platform impls
/platforms/bukkit/ @dfsek
/platforms/fabric/ @dfsek
/platforms/forge/ @dfsek
/platforms/sponge/ @dfsek
## solonovamax is working on the region generator (unless duplexsystem takes it over)
/platforms/region/ @solonovamax
# Common
/common/ @dfsek @solonovamax @duplexsystem @Astrashh
/common/ @dfsek @solonovamax
# Gradle Stuff
/buildSrc/ @dfsek @solonovamax @duplexsystem
*.gradle.kts @dfsek @solonovamax @duplexsystem
/gradle/ @dfsek @solonovamax @duplexsystem
## Most gradle stuff was written by solonovamax
/buildSrc/ @solonovamax
*.gradle.kts @solonovamax
-47
View File
@@ -1,47 +0,0 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow will build a package using Gradle and then publish it to GitHub packages when a release is created
# For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#Publishing-using-gradle
name: Gradle Build
on: [ pull_request ]
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
- name: Set up JDK 21
uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93
with:
java-version: '21'
distribution: 'temurin'
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
settings-path: ${{ github.workspace }} # location for the settings.xml file
- uses: burrunan/gradle-cache-action@03c71a8ba93d670980695505f48f49daf43704a6
name: Build Terra
with:
# Specifies arguments for Gradle execution
# If arguments is missing or empty, then Gradle is not executed
arguments: build
# arguments can be multi-line for better readability
# arguments: |
# --no-paralell
# build
# -x test
# Gradle version to use for execution:
# wrapper (default), current, rc, nightly, release-nightly, or
# versions like 6.6 (see https://services.gradle.org/versions/all)
gradle-version: wrapper
# Properties are passed as -Pname=value
properties: |
kotlin.js.compiler=ir
kotlin.parallel.tasks.in.project=true
-2
View File
@@ -249,5 +249,3 @@ nbdist/
platforms/**/run/**
#Vale Config File
**/.vale.ini
+1 -2
View File
@@ -15,7 +15,6 @@ allprojects {
tasks.withType<JavaCompile>().configureEach {
options.isFork = true
options.isIncremental = true
options.release.set(21)
}
tasks.withType<Test>().configureEach {
@@ -45,7 +44,7 @@ afterEvaluate {
}
project(":platforms:bukkit:common").configureDistribution()
forSubProjects(":common:addons") {
apply(plugin = "com.gradleup.shadow")
apply(plugin = "com.github.johnrengelman.shadow")
tasks.named("build") {
finalizedBy(tasks.named("shadowJar"))
+7 -7
View File
@@ -9,18 +9,18 @@ repositories {
maven("https://repo.codemc.org/repository/maven-public") {
name = "CodeMC"
}
maven("https://repo.papermc.io/repository/maven-public/") {
maven("https://papermc.io/repo/repository/maven-public/") {
name = "PaperMC"
}
}
dependencies {
//TODO Allow pulling from Versions.kt
implementation("com.gradleup.shadow", "shadow-gradle-plugin", "8.3.1")
implementation("io.papermc.paperweight.userdev", "io.papermc.paperweight.userdev.gradle.plugin", "1.7.2")
implementation("com.github.johnrengelman", "shadow", "8.1.1")
implementation("io.papermc.paperweight.userdev", "io.papermc.paperweight.userdev.gradle.plugin", "1.5.6")
implementation("org.ow2.asm", "asm", "9.7")
implementation("org.ow2.asm", "asm-tree", "9.7")
implementation("com.dfsek.tectonic", "common", "4.2.1")
implementation("org.yaml", "snakeyaml", "2.3")
implementation("org.ow2.asm", "asm", "9.5")
implementation("org.ow2.asm", "asm-tree", "9.5")
implementation("com.dfsek.tectonic", "common", "4.2.0")
implementation("org.yaml", "snakeyaml", "2.2")
}
+2 -2
View File
@@ -18,7 +18,7 @@ fun Project.addonDir(dir: File, task: Task) {
matchingAddons(dir) {
it.name.startsWith("Terra-") // Assume everything that starts with Terra- is a core addon.
}.forEach {
logger.info("Deleting old addon: " + it.absolutePath)
println("Deleting old addon: " + it.absolutePath)
it.delete()
}
forSubProjects(":common:addons") {
@@ -29,7 +29,7 @@ fun Project.addonDir(dir: File, task: Task) {
val base = "${jar.archiveBaseName.get()}-${version}"
logger.info("Copying addon ${jar.archiveFileName.get()} to ${target.absolutePath}. Base name: $base")
println("Copying addon ${jar.archiveFileName.get()} to ${target.absolutePath}. Base name: $base")
jar.archiveFile.orNull?.asFile?.copyTo(target)
}
@@ -22,8 +22,8 @@ fun Project.configureCompilation() {
apply<TectonicDocPlugin>()
configure<JavaPluginExtension> {
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
tasks.withType<JavaCompile> {
+8 -8
View File
@@ -36,7 +36,7 @@ fun Project.configureDependencies() {
maven("https://repo.codemc.org/repository/maven-public") {
name = "CodeMC"
}
maven("https://repo.papermc.io/repository/maven-public/") {
maven("https://papermc.io/repo/repository/maven-public/") {
name = "PaperMC"
}
maven("https://files.minecraftforge.net/maven/") {
@@ -48,17 +48,17 @@ fun Project.configureDependencies() {
maven("https://jitpack.io") {
name = "JitPack"
}
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") {
name = "Sonatype Snapshots"
maven("https://nexuslite.gcnt.net/repos/other/") {
name = "GCNT"
}
}
dependencies {
testImplementation("org.junit.jupiter", "junit-jupiter-api", Versions.Libraries.Internal.junit)
testImplementation("org.junit.jupiter", "junit-jupiter-engine", Versions.Libraries.Internal.junit)
compileOnly("org.jetbrains", "annotations", Versions.Libraries.Internal.jetBrainsAnnotations)
testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.0")
testImplementation("org.junit.jupiter:junit-jupiter-engine:5.7.0")
compileOnly("org.jetbrains:annotations:23.0.0")
compileOnly("com.google.guava", "guava", Versions.Libraries.Internal.guava)
testImplementation("com.google.guava", "guava", Versions.Libraries.Internal.guava)
compileOnly("com.google.guava:guava:30.0-jre")
testImplementation("com.google.guava:guava:30.0-jre")
}
}
@@ -21,14 +21,13 @@ import kotlin.io.path.exists
fun Project.configureDistribution() {
apply(plugin = "com.gradleup.shadow")
apply(plugin = "com.github.johnrengelman.shadow")
val downloadDefaultPacks = tasks.create("downloadDefaultPacks") {
group = "terra"
doFirst {
file("${buildDir}/resources/main/packs/").deleteRecursively()
val defaultPackUrl =
URL("https://github.com/PolyhedralDev/TerraOverworldConfig/releases/download/" + Versions.Terra.overworldConfig + "/default.zip")
val defaultPackUrl = URL("https://github.com/PolyhedralDev/TerraOverworldConfig/releases/download/latest/default.zip")
downloadPack(defaultPackUrl, project)
}
}
@@ -54,7 +53,7 @@ fun Project.configureDistribution() {
forSubProjects(":common:addons") {
val jar = getJarTask()
logger.info("Packaging addon ${jar.archiveFileName.get()} to $dest. size: ${jar.archiveFile.get().asFile.length() / 1024}KB")
println("Packaging addon ${jar.archiveFileName.get()} to $dest. size: ${jar.archiveFile.get().asFile.length() / 1024}KB")
val boot = if (extra.has("bootstrap") && extra.get("bootstrap") as Boolean) "bootstrap/" else ""
val addonPath = fs.getPath("/addons/$boot${jar.archiveFileName.get()}")
+2 -2
View File
@@ -42,10 +42,10 @@ fun preRelease(preRelease: Boolean) {
fun Project.versionProjects(project: String, version: String) {
forSubProjects(project) {
this.version = version
logger.info("Setting version of $path to $version")
println("Setting version of $path to $version")
}
project(project).version = version
logger.info("Setting version of $project to $version")
println("Setting version of $project to $version")
}
fun Project.version(version: String): String {
+32 -39
View File
@@ -1,35 +1,26 @@
object Versions {
object Terra {
const val overworldConfig = "v1.3.4"
}
object Libraries {
const val tectonic = "4.2.1"
const val paralithic = "0.7.1"
const val strata = "1.3.2"
const val cloud = "2.0.0"
const val cloudPaper = "2.0.0-beta.10"
const val cloudFabric = "2.0.0-beta.9"
const val cloud = "1.8.4"
const val caffeine = "3.1.8"
const val slf4j = "2.0.9"
const val log4j_slf4j_impl = "2.20.0"
const val slf4j = "2.0.16"
object Internal {
const val shadow = "8.3.1"
const val apacheText = "1.12.0"
const val apacheIO = "2.16.1"
const val guava = "33.3.0-jre"
const val asm = "9.7"
const val snakeYml = "2.3"
const val jetBrainsAnnotations = "24.1.0"
const val junit = "5.11.0"
const val shadow = "8.1.1"
const val apacheText = "1.10.0"
const val apacheIO = "2.14.0"
const val guava = "32.1.3-jre"
const val asm = "9.5"
const val snakeYml = "2.2"
}
}
object Fabric {
const val fabricAPI = "0.104.0+${Mod.minecraft}"
const val fabricAPI = "0.90.0+${Mod.minecraft}"
}
//
// object Quilt {
@@ -38,30 +29,32 @@ object Versions {
// }
object Mod {
const val mixin = "0.15.3+mixin.0.8.7"
const val mixin = "0.12.5+mixin.0.8.5"
const val minecraft = "1.21.1"
const val yarn = "$minecraft+build.3"
const val fabricLoader = "0.16.5"
const val minecraft = "1.20.2"
const val yarn = "$minecraft+build.4"
const val fabricLoader = "0.14.23"
const val architecuryLoom = "1.7.413"
const val architecturyPlugin = "3.4.159"
const val architecuryLoom = "1.3.357"
const val architecturyPlugin = "3.4.146"
const val loomVineflower = "1.11.0"
}
object Forge {
const val forge = "${Mod.minecraft}-48.0.13"
const val burningwave = "12.63.0"
}
//
// object Forge {
// const val forge = "${Mod.minecraft}-48.0.13"
// const val burningwave = "12.63.0"
// }
object Bukkit {
const val minecraft = "1.21.1"
const val paperBuild = "$minecraft-R0.1-20240917.151311-80"
const val paper = paperBuild
const val paperLib = "1.0.8"
const val reflectionRemapper = "0.1.1"
const val paperDevBundle = paperBuild
const val runPaper = "2.3.1"
const val paperWeight = "1.7.2"
const val paper = "1.18.2-R0.1-SNAPSHOT"
const val paperLib = "1.0.5"
const val foliaLib = "0.2.5"
const val minecraft = "1.20.2"
const val reflectionRemapper = "0.1.0-SNAPSHOT"
const val paperDevBundle = "1.20.2-R0.1-SNAPSHOT"
const val runPaper = "2.2.0"
const val paperWeight = "1.5.6"
}
//
@@ -73,6 +66,6 @@ object Versions {
//
object CLI {
const val nbt = "6.1"
const val logback = "1.5.8"
const val logback = "1.4.11"
}
}
@@ -82,7 +82,7 @@ abstract class GenerateDocsTask : DefaultTask() {
}
template.add(keyName.toString(), description.toString().ifBlank {
logger.info("No description provided for field " + field.name + " in class " + name)
println("No description provided for field " + field.name + " in class " + name)
"*No description provided.*"
})
}
@@ -1,9 +1,9 @@
package com.dfsek.terra.addons.biome.extrusion.api;
import com.dfsek.terra.api.world.biome.Biome;
import java.util.Collection;
import com.dfsek.terra.api.world.biome.Biome;
public interface Extrusion {
Biome extrude(Biome original, int x, int y, int z, long seed);
@@ -1,9 +1,5 @@
package com.dfsek.terra.addons.biome.extrusion.extrusions;
import java.util.Collection;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import com.dfsek.terra.addons.biome.extrusion.api.Extrusion;
import com.dfsek.terra.addons.biome.extrusion.api.ReplaceableBiome;
import com.dfsek.terra.addons.biome.query.api.BiomeQueries;
@@ -12,6 +8,10 @@ import com.dfsek.terra.api.util.Range;
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
import com.dfsek.terra.api.world.biome.Biome;
import java.util.Collection;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
* Sets biomes at locations based on a sampler.
@@ -7,13 +7,13 @@
package com.dfsek.terra.addons.biome.image.v2;
import java.util.Optional;
import com.dfsek.terra.addons.image.colorsampler.ColorSampler;
import com.dfsek.terra.addons.image.converter.ColorConverter;
import com.dfsek.terra.api.world.biome.Biome;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import java.util.Optional;
public class ImageBiomeProvider implements BiomeProvider {
private final int resolution;
@@ -29,7 +29,7 @@ public class BiomePipelineTemplate implements ObjectTemplate<BiomeProvider> {
@Default
@Description("""
The resolution at which to sample biomes.
Larger values are quadratically faster, but produce lower quality results.
For example, a value of 3 would sample every 3 blocks.""")
protected @Meta int resolution = 1;
@@ -14,8 +14,7 @@ public class BiomeChunkImpl implements BiomeChunk {
private final SeededVector worldOrigin;
private final int chunkOriginArrayIndex;
private final int worldCoordinateScale;
private final int size;
private PipelineBiome[] biomes;
private PipelineBiome[][] biomes;
public BiomeChunkImpl(SeededVector worldOrigin, PipelineImpl pipeline) {
@@ -23,14 +22,14 @@ public class BiomeChunkImpl implements BiomeChunk {
this.chunkOriginArrayIndex = pipeline.getChunkOriginArrayIndex();
this.worldCoordinateScale = pipeline.getResolution();
this.size = pipeline.getArraySize();
int size = pipeline.getArraySize();
int expanderCount = pipeline.getExpanderCount();
int expansionsApplied = 0;
// Allocate working arrays
this.biomes = new PipelineBiome[size * size];
PipelineBiome[] lookupArray = new PipelineBiome[size * size];
this.biomes = new PipelineBiome[size][size];
PipelineBiome[][] lookupArray = new PipelineBiome[size][size];
// A second lookup array is required such that stage application doesn't affect lookups, otherwise application may cascade
// Construct working grid
@@ -44,7 +43,7 @@ public class BiomeChunkImpl implements BiomeChunk {
for(int gridZ = 0; gridZ < gridSize; gridZ++) {
int xIndex = gridOrigin + gridX * gridInterval;
int zIndex = gridOrigin + gridZ * gridInterval;
biomes[(xIndex * size) + zIndex] = pipeline.getSource().get(worldOrigin.seed(), xIndexToWorldCoordinate(xIndex),
biomes[xIndex][zIndex] = pipeline.getSource().get(worldOrigin.seed(), xIndexToWorldCoordinate(xIndex),
zIndexToWorldCoordinate(zIndex));
}
}
@@ -66,7 +65,7 @@ public class BiomeChunkImpl implements BiomeChunk {
// Cycle arrays, the previously populated array is swapped to be used for lookups, and the result of the stage application
// overwrites the previous lookup array. This saves having to allocate a new array copy each time
PipelineBiome[] tempArray = biomes;
PipelineBiome[][] tempArray = biomes;
biomes = lookupArray;
lookupArray = tempArray;
@@ -75,8 +74,7 @@ public class BiomeChunkImpl implements BiomeChunk {
for(int gridX = 0; gridX < gridSize; gridX = gridX + 1) {
int xIndex = gridOrigin + gridX * gridInterval;
int zIndex = gridOrigin + gridZ * gridInterval;
biomes[(xIndex * size) + zIndex] = stage.apply(
new ViewPoint(this, gridInterval, gridX, gridZ, xIndex, zIndex, lookupArray, size));
biomes[xIndex][zIndex] = stage.apply(new ViewPoint(this, gridInterval, gridX, gridZ, xIndex, zIndex, lookupArray));
}
}
}
@@ -135,7 +133,7 @@ public class BiomeChunkImpl implements BiomeChunk {
public PipelineBiome get(int xInChunk, int zInChunk) {
int xIndex = xInChunk + chunkOriginArrayIndex;
int zIndex = zInChunk + chunkOriginArrayIndex;
return biomes[(xIndex * size) + zIndex];
return biomes[xIndex][zIndex];
}
private int xIndexToWorldCoordinate(int xIndex) {
@@ -161,11 +159,10 @@ public class BiomeChunkImpl implements BiomeChunk {
private final int gridZ;
private final int xIndex;
private final int zIndex;
private final PipelineBiome[] lookupArray;
private final int size;
private final PipelineBiome[][] lookupArray;
private ViewPoint(BiomeChunkImpl chunk, int gridInterval, int gridX, int gridZ, int xIndex, int zIndex,
PipelineBiome[] lookupArray, int size) {
PipelineBiome[][] lookupArray) {
this.chunk = chunk;
this.gridInterval = gridInterval;
this.gridX = gridX;
@@ -173,14 +170,13 @@ public class BiomeChunkImpl implements BiomeChunk {
this.xIndex = xIndex;
this.zIndex = zIndex;
this.lookupArray = lookupArray;
this.size = size;
this.biome = lookupArray[(this.xIndex * this.size) + this.zIndex];
this.biome = lookupArray[xIndex][zIndex];
}
public PipelineBiome getRelativeBiome(int x, int z) {
int lookupXIndex = this.xIndex + x * gridInterval;
int lookupZIndex = this.zIndex + z * gridInterval;
return lookupArray[(lookupXIndex * this.size) + lookupZIndex];
return lookupArray[lookupXIndex][lookupZIndex];
}
public PipelineBiome getBiome() {
@@ -28,7 +28,7 @@ public class BiomePipelineTemplate extends BiomeProviderTemplate {
@Description("""
The initial size of biome chunks. This value must be at least 2.
<b>This is not the final size of biome chunks. Final chunks will be much larger</b>.
It is recommended to keep biome chunks' final size in the range of [50, 300]
to prevent performance issues. To calculate the size of biome chunks, simply
take initial-size and for each expand stage, multiply the running value by 2
@@ -22,7 +22,7 @@ public abstract class BiomeProviderTemplate implements ObjectTemplate<BiomeProvi
@Default
@Description("""
The resolution at which to sample biomes.
Larger values are quadratically faster, but produce lower quality results.
For example, a value of 3 would sample every 3 blocks.""")
protected @Meta int resolution = 1;
@@ -13,7 +13,6 @@ import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseProperties;
import com.dfsek.terra.addons.chunkgenerator.config.palette.BiomePaletteTemplate;
import com.dfsek.terra.addons.chunkgenerator.config.palette.slant.SlantLayerTemplate;
import com.dfsek.terra.addons.chunkgenerator.generation.NoiseChunkGenerator3D;
import com.dfsek.terra.addons.chunkgenerator.generation.math.SlantCalculationMethod;
import com.dfsek.terra.addons.chunkgenerator.palette.BiomePaletteInfo;
import com.dfsek.terra.addons.chunkgenerator.palette.slant.SlantHolder;
import com.dfsek.terra.addons.manifest.api.AddonInitializer;
@@ -46,8 +45,8 @@ public class NoiseChunkGenerator3DAddon implements AddonInitializer {
.priority(1000)
.then(event -> {
event.getPack().applyLoader(SlantCalculationMethod.class,
(type, o, loader, depthTracker) -> SlantCalculationMethod.valueOf((String) o));
event.getPack().applyLoader(SlantHolder.CalculationMethod.class,
(type, o, loader, depthTracker) -> SlantHolder.CalculationMethod.valueOf((String) o));
NoiseChunkGeneratorPackConfigTemplate config = event.loadTemplate(new NoiseChunkGeneratorPackConfigTemplate());
event.getPack().getContext().put(config);
@@ -58,8 +57,7 @@ public class NoiseChunkGenerator3DAddon implements AddonInitializer {
pack -> new NoiseChunkGenerator3D(pack, platform, config.getElevationBlend(),
config.getHorizontalRes(),
config.getVerticalRes(), noisePropertiesPropertyKey,
paletteInfoPropertyKey, config.getSlantCalculationMethod(),
config.isSlantPalettesEnabled()));
paletteInfoPropertyKey));
event.getPack()
.applyLoader(SlantHolder.Layer.class, SlantLayerTemplate::new);
})
@@ -4,7 +4,7 @@ import com.dfsek.tectonic.api.config.template.ConfigTemplate;
import com.dfsek.tectonic.api.config.template.annotations.Default;
import com.dfsek.tectonic.api.config.template.annotations.Value;
import com.dfsek.terra.addons.chunkgenerator.generation.math.SlantCalculationMethod;
import com.dfsek.terra.addons.chunkgenerator.palette.slant.SlantHolder;
import com.dfsek.terra.api.config.meta.Meta;
import com.dfsek.terra.api.properties.Properties;
@@ -24,11 +24,7 @@ public class NoiseChunkGeneratorPackConfigTemplate implements ConfigTemplate, Pr
@Value("slant.calculation-method")
@Default
private @Meta SlantCalculationMethod slantCalculationMethod = SlantCalculationMethod.Derivative;
@Value("slant.disable-palettes")
@Default
private @Meta boolean disableSlantPalettes = false;
private SlantHolder.@Meta CalculationMethod slantCalculationMethod = SlantHolder.CalculationMethod.Derivative;
public int getElevationBlend() {
return elevationBlend;
@@ -42,11 +38,7 @@ public class NoiseChunkGeneratorPackConfigTemplate implements ConfigTemplate, Pr
return verticalRes;
}
public SlantCalculationMethod getSlantCalculationMethod() {
public SlantHolder.CalculationMethod getSlantCalculationMethod() {
return slantCalculationMethod;
}
public boolean isSlantPalettesEnabled() {
return !disableSlantPalettes;
}
}
@@ -16,7 +16,6 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import com.dfsek.terra.addons.chunkgenerator.generation.math.SlantCalculationMethod;
import com.dfsek.terra.addons.chunkgenerator.palette.BiomePaletteInfo;
import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolder;
import com.dfsek.terra.addons.chunkgenerator.palette.slant.SlantHolder;
@@ -28,7 +27,7 @@ import com.dfsek.terra.api.world.chunk.generation.util.Palette;
public class BiomePaletteTemplate implements ObjectTemplate<BiomePaletteInfo> {
private final Platform platform;
private final SlantCalculationMethod slantCalculationMethod;
private final SlantHolder.CalculationMethod slantCalculationMethod;
@Value("slant")
@Default
@Description("The slant palettes to use in this biome.")
@@ -57,7 +56,7 @@ public class BiomePaletteTemplate implements ObjectTemplate<BiomePaletteInfo> {
@Default
private @Meta boolean updatePalette = false;
public BiomePaletteTemplate(Platform platform, SlantCalculationMethod slantCalculationMethod) {
public BiomePaletteTemplate(Platform platform, SlantHolder.CalculationMethod slantCalculationMethod) {
this.platform = platform;
this.slantCalculationMethod = slantCalculationMethod;
}
@@ -11,12 +11,11 @@ package com.dfsek.terra.addons.chunkgenerator.generation;
import org.jetbrains.annotations.NotNull;
import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseProperties;
import com.dfsek.terra.addons.chunkgenerator.generation.math.SlantCalculationMethod;
import com.dfsek.terra.addons.chunkgenerator.generation.math.PaletteUtil;
import com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation.LazilyEvaluatedInterpolator;
import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.Sampler3D;
import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.SamplerProvider;
import com.dfsek.terra.addons.chunkgenerator.palette.BiomePaletteInfo;
import com.dfsek.terra.addons.chunkgenerator.palette.slant.SlantHolder;
import com.dfsek.terra.api.Platform;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.config.ConfigPack;
@@ -43,23 +42,16 @@ public class NoiseChunkGenerator3D implements ChunkGenerator {
private final PropertyKey<BiomePaletteInfo> paletteInfoPropertyKey;
private final PropertyKey<BiomeNoiseProperties> noisePropertiesKey;
private final SlantCalculationMethod slantCalculationMethod;
private final boolean useSlantPalettes;
public NoiseChunkGenerator3D(ConfigPack pack, Platform platform, int elevationBlend, int carverHorizontalResolution,
int carverVerticalResolution,
PropertyKey<BiomeNoiseProperties> noisePropertiesKey,
PropertyKey<BiomePaletteInfo> paletteInfoPropertyKey,
SlantCalculationMethod slantCalculationMethod, boolean useSlantPalettes) {
PropertyKey<BiomePaletteInfo> paletteInfoPropertyKey) {
this.platform = platform;
this.air = platform.getWorldHandle().air();
this.carverHorizontalResolution = carverHorizontalResolution;
this.carverVerticalResolution = carverVerticalResolution;
this.paletteInfoPropertyKey = paletteInfoPropertyKey;
this.noisePropertiesKey = noisePropertiesKey;
this.slantCalculationMethod = slantCalculationMethod;
this.useSlantPalettes = useSlantPalettes;
int maxBlend = pack
.getBiomeProvider()
.stream()
@@ -71,17 +63,6 @@ public class NoiseChunkGenerator3D implements ChunkGenerator {
this.samplerCache = new SamplerProvider(platform, elevationBlend, noisePropertiesKey, maxBlend);
}
private Palette paletteAt(int x, int y, int z, Sampler3D sampler, BiomePaletteInfo paletteInfo, int depth) {
SlantHolder slantHolder = paletteInfo.slantHolder();
if(useSlantPalettes && slantHolder.isAboveDepth(depth)) {
double slant = slantCalculationMethod.slant(sampler, x, y, z);
if(slantHolder.isInSlantThreshold(slant)) {
return slantHolder.getPalette(slant).getPalette(y);
}
}
return paletteInfo.paletteHolder().getPalette(y);
}
@Override
@SuppressWarnings("try")
public void generateChunkData(@NotNull ProtoChunk chunk, @NotNull WorldProperties world,
@@ -122,7 +103,8 @@ public class NoiseChunkGenerator3D implements ChunkGenerator {
if(sampler.sample(x, y, z) > 0) {
if(carver.sample(x, y, z) <= 0) {
data = paletteAt(x, y, z, sampler, paletteInfo, paletteLevel)
data = PaletteUtil
.getPalette(x, y, z, sampler, paletteInfo, paletteLevel)
.get(paletteLevel, cx, y, cz, seed);
chunk.setBlock(x, y, z, data);
paletteLevel++;
@@ -153,7 +135,7 @@ public class NoiseChunkGenerator3D implements ChunkGenerator {
int fdX = Math.floorMod(x, 16);
int fdZ = Math.floorMod(z, 16);
Palette palette = paletteAt(fdX, y, fdZ, sampler, paletteInfo, 0);
Palette palette = PaletteUtil.getPalette(fdX, y, fdZ, sampler, paletteInfo, 0);
double noise = sampler.sample(fdX, y, fdZ);
if(noise > 0) {
int level = 0;
@@ -175,8 +157,11 @@ public class NoiseChunkGenerator3D implements ChunkGenerator {
public double getSlant(int x, int y, int z, WorldProperties world, BiomeProvider biomeProvider) {
int fdX = Math.floorMod(x, 16);
int fdZ = Math.floorMod(z, 16);
Sampler3D sampler = samplerCache.get(x, z, world, biomeProvider);
return slantCalculationMethod.slant(sampler, fdX, y, fdZ);
return biomeProvider.getBiome(x, y, z, world.getSeed())
.getContext()
.get(paletteInfoPropertyKey)
.slantHolder()
.calculateSlant(samplerCache.get(x, z, world, biomeProvider), fdX, y, fdZ);
}
public SamplerProvider samplerProvider() {
@@ -0,0 +1,29 @@
/*
* Copyright (c) 2020-2023 Polyhedral Development
*
* The Terra Core Addons are licensed under the terms of the MIT License. For more details,
* reference the LICENSE file in this module's root directory.
*/
package com.dfsek.terra.addons.chunkgenerator.generation.math;
import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.Sampler3D;
import com.dfsek.terra.addons.chunkgenerator.palette.BiomePaletteInfo;
import com.dfsek.terra.addons.chunkgenerator.palette.slant.SlantHolder;
import com.dfsek.terra.api.world.chunk.generation.util.Palette;
public final class PaletteUtil {
public static Palette getPalette(int x, int y, int z, Sampler3D sampler, BiomePaletteInfo paletteInfo, int depth) {
SlantHolder slantHolder = paletteInfo.slantHolder();
if(slantHolder.isAboveDepth(depth)) {
double slant = slantHolder.calculateSlant(sampler, x, y, z);
if(slantHolder.isInSlantThreshold(slant)) {
return slantHolder.getPalette(slant).getPalette(y);
}
}
return paletteInfo.paletteHolder().getPalette(y);
}
}
@@ -1,69 +0,0 @@
package com.dfsek.terra.addons.chunkgenerator.generation.math;
import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.Sampler3D;
import com.dfsek.terra.api.util.vector.Vector3;
public enum SlantCalculationMethod {
DotProduct {
private static final Vector3 DOT_PRODUCT_DIRECTION = Vector3.of(0, 1, 0);
private static final Vector3[] DOT_PRODUCT_SAMPLE_POINTS = {
Vector3.of(0, 0, -DERIVATIVE_DIST),
Vector3.of(0, 0, DERIVATIVE_DIST),
Vector3.of(0, -DERIVATIVE_DIST, 0),
Vector3.of(0, DERIVATIVE_DIST, 0),
Vector3.of(-DERIVATIVE_DIST, 0, 0),
Vector3.of(DERIVATIVE_DIST, 0, 0)
};
@Override
public double slant(Sampler3D sampler, double x, double y, double z) {
Vector3.Mutable normalApproximation = Vector3.Mutable.of(0, 0, 0);
for(Vector3 point : DOT_PRODUCT_SAMPLE_POINTS) {
var scalar = -sampler.sample(x + point.getX(), y + point.getY(), z + point.getZ());
normalApproximation.add(point.mutable().multiply(scalar));
}
return DOT_PRODUCT_DIRECTION.dot(normalApproximation.normalize());
}
@Override
public boolean floorToThreshold() {
return false;
}
},
Derivative {
@Override
public double slant(Sampler3D sampler, double x, double y, double z) {
double baseSample = sampler.sample(x, y, z);
double xVal1 = (sampler.sample(x + DERIVATIVE_DIST, y, z) - baseSample) / DERIVATIVE_DIST;
double xVal2 = (sampler.sample(x - DERIVATIVE_DIST, y, z) - baseSample) / DERIVATIVE_DIST;
double zVal1 = (sampler.sample(x, y, z + DERIVATIVE_DIST) - baseSample) / DERIVATIVE_DIST;
double zVal2 = (sampler.sample(x, y, z - DERIVATIVE_DIST) - baseSample) / DERIVATIVE_DIST;
double yVal1 = (sampler.sample(x, y + DERIVATIVE_DIST, z) - baseSample) / DERIVATIVE_DIST;
double yVal2 = (sampler.sample(x, y - DERIVATIVE_DIST, z) - baseSample) / DERIVATIVE_DIST;
return Math.sqrt(
((xVal2 - xVal1) * (xVal2 - xVal1)) + ((zVal2 - zVal1) * (zVal2 - zVal1)) + ((yVal2 - yVal1) * (yVal2 - yVal1)));
}
@Override
public boolean floorToThreshold() {
return true;
}
};
private static final double DERIVATIVE_DIST = 0.55;
public abstract double slant(Sampler3D sampler, double x, double y, double z);
/*
* Controls whether palettes should be applied before or after their respective thresholds.
*
* If true, slant values will map to the palette of the next floor threshold, otherwise they
* will map to the ceiling.
*/
public abstract boolean floorToThreshold();
}
@@ -14,7 +14,6 @@ import java.util.TreeMap;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.dfsek.terra.addons.chunkgenerator.generation.math.SlantCalculationMethod;
import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolder;
@@ -22,7 +21,7 @@ public class MultipleSlantHolder extends SlantHolderImpl {
private final NavigableMap<Double, PaletteHolder> layers;
private final double slantThreshold;
MultipleSlantHolder(List<SlantHolder.Layer> slant, int slantDepth, SlantCalculationMethod calculationMethod) {
MultipleSlantHolder(List<SlantHolder.Layer> slant, int slantDepth, CalculationMethod calculationMethod) {
super(slantDepth, calculationMethod);
NavigableMap<Double, PaletteHolder> layers = new TreeMap<>(
slant.stream().collect(Collectors.toMap(SlantHolder.Layer::threshold, SlantHolder.Layer::palette)));
@@ -1,6 +1,5 @@
package com.dfsek.terra.addons.chunkgenerator.palette.slant;
import com.dfsek.terra.addons.chunkgenerator.generation.math.SlantCalculationMethod;
import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolder;
@@ -8,7 +7,7 @@ final class SingleSlantHolder extends SlantHolderImpl {
private final SlantHolder.Layer layer;
public SingleSlantHolder(SlantHolder.Layer layer, int slantDepth, SlantCalculationMethod calculationMethod) {
public SingleSlantHolder(SlantHolder.Layer layer, int slantDepth, CalculationMethod calculationMethod) {
super(slantDepth, calculationMethod);
this.layer = layer;
}
@@ -2,13 +2,19 @@ package com.dfsek.terra.addons.chunkgenerator.palette.slant;
import java.util.List;
import com.dfsek.terra.addons.chunkgenerator.generation.math.SlantCalculationMethod;
import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.Sampler3D;
import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolder;
import com.dfsek.terra.api.util.vector.Vector3;
public interface SlantHolder {
SlantHolder EMPTY = new SlantHolder() {
@Override
public double calculateSlant(Sampler3D sampler, double x, double y, double z) {
throw new UnsupportedOperationException("Empty holder should not calculate slant");
}
@Override
public boolean isAboveDepth(int depth) {
return false;
@@ -25,7 +31,7 @@ public interface SlantHolder {
}
};
static SlantHolder of(List<SlantHolder.Layer> layers, int slantDepth, SlantCalculationMethod calculationMethod) {
static SlantHolder of(List<SlantHolder.Layer> layers, int slantDepth, CalculationMethod calculationMethod) {
if(layers.isEmpty()) {
return EMPTY;
} else if(layers.size() == 1) {
@@ -34,6 +40,8 @@ public interface SlantHolder {
return new MultipleSlantHolder(layers, slantDepth, calculationMethod);
}
double calculateSlant(Sampler3D sampler, double x, double y, double z);
boolean isAboveDepth(int depth);
boolean isInSlantThreshold(double slant);
@@ -41,6 +49,71 @@ public interface SlantHolder {
PaletteHolder getPalette(double slant);
enum CalculationMethod {
DotProduct {
private static final Vector3 DOT_PRODUCT_DIRECTION = Vector3.of(0, 1, 0);
private static final Vector3[] DOT_PRODUCT_SAMPLE_POINTS = {
Vector3.of(0, 0, -DERIVATIVE_DIST),
Vector3.of(0, 0, DERIVATIVE_DIST),
Vector3.of(0, -DERIVATIVE_DIST, 0),
Vector3.of(0, DERIVATIVE_DIST, 0),
Vector3.of(-DERIVATIVE_DIST, 0, 0),
Vector3.of(DERIVATIVE_DIST, 0, 0)
};
@Override
public double slant(Sampler3D sampler, double x, double y, double z) {
Vector3.Mutable normalApproximation = Vector3.Mutable.of(0, 0, 0);
for(Vector3 point : DOT_PRODUCT_SAMPLE_POINTS) {
var scalar = -sampler.sample(x + point.getX(), y + point.getY(), z + point.getZ());
normalApproximation.add(point.mutable().multiply(scalar));
}
return DOT_PRODUCT_DIRECTION.dot(normalApproximation.normalize());
}
@Override
public boolean floorToThreshold() {
return false;
}
},
Derivative {
@Override
public double slant(Sampler3D sampler, double x, double y, double z) {
double baseSample = sampler.sample(x, y, z);
double xVal1 = (sampler.sample(x + DERIVATIVE_DIST, y, z) - baseSample) / DERIVATIVE_DIST;
double xVal2 = (sampler.sample(x - DERIVATIVE_DIST, y, z) - baseSample) / DERIVATIVE_DIST;
double zVal1 = (sampler.sample(x, y, z + DERIVATIVE_DIST) - baseSample) / DERIVATIVE_DIST;
double zVal2 = (sampler.sample(x, y, z - DERIVATIVE_DIST) - baseSample) / DERIVATIVE_DIST;
double yVal1 = (sampler.sample(x, y + DERIVATIVE_DIST, z) - baseSample) / DERIVATIVE_DIST;
double yVal2 = (sampler.sample(x, y - DERIVATIVE_DIST, z) - baseSample) / DERIVATIVE_DIST;
return Math.sqrt(
((xVal2 - xVal1) * (xVal2 - xVal1)) + ((zVal2 - zVal1) * (zVal2 - zVal1)) + ((yVal2 - yVal1) * (yVal2 - yVal1)));
}
@Override
public boolean floorToThreshold() {
return true;
}
};
private static final double DERIVATIVE_DIST = 0.55;
public abstract double slant(Sampler3D sampler, double x, double y, double z);
/*
* Controls whether palettes should be applied before or after their respective thresholds.
*
* If true, slant values will map to the palette of the next floor threshold, otherwise they
* will map to the ceiling.
*/
public abstract boolean floorToThreshold();
}
record Layer(PaletteHolder palette, double threshold) {
}
}
@@ -1,19 +1,26 @@
package com.dfsek.terra.addons.chunkgenerator.palette.slant;
import com.dfsek.terra.addons.chunkgenerator.generation.math.SlantCalculationMethod;
import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.Sampler3D;
public abstract class SlantHolderImpl implements SlantHolder {
protected final boolean floorToThreshold;
private final SlantHolder.CalculationMethod calculationMethod;
private final int slantDepth;
protected SlantHolderImpl(int slantDepth, SlantCalculationMethod calculationMethod) {
protected SlantHolderImpl(int slantDepth, CalculationMethod calculationMethod) {
this.floorToThreshold = calculationMethod.floorToThreshold();
this.calculationMethod = calculationMethod;
this.slantDepth = slantDepth;
}
protected abstract double getSlantThreshold();
@Override
public final double calculateSlant(Sampler3D sampler, double x, double y, double z) {
return calculationMethod.slant(sampler, x, y, z);
}
@Override
public final boolean isAboveDepth(int depth) {
return depth <= slantDepth;
@@ -1,7 +1,7 @@
package com.dfsek.terra.addons.commands.addons;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.description.Description;
import cloud.commandframework.ArgumentDescription;
import cloud.commandframework.CommandManager;
import com.dfsek.terra.addons.manifest.api.AddonInitializer;
import com.dfsek.terra.api.Platform;
@@ -30,7 +30,7 @@ public class AddonsCommandAddon implements AddonInitializer {
CommandManager<CommandSender> manager = event.getCommandManager();
manager.command(
manager.commandBuilder("addons", Description.of("List installed Terra addons"))
manager.commandBuilder("addons", ArgumentDescription.of("List installed Terra addons"))
.permission("terra.addons")
.handler(context -> {
StringBuilder addons = new StringBuilder("Installed addons:\n");
@@ -41,7 +41,7 @@ public class AddonsCommandAddon implements AddonInitializer {
.append('@')
.append(addon.getVersion().getFormatted())
.append('\n'));
context.sender().sendMessage(addons.toString());
context.getSender().sendMessage(addons.toString());
})
)
.command(
@@ -61,7 +61,7 @@ public class AddonsCommandAddon implements AddonInitializer {
.append('@')
.append(versions.getFormatted())
.append('\n'));
context.sender().sendMessage(addonInfo.toString());
context.getSender().sendMessage(addonInfo.toString());
})
);
});
@@ -1,7 +1,7 @@
package com.dfsek.terra.addons.commands.packs;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.description.Description;
import cloud.commandframework.ArgumentDescription;
import cloud.commandframework.CommandManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -35,7 +35,7 @@ public class PacksCommandAddon implements AddonInitializer {
CommandManager<CommandSender> manager = event.getCommandManager();
manager.command(
manager.commandBuilder("packs", Description.of("List installed config packs"))
manager.commandBuilder("packs", ArgumentDescription.of("List installed config packs"))
.permission("terra.packs")
.handler(context -> {
StringBuilder packs = new StringBuilder("Installed packs:\n");
@@ -43,12 +43,12 @@ public class PacksCommandAddon implements AddonInitializer {
.append(pack.getID())
.append('@')
.append(pack.getVersion().getFormatted()));
context.sender().sendMessage(packs.toString());
context.getSender().sendMessage(packs.toString());
})
)
.command(
manager.commandBuilder("packs")
.literal("info", Description.of("Get information about a pack"))
.literal("info", ArgumentDescription.of("Get information about a pack"))
.permission("terra.packs.info")
.argument(RegistryArgument.of("pack", platform.getConfigRegistry()))
.handler(context -> {
@@ -65,21 +65,21 @@ public class PacksCommandAddon implements AddonInitializer {
.append('@')
.append(versions.getFormatted())
.append('\n'));
context.sender().sendMessage(packInfo.toString());
context.getSender().sendMessage(packInfo.toString());
}))
.command(
manager.commandBuilder("packs")
.literal("reload", Description.of("Reload config packs"))
.literal("reload", ArgumentDescription.of("Reload config packs"))
.permission("terra.packs.reload")
.handler(context -> {
context.sender().sendMessage("Reloading Terra...");
context.getSender().sendMessage("Reloading Terra...");
logger.info("Reloading Terra...");
if(platform.reload()) {
logger.info("Terra reloaded successfully.");
context.sender().sendMessage("Terra reloaded successfully.");
context.getSender().sendMessage("Terra reloaded successfully.");
} else {
logger.error("Terra failed to reload.");
context.sender().sendMessage(
context.getSender().sendMessage(
"Terra failed to reload. See logs for more information.");
}
}));
@@ -1,7 +1,7 @@
package com.dfsek.terra.addons.commands.profiler;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.description.Description;
import cloud.commandframework.ArgumentDescription;
import cloud.commandframework.CommandManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,24 +33,24 @@ public class ProfilerCommandAddon implements AddonInitializer {
CommandManager<CommandSender> manager = event.getCommandManager();
manager
.command(
manager.commandBuilder("profiler", Description.of("Access the profiler"))
.literal("start", Description.of("Start profiling"), "st")
manager.commandBuilder("profiler", ArgumentDescription.of("Access the profiler"))
.literal("start", ArgumentDescription.of("Start profiling"), "st")
.permission("terra.profiler.start")
.handler(context -> {
platform.getProfiler().start();
context.sender().sendMessage("Profiling started.");
context.getSender().sendMessage("Profiling started.");
}))
.command(
manager.commandBuilder("profiler", Description.of("Access the profiler"))
.literal("stop", Description.of("Stop profiling"), "s")
manager.commandBuilder("profiler", ArgumentDescription.of("Access the profiler"))
.literal("stop", ArgumentDescription.of("Stop profiling"), "s")
.permission("terra.profiler.stop")
.handler(context -> {
platform.getProfiler().stop();
context.sender().sendMessage("Profiling stopped.");
context.getSender().sendMessage("Profiling stopped.");
}))
.command(
manager.commandBuilder("profiler", Description.of("Access the profiler"))
.literal("query", Description.of("Query profiler results"), "q")
manager.commandBuilder("profiler", ArgumentDescription.of("Access the profiler"))
.literal("query", ArgumentDescription.of("Query profiler results"), "q")
.permission("terra.profiler.query")
.handler(context -> {
StringBuilder data = new StringBuilder("Terra Profiler data: \n");
@@ -59,15 +59,15 @@ public class ProfilerCommandAddon implements AddonInitializer {
.append(timings.toString())
.append('\n'));
logger.info(data.toString());
context.sender().sendMessage("Profiling data dumped to console.");
context.getSender().sendMessage("Profiling data dumped to console.");
}))
.command(
manager.commandBuilder("profiler", Description.of("Access the profiler"))
.literal("reset", Description.of("Reset the profiler"), "r")
manager.commandBuilder("profiler", ArgumentDescription.of("Access the profiler"))
.literal("reset", ArgumentDescription.of("Reset the profiler"), "r")
.permission("terra.profiler.reset")
.handler(context -> {
platform.getProfiler().reset();
context.sender().sendMessage("Profiler reset.");
context.getSender().sendMessage("Profiler reset.");
}));
});
}
@@ -1,11 +1,10 @@
package com.dfsek.terra.addons.commands.structure;
import org.incendo.cloud.CommandManager;
import org.incendo.cloud.component.DefaultValue;
import org.incendo.cloud.context.CommandContext;
import org.incendo.cloud.description.Description;
import org.incendo.cloud.parser.standard.EnumParser;
import org.incendo.cloud.parser.standard.LongParser;
import cloud.commandframework.ArgumentDescription;
import cloud.commandframework.CommandManager;
import cloud.commandframework.arguments.standard.EnumArgument;
import cloud.commandframework.arguments.standard.LongArgument;
import cloud.commandframework.context.CommandContext;
import java.util.Random;
@@ -32,7 +31,7 @@ public class StructureCommandAddon implements AddonInitializer {
private BaseAddon addon;
private static Registry<Structure> getStructureRegistry(CommandContext<CommandSender> sender) {
return sender.sender().getEntity().orElseThrow().world().getPack().getRegistry(Structure.class);
return sender.getSender().getEntity().orElseThrow().world().getPack().getRegistry(Structure.class);
}
@Override
@@ -44,16 +43,16 @@ public class StructureCommandAddon implements AddonInitializer {
CommandManager<CommandSender> manager = event.getCommandManager();
manager.command(
manager.commandBuilder("structures", Description.of("Manage or generate structures"))
manager.commandBuilder("structures", ArgumentDescription.of("Manage or generate structures"))
.literal("generate")
.optional(RegistryArgument.builder("structure",
.argument(RegistryArgument.builder("structure",
StructureCommandAddon::getStructureRegistry,
TypeKey.of(Structure.class)))
.optional("seed", LongParser.longParser(), DefaultValue.constant(0L))
.optional("rotation", EnumParser.enumParser(Rotation.class), DefaultValue.constant(Rotation.NONE))
.argument(LongArgument.optional("seed", 0))
.argument(EnumArgument.optional(Rotation.class, "rotation", Rotation.NONE))
.handler(context -> {
Structure structure = context.get("structure");
Entity sender = context.sender().getEntity().orElseThrow();
Entity sender = context.getSender().getEntity().orElseThrow();
structure.generate(
sender.position().toInt(),
sender.world(),
@@ -7,11 +7,11 @@
package com.dfsek.terra.addons.biome.holder;
import com.dfsek.terra.api.world.chunk.generation.util.Palette;
import java.util.Map;
import java.util.TreeMap;
import com.dfsek.terra.api.world.chunk.generation.util.Palette;
public class PaletteHolderBuilder {
private final TreeMap<Integer, Palette> paletteMap = new TreeMap<>();
@@ -7,11 +7,11 @@
package com.dfsek.terra.addons.feature.distributor.distributors;
import java.util.Set;
import com.dfsek.terra.addons.feature.distributor.util.Point;
import com.dfsek.terra.api.structure.feature.Distributor;
import java.util.Set;
public class PointSetDistributor implements Distributor {
private final Set<Point> points;
@@ -1,4 +1,4 @@
version = version("1.2.0")
version = version("1.1.0")
dependencies {
compileOnlyApi(project(":common:addons:manifest-addon-loader"))
@@ -17,7 +17,6 @@ import com.dfsek.terra.addons.manifest.api.AddonInitializer;
import com.dfsek.terra.addons.noise.config.CubicSplinePointTemplate;
import com.dfsek.terra.addons.noise.config.DimensionApplicableNoiseSampler;
import com.dfsek.terra.addons.noise.config.templates.BinaryArithmeticTemplate;
import com.dfsek.terra.addons.noise.config.templates.DerivativeNoiseSamplerTemplate;
import com.dfsek.terra.addons.noise.config.templates.DomainWarpTemplate;
import com.dfsek.terra.addons.noise.config.templates.FunctionTemplate;
import com.dfsek.terra.addons.noise.config.templates.ImageSamplerTemplate;
@@ -29,7 +28,6 @@ import com.dfsek.terra.addons.noise.config.templates.noise.ConstantNoiseTemplate
import com.dfsek.terra.addons.noise.config.templates.noise.DistanceSamplerTemplate;
import com.dfsek.terra.addons.noise.config.templates.noise.ExpressionFunctionTemplate;
import com.dfsek.terra.addons.noise.config.templates.noise.GaborNoiseTemplate;
import com.dfsek.terra.addons.noise.config.templates.noise.PseudoErosionTemplate;
import com.dfsek.terra.addons.noise.config.templates.noise.SimpleNoiseTemplate;
import com.dfsek.terra.addons.noise.config.templates.noise.fractal.BrownianMotionTemplate;
import com.dfsek.terra.addons.noise.config.templates.noise.fractal.PingPongTemplate;
@@ -65,7 +63,6 @@ import com.dfsek.terra.api.addon.BaseAddon;
import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent;
import com.dfsek.terra.api.event.functional.FunctionalEventHandler;
import com.dfsek.terra.api.inject.annotations.Inject;
import com.dfsek.terra.api.noise.DerivativeNoiseSampler;
import com.dfsek.terra.api.noise.NoiseSampler;
import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.api.util.reflection.TypeKey;
@@ -97,8 +94,7 @@ public class NoiseAddon implements AddonInitializer {
(type, o, loader, depthTracker) -> DistanceSampler.DistanceFunction.valueOf((String) o))
.applyLoader(DimensionApplicableNoiseSampler.class, DimensionApplicableNoiseSampler::new)
.applyLoader(FunctionTemplate.class, FunctionTemplate::new)
.applyLoader(CubicSpline.Point.class, CubicSplinePointTemplate::new)
.applyLoader(DerivativeNoiseSampler.class, DerivativeNoiseSamplerTemplate::new);
.applyLoader(CubicSpline.Point.class, CubicSplinePointTemplate::new);
noiseRegistry.register(addon.key("LINEAR"), LinearNormalizerTemplate::new);
noiseRegistry.register(addon.key("NORMAL"), NormalNormalizerTemplate::new);
@@ -121,7 +117,7 @@ public class NoiseAddon implements AddonInitializer {
noiseRegistry.register(addon.key("PERLIN"), () -> new SimpleNoiseTemplate(PerlinSampler::new));
noiseRegistry.register(addon.key("SIMPLEX"), () -> new SimpleNoiseTemplate(SimplexSampler::new));
noiseRegistry.register(addon.key("GABOR"), GaborNoiseTemplate::new);
noiseRegistry.register(addon.key("PSEUDOEROSION"), PseudoErosionTemplate::new);
noiseRegistry.register(addon.key("VALUE"), () -> new SimpleNoiseTemplate(ValueSampler::new));
noiseRegistry.register(addon.key("VALUE_CUBIC"), () -> new SimpleNoiseTemplate(ValueCubicSampler::new));
@@ -11,14 +11,14 @@ import com.dfsek.tectonic.api.config.template.ConfigTemplate;
import com.dfsek.tectonic.api.config.template.annotations.Default;
import com.dfsek.tectonic.api.config.template.annotations.Value;
import java.util.LinkedHashMap;
import java.util.Map;
import com.dfsek.terra.addons.noise.config.DimensionApplicableNoiseSampler;
import com.dfsek.terra.addons.noise.config.templates.FunctionTemplate;
import com.dfsek.terra.api.config.meta.Meta;
import com.dfsek.terra.api.properties.Properties;
import java.util.LinkedHashMap;
import java.util.Map;
@SuppressWarnings("FieldMayBeFinal")
public class NoiseConfigPackTemplate implements ConfigTemplate, Properties {
@@ -1,26 +0,0 @@
package com.dfsek.terra.addons.noise.config.templates;
import com.dfsek.tectonic.api.config.template.annotations.Value;
import com.dfsek.tectonic.api.exception.ValidationException;
import com.dfsek.terra.api.noise.DerivativeNoiseSampler;
import com.dfsek.terra.api.noise.NoiseSampler;
public class DerivativeNoiseSamplerTemplate extends SamplerTemplate<DerivativeNoiseSampler> {
@Value(".")
private NoiseSampler sampler;
@Override
public boolean validate() throws ValidationException {
if(!DerivativeNoiseSampler.isDifferentiable(sampler)) throw new ValidationException(
"Provided sampler does not support calculating a derivative");
return super.validate();
}
@Override
public DerivativeNoiseSampler get() {
return (DerivativeNoiseSampler) sampler;
}
}
@@ -1,8 +0,0 @@
package com.dfsek.terra.addons.noise.config.templates.noise;
import com.dfsek.terra.addons.noise.samplers.noise.DerivativeNoiseFunction;
public abstract class DerivativeNoiseTemplate<T extends DerivativeNoiseFunction> extends NoiseTemplate<T> {
}
@@ -1,79 +0,0 @@
package com.dfsek.terra.addons.noise.config.templates.noise;
import com.dfsek.tectonic.api.config.template.annotations.Default;
import com.dfsek.tectonic.api.config.template.annotations.Value;
import com.dfsek.terra.addons.noise.samplers.noise.PseudoErosionSampler;
import com.dfsek.terra.addons.noise.samplers.noise.simplex.OpenSimplex2Sampler;
import com.dfsek.terra.api.config.meta.Meta;
import com.dfsek.terra.api.noise.DerivativeNoiseSampler;
public class PseudoErosionTemplate extends NoiseTemplate<PseudoErosionSampler> {
@Value("frequency")
@Default
protected @Meta double frequency = 1d;
@Value("octaves")
@Default
private int octaves = 4;
@Value("lacunarity")
@Default
private double lacunarity = 2.0;
@Value("gain")
@Default
private double gain = 0.5;
@Value("slope-strength")
@Default
private double slopeStrength = 1.0;
@Value("branch-strength")
@Default
private double branchStrength = 1.0;
@Value("strength")
@Default
private double strength = 0.04;
@Value("erosion-frequency")
@Default
private double erosionFrequency = 0.02;
@Value("sampler")
@Default
private DerivativeNoiseSampler heightSampler = new OpenSimplex2Sampler();
@Value("slope-mask.enable")
@Default
private boolean slopeMask = true;
@Value("slope-mask.none")
@Default
private double slopeMaskNone = -0.5;
@Value("slope-mask.full")
@Default
private double slopeMaskFull = 1;
@Value("jitter")
@Default
private double jitterModifier = 1;
@Value("average-impulses")
@Default
private boolean averageErosionImpulses = true;
@Override
public PseudoErosionSampler get() {
PseudoErosionSampler pseudoErosion = new PseudoErosionSampler(octaves, gain, lacunarity,
slopeStrength, branchStrength, strength,
erosionFrequency, heightSampler, slopeMask, slopeMaskFull, slopeMaskNone, jitterModifier, averageErosionImpulses);
pseudoErosion.setFrequency(frequency);
pseudoErosion.setSalt(salt);
return pseudoErosion;
}
}
@@ -11,8 +11,6 @@ import com.dfsek.terra.addons.noise.config.templates.FunctionTemplate;
import com.dfsek.terra.addons.noise.paralithic.defined.UserDefinedFunction;
import com.dfsek.terra.addons.noise.paralithic.noise.NoiseFunction2;
import com.dfsek.terra.addons.noise.paralithic.noise.NoiseFunction3;
import com.dfsek.terra.addons.noise.paralithic.noise.SaltedNoiseFunction2;
import com.dfsek.terra.addons.noise.paralithic.noise.SaltedNoiseFunction3;
public class FunctionUtil {
@@ -25,15 +23,10 @@ public class FunctionUtil {
for(Map.Entry<String, FunctionTemplate> entry : functions.entrySet()) {
functionMap.put(entry.getKey(), UserDefinedFunction.newInstance(entry.getValue()));
}
samplers.forEach((id, sampler) -> {
if(sampler.getDimensions() == 2) {
functionMap.put(id, new NoiseFunction2(sampler.getSampler()));
functionMap.put(id + "Salted", new SaltedNoiseFunction2(sampler.getSampler()));
} else {
functionMap.put(id, new NoiseFunction3(sampler.getSampler()));
functionMap.put(id + "Salted", new SaltedNoiseFunction3(sampler.getSampler()));
}
});
samplers.forEach((id, sampler) -> functionMap.put(id,
sampler.getDimensions() == 2 ?
new NoiseFunction2(sampler.getSampler()) :
new NoiseFunction3(sampler.getSampler())));
return functionMap;
}
}
@@ -1,37 +0,0 @@
package com.dfsek.terra.addons.noise.paralithic.noise;
import com.dfsek.paralithic.functions.dynamic.Context;
import com.dfsek.paralithic.functions.dynamic.DynamicFunction;
import com.dfsek.paralithic.node.Statefulness;
import org.jetbrains.annotations.NotNull;
import com.dfsek.terra.api.noise.NoiseSampler;
public class SaltedNoiseFunction2 implements DynamicFunction {
private final NoiseSampler gen;
public SaltedNoiseFunction2(NoiseSampler gen) {
this.gen = gen;
}
@Override
public double eval(double... args) {
throw new UnsupportedOperationException("Cannot evaluate seeded function without seed context.");
}
@Override
public double eval(Context context, double... args) {
return gen.noise(((SeedContext) context).getSeed() + (long) args[2], args[0], args[1]);
}
@Override
public int getArgNumber() {
return 3;
}
@Override
public @NotNull Statefulness statefulness() {
return Statefulness.CONTEXTUAL;
}
}
@@ -1,37 +0,0 @@
package com.dfsek.terra.addons.noise.paralithic.noise;
import com.dfsek.paralithic.functions.dynamic.Context;
import com.dfsek.paralithic.functions.dynamic.DynamicFunction;
import com.dfsek.paralithic.node.Statefulness;
import org.jetbrains.annotations.NotNull;
import com.dfsek.terra.api.noise.NoiseSampler;
public class SaltedNoiseFunction3 implements DynamicFunction {
private final NoiseSampler gen;
public SaltedNoiseFunction3(NoiseSampler gen) {
this.gen = gen;
}
@Override
public double eval(double... args) {
throw new UnsupportedOperationException("Cannot evaluate seeded function without seed context.");
}
@Override
public double eval(Context context, double... args) {
return gen.noise(((SeedContext) context).getSeed() + (long) args[3], args[0], args[1], args[2]);
}
@Override
public int getArgNumber() {
return 4;
}
@Override
public @NotNull Statefulness statefulness() {
return Statefulness.CONTEXTUAL;
}
}
@@ -1,25 +0,0 @@
package com.dfsek.terra.addons.noise.samplers.noise;
import com.dfsek.terra.api.noise.DerivativeNoiseSampler;
public abstract class DerivativeNoiseFunction extends NoiseFunction implements DerivativeNoiseSampler {
@Override
public boolean isDifferentiable() {
return true;
}
@Override
public double[] noised(long seed, double x, double y) {
return getNoiseDerivativeRaw(seed + salt, x * frequency, y * frequency);
}
@Override
public double[] noised(long seed, double x, double y, double z) {
return getNoiseDerivativeRaw(seed + salt, x * frequency, y * frequency, z * frequency);
}
public abstract double[] getNoiseDerivativeRaw(long seed, double x, double y);
public abstract double[] getNoiseDerivativeRaw(long seed, double x, double y, double z);
}
@@ -1,173 +0,0 @@
package com.dfsek.terra.addons.noise.samplers.noise;
import com.dfsek.terra.api.noise.DerivativeNoiseSampler;
import com.dfsek.terra.api.util.MathUtil;
public class PseudoErosionSampler extends NoiseFunction {
public static final double TAU = 2.0 * Math.PI;
private static final double HASH_X = 0.3183099f;
private static final double HASH_Y = 0.3678794f;
public final double gain;
public final double lacunarity;
public final double slopeStrength;
public final double branchStrength;
public final double erosionStrength;
private final int octaves;
private final double erosionFrequency;
private final DerivativeNoiseSampler sampler;
private final boolean slopeMask;
private final double slopeMaskFullSq;
private final double slopeMaskNoneSq;
private final double jitter;
private final double maxCellDistSq;
private final double maxCellDistSqRecip;
private final boolean averageErosionImpulses;
public PseudoErosionSampler(int octaves, double gain, double lacunarity, double slopeStrength, double branchStrength,
double erosionStrength, double erosionFrequency, DerivativeNoiseSampler sampler,
boolean slopeMask, double slopeMaskFull, double slopeMaskNone, double jitterModifier,
boolean averageErosionImpulses) {
this.octaves = octaves;
this.gain = gain;
this.lacunarity = lacunarity;
this.slopeStrength = slopeStrength;
this.branchStrength = branchStrength;
this.erosionStrength = erosionStrength;
this.erosionFrequency = erosionFrequency;
this.sampler = sampler;
this.slopeMask = slopeMask;
// Square these values and maintain sign since they're compared to a
// squared value, otherwise a sqrt would need to be used
this.slopeMaskFullSq = slopeMaskFull * slopeMaskFull * Math.signum(slopeMaskFull);
this.slopeMaskNoneSq = slopeMaskNone * slopeMaskNone * Math.signum((slopeMaskNone));
this.jitter = 0.43701595 * jitterModifier;
this.averageErosionImpulses = averageErosionImpulses;
this.maxCellDistSq = 1 + jitter * jitter;
this.maxCellDistSqRecip = 1 / maxCellDistSq;
}
public static double hashX(double seed, double n) {
// Swapped the components here
double nx = HASH_X * n * seed;
return -1.0f + 2.0f * fract(nx);
}
public static double hashY(double seed, double n) {
double ny = HASH_Y * n * seed;
return -1.0f + 2.0f * fract(ny);
}
public static double fract(double x) {
return (x - Math.floor(x));
}
public static double smoothstep(double edge0, double edge1, double x) {
// Scale, bias and saturate x to 0..1 range
x = clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
// Evaluate polynomial
return x * x * (3 - 2 * x);
}
public static double clamp(double x, double minVal, double maxVal) {
return Math.max(minVal, Math.min(maxVal, x));
}
public static double dot(double x1, double y1, double x2, double y2) {
return x1 * x2 + y1 * y2;
}
public double[] erosion(int seed, double x, double y, double dirX, double dirY) {
int gridX = (int) Math.round(x);
int gridY = (int) Math.round(y);
double noise = 0.0f;
double dirOutX = 0.0f;
double dirOutY = 0.0f;
double cumAmp = 0.0f;
for(int cellX = gridX - 1; cellX <= gridX + 1; cellX++) {
for(int cellY = gridY - 1; cellY <= gridY + 1; cellY++) {
double cellHash = hash(seed, cellX, cellY);
double cellOffsetX = hashX(seed, cellHash) * jitter;
double cellOffsetY = hashY(seed, cellHash) * jitter;
double cellOriginDeltaX = (x - cellX) + cellOffsetX;
double cellOriginDeltaY = (y - cellY) + cellOffsetY;
double cellOriginDistSq = cellOriginDeltaX * cellOriginDeltaX + cellOriginDeltaY * cellOriginDeltaY;
if(cellOriginDistSq > maxCellDistSq) continue; // Skip calculating cells too far away
double ampTmp = (cellOriginDistSq * maxCellDistSqRecip) - 1;
double amp = ampTmp * ampTmp; // Decrease cell amplitude further away
cumAmp += amp;
double directionalStrength = dot(cellOriginDeltaX, cellOriginDeltaY, dirX, dirY) * TAU;
noise += MathUtil.cos(directionalStrength) * amp;
double sinAngle = MathUtil.sin(directionalStrength) * amp;
dirOutX -= sinAngle * (cellOriginDeltaX + dirX);
dirOutY -= sinAngle * (cellOriginDeltaY + dirY);
}
}
if(averageErosionImpulses && cumAmp != 0) {
noise /= cumAmp;
dirOutX /= cumAmp;
dirOutY /= cumAmp;
}
return new double[]{ noise, dirOutX, dirOutY };
}
public double heightMap(long seed, double x, double y) {
double[] sample = sampler.noised(seed, x, y);
double height = sample[0];
double heightDirX = sample[1];
double heightDirY = sample[2];
// Take the curl of the normal to get the gradient facing down the slope
double baseDirX = heightDirY * slopeStrength;
double baseDirY = -heightDirX * slopeStrength;
double erosion = 0.0f;
double dirX = 0.0f;
double dirY = 0.0f;
double amp = 1.0f;
double cumAmp = 0.0f;
double freq = 1.0f;
// Stack erosion octaves
for(int i = 0; i < octaves; i++) {
double[] erosionResult = erosion((int) seed,
x * freq * erosionFrequency,
y * freq * erosionFrequency,
baseDirX + dirY * branchStrength,
baseDirY - dirX * branchStrength);
erosion += erosionResult[0] * amp;
dirX += erosionResult[1] * amp * freq;
dirY += erosionResult[2] * amp * freq;
cumAmp += amp;
amp *= gain;
freq *= lacunarity;
}
// Normalize erosion noise
erosion /= cumAmp;
// [-1, 1] -> [0, 1]
erosion = erosion * 0.5F + 0.5F;
// Without masking, erosion noise in areas with small gradients tend to produce mounds,
// this reduces erosion amplitude towards smaller gradients to avoid this
if(slopeMask) {
double dirMagSq = dot(baseDirX, baseDirY, baseDirX, baseDirY);
double flatness = smoothstep((double) slopeMaskNoneSq, slopeMaskFullSq, dirMagSq);
erosion *= flatness;
}
return height + erosion * erosionStrength;
}
@Override
public double getNoiseRaw(long seed, double x, double y) {
return heightMap(seed, x, y);
}
@Override
public double getNoiseRaw(long seed, double x, double y, double z) {
return getNoiseRaw(seed, x, z);
}
}
@@ -24,7 +24,7 @@ public class BrownianMotionSampler extends FractalNoiseFunction {
for(int i = 0; i < octaves; i++) {
double noise = input.noise(seed++, x, y);
sum += noise * amp;
amp *= MathUtil.lerp(weightedStrength, 1.0, Math.min(noise + 1, 2) * 0.5);
amp *= MathUtil.lerp(1.0, Math.min(noise + 1, 2) * 0.5, weightedStrength);
x *= lacunarity;
y *= lacunarity;
@@ -42,7 +42,7 @@ public class BrownianMotionSampler extends FractalNoiseFunction {
for(int i = 0; i < octaves; i++) {
double noise = input.noise(seed++, x, y, z);
sum += noise * amp;
amp *= MathUtil.lerp(weightedStrength, 1.0, (noise + 1) * 0.5);
amp *= MathUtil.lerp(1.0, (noise + 1) * 0.5, weightedStrength);
x *= lacunarity;
y *= lacunarity;
@@ -36,7 +36,7 @@ public class PingPongSampler extends FractalNoiseFunction {
for(int i = 0; i < octaves; i++) {
double noise = pingPong((input.noise(seed++, x, y) + 1) * pingPongStrength);
sum += (noise - 0.5) * 2 * amp;
amp *= MathUtil.lerp(weightedStrength, 1.0, noise);
amp *= MathUtil.lerp(1.0, noise, weightedStrength);
x *= lacunarity;
y *= lacunarity;
@@ -54,7 +54,7 @@ public class PingPongSampler extends FractalNoiseFunction {
for(int i = 0; i < octaves; i++) {
double noise = pingPong((input.noise(seed++, x, y, z) + 1) * pingPongStrength);
sum += (noise - 0.5) * 2 * amp;
amp *= MathUtil.lerp(weightedStrength, 1.0, noise);
amp *= MathUtil.lerp(1.0, noise, weightedStrength);
x *= lacunarity;
y *= lacunarity;
@@ -25,7 +25,7 @@ public class RidgedFractalSampler extends FractalNoiseFunction {
for(int i = 0; i < octaves; i++) {
double noise = Math.abs(input.noise(seed++, x, y));
sum += (noise * -2 + 1) * amp;
amp *= MathUtil.lerp(weightedStrength, 1.0, 1 - noise);
amp *= MathUtil.lerp(1.0, 1 - noise, weightedStrength);
x *= lacunarity;
y *= lacunarity;
@@ -43,7 +43,7 @@ public class RidgedFractalSampler extends FractalNoiseFunction {
for(int i = 0; i < octaves; i++) {
double noise = Math.abs(input.noise(seed++, x, y, z));
sum += (noise * -2 + 1) * amp;
amp *= MathUtil.lerp(weightedStrength, 1.0, 1 - noise);
amp *= MathUtil.lerp(1.0, 1 - noise, weightedStrength);
x *= lacunarity;
y *= lacunarity;
@@ -276,424 +276,4 @@ public class OpenSimplex2SSampler extends SimplexStyleSampler {
return value * 9.046026385208288;
}
@Override
public boolean isDifferentiable() {
return true;
}
@Override
public double[] getNoiseDerivativeRaw(long sl, double x, double y) {
int seed = (int) sl;
// 2D OpenSimplex2S case is a modified 2D simplex noise.
final double SQRT3 = 1.7320508075688772935274463415059;
final double G2 = (3 - SQRT3) / 6;
final double F2 = 0.5f * (SQRT3 - 1);
double s = (x + y) * F2;
x += s;
y += s;
int i = (int) Math.floor(x);
int j = (int) Math.floor(y);
double xi = x - i;
double yi = y - j;
i *= PRIME_X;
j *= PRIME_Y;
int i1 = i + PRIME_X;
int j1 = j + PRIME_Y;
double t = (xi + yi) * G2;
double x0 = xi - t;
double y0 = yi - t;
double[] out = { 0.0f, 0.0f, 0.0f };
double a0 = (2.0 / 3.0) - x0 * x0 - y0 * y0;
double aa0 = a0 * a0, aaa0 = aa0 * a0, aaaa0 = aa0 * aa0;
int gi0 = gradCoordIndex(seed, i, j);
double gx0 = GRADIENTS_2_D[gi0], gy0 = GRADIENTS_2_D[gi0 | 1];
double rampValue0 = gx0 * x0 + gy0 * y0;
out[0] = aaaa0 * rampValue0;
out[1] = gx0 * aaaa0 - 8 * rampValue0 * aaa0 * x0;
out[2] = gy0 * aaaa0 - 8 * rampValue0 * aaa0 * y0;
double a1 = 2 * (1 - 2 * G2) * (1 / G2 - 2) * t + ((-2 * (1 - 2 * G2) * (1 - 2 * G2)) + a0);
double x1 = x0 - (1 - 2 * G2);
double y1 = y0 - (1 - 2 * G2);
double aa1 = a1 * a1, aaa1 = aa1 * a1, aaaa1 = aa1 * aa1;
int gi1 = gradCoordIndex(seed, i1, j1);
double gx1 = GRADIENTS_2_D[gi1], gy1 = GRADIENTS_2_D[gi1 | 1];
double rampValue1 = gx1 * x1 + gy1 * y1;
out[0] += aaaa1 * rampValue1;
out[1] += gx1 * aaaa1 - 8 * rampValue1 * aaa1 * x1;
out[2] += gy1 * aaaa1 - 8 * rampValue1 * aaa1 * y1;
// Nested conditionals were faster than compact bit logic/arithmetic.
double xmyi = xi - yi;
if(t > G2) {
if(xi + xmyi > 1) {
double x2 = x0 + (3 * G2 - 2);
double y2 = y0 + (3 * G2 - 1);
double a2 = (2.0 / 3.0) - x2 * x2 - y2 * y2;
if(a2 > 0) {
double aa2 = a2 * a2, aaa2 = aa2 * a2, aaaa2 = aa2 * aa2;
int gi2 = gradCoordIndex(seed, i + (PRIME_X << 1), j + PRIME_Y);
double gx2 = GRADIENTS_2_D[gi2 | 0], gy2 = GRADIENTS_2_D[gi2 | 1];
double rampValue2 = gx2 * x2 + gy2 * y2;
out[0] += aaaa2 * rampValue2;
out[1] += gx2 * aaaa2 - 8 * rampValue2 * aaa2 * x2;
out[2] += gy2 * aaaa2 - 8 * rampValue2 * aaa2 * y2;
}
} else {
double x2 = x0 + G2;
double y2 = y0 + (G2 - 1);
double a2 = (2.0 / 3.0) - x2 * x2 - y2 * y2;
if(a2 > 0) {
double aa2 = a2 * a2, aaa2 = aa2 * a2, aaaa2 = aa2 * aa2;
int gi2 = gradCoordIndex(seed, i, j + PRIME_Y);
double gx2 = GRADIENTS_2_D[gi2], gy2 = GRADIENTS_2_D[gi2 | 1];
double rampValue2 = gx2 * x2 + gy2 * y2;
out[0] += aaaa2 * rampValue2;
out[1] += gx2 * aaaa2 - 8 * rampValue2 * aaa2 * x2;
out[2] += gy2 * aaaa2 - 8 * rampValue2 * aaa2 * y2;
}
}
if(yi - xmyi > 1) {
double x3 = x0 + (3 * G2 - 1);
double y3 = y0 + (3 * G2 - 2);
double a3 = (2.0 / 3.0) - x3 * x3 - y3 * y3;
if(a3 > 0) {
double aa3 = a3 * a3, aaa3 = aa3 * a3, aaaa3 = aa3 * aa3;
int gi3 = gradCoordIndex(seed, i + PRIME_X, j + (PRIME_Y << 1));
double gx3 = GRADIENTS_2_D[gi3], gy3 = GRADIENTS_2_D[gi3 | 1];
double rampValue3 = gx3 * x3 + gy3 * y3;
out[0] += aaaa3 * rampValue3;
out[1] += gx3 * aaaa3 - 8 * rampValue3 * aaa3 * x3;
out[2] += gy3 * aaaa3 - 8 * rampValue3 * aaa3 * y3;
}
} else {
double x3 = x0 + (G2 - 1);
double y3 = y0 + G2;
double a3 = (2.0 / 3.0) - x3 * x3 - y3 * y3;
if(a3 > 0) {
double aa3 = a3 * a3, aaa3 = aa3 * a3, aaaa3 = aa3 * aa3;
int gi3 = gradCoordIndex(seed, i + PRIME_X, j);
double gx3 = GRADIENTS_2_D[gi3], gy3 = GRADIENTS_2_D[gi3 | 1];
double rampValue3 = gx3 * x3 + gy3 * y3;
out[0] += aaaa3 * rampValue3;
out[1] += gx3 * aaaa3 - 8 * rampValue3 * aaa3 * x3;
out[2] += gy3 * aaaa3 - 8 * rampValue3 * aaa3 * y3;
}
}
} else {
if(xi + xmyi < 0) {
double x2 = x0 + (1 - G2);
double y2 = y0 - G2;
double a2 = (2.0 / 3.0) - x2 * x2 - y2 * y2;
if(a2 > 0) {
double aa2 = a2 * a2, aaa2 = aa2 * a2, aaaa2 = aa2 * aa2;
int gi2 = gradCoordIndex(seed, i - PRIME_X, j);
double gx2 = GRADIENTS_2_D[gi2], gy2 = GRADIENTS_2_D[gi2 | 1];
double rampValue2 = gx2 * x2 + gy2 * y2;
out[0] += aaaa2 * rampValue2;
out[1] += gx2 * aaaa2 - 8 * rampValue2 * aaa2 * x2;
out[2] += gy2 * aaaa2 - 8 * rampValue2 * aaa2 * y2;
}
} else {
double x2 = x0 + (G2 - 1);
double y2 = y0 + G2;
double a2 = (2.0 / 3.0) - x2 * x2 - y2 * y2;
if(a2 > 0) {
double aa2 = a2 * a2, aaa2 = aa2 * a2, aaaa2 = aa2 * aa2;
int gi2 = gradCoordIndex(seed, i + PRIME_X, j);
double gx2 = GRADIENTS_2_D[gi2], gy2 = GRADIENTS_2_D[gi2 | 1];
double rampValue2 = gx2 * x2 + gy2 * y2;
out[0] += aaaa2 * rampValue2;
out[1] += gx2 * aaaa2 - 8 * rampValue2 * aaa2 * x2;
out[2] += gy2 * aaaa2 - 8 * rampValue2 * aaa2 * y2;
}
}
if(yi < xmyi) {
double x2 = x0 - G2;
double y2 = y0 - (G2 - 1);
double a2 = (2.0 / 3.0) - x2 * x2 - y2 * y2;
if(a2 > 0) {
double aa2 = a2 * a2, aaa2 = aa2 * a2, aaaa2 = aa2 * aa2;
int gi2 = gradCoordIndex(seed, i, j - PRIME_Y);
double gx2 = GRADIENTS_2_D[gi2], gy2 = GRADIENTS_2_D[gi2 | 1];
double rampValue2 = gx2 * x2 + gy2 * y2;
out[0] += aaaa2 * rampValue2;
out[1] += gx2 * aaaa2 - 8 * rampValue2 * aaa2 * x2;
out[2] += gy2 * aaaa2 - 8 * rampValue2 * aaa2 * y2;
}
} else {
double x2 = x0 + G2;
double y2 = y0 + (G2 - 1);
double a2 = (2.0 / 3.0) - x2 * x2 - y2 * y2;
if(a2 > 0) {
double aa2 = a2 * a2, aaa2 = aa2 * a2, aaaa2 = aa2 * aa2;
int gi2 = gradCoordIndex(seed, i, j + PRIME_Y);
double gx2 = GRADIENTS_2_D[gi2], gy2 = GRADIENTS_2_D[gi2 | 1];
double rampValue2 = gx2 * x2 + gy2 * y2;
out[0] += aaaa2 * rampValue2;
out[1] += gx2 * aaaa2 - 8 * rampValue2 * aaa2 * x2;
out[2] += gy2 * aaaa2 - 8 * rampValue2 * aaa2 * y2;
}
}
}
out[0] *= 18.24196194486065;
out[1] *= 18.24196194486065;
out[2] *= 18.24196194486065;
return out;
}
@Override
public double[] getNoiseDerivativeRaw(long sl, double x, double y, double z) {
int seed = (int) sl;
// 3D OpenSimplex2S case uses two offset rotated cube grids.
final double R3 = (2.0 / 3.0);
double r = (x + y + z) * R3; // Rotation, not skew
x = r - x;
y = r - y;
z = r - z;
int i = (int) Math.floor(x);
int j = (int) Math.floor(y);
int k = (int) Math.floor(z);
double xi = x - i;
double yi = y - j;
double zi = z - k;
i *= PRIME_X;
j *= PRIME_Y;
k *= PRIME_Z;
int seed2 = seed + 1293373;
int xNMask = (int) (-0.5 - xi);
int yNMask = (int) (-0.5 - yi);
int zNMask = (int) (-0.5 - zi);
double[] out = { 0.0f, 0.0f, 0.0f, 0.0f };
double x0 = xi + xNMask;
double y0 = yi + yNMask;
double z0 = zi + zNMask;
double a0 = 0.75 - x0 * x0 - y0 * y0 - z0 * z0;
double aa0 = a0 * a0, aaa0 = aa0 * a0, aaaa0 = aa0 * aa0;
int gi0 = gradCoordIndex(seed, i + (xNMask & PRIME_X), j + (yNMask & PRIME_Y), k + (zNMask & PRIME_Z));
double gx0 = GRADIENTS_3D[gi0], gy0 = GRADIENTS_3D[gi0 | 1], gz0 = GRADIENTS_3D[gi0 | 2];
double rampValue0 = gx0 * x0 + gy0 * y0 + gz0 * z0;
out[0] = aaaa0 * rampValue0;
out[1] = gx0 * aaaa0 - 8 * rampValue0 * aaa0 * x0;
out[2] = gy0 * aaaa0 - 8 * rampValue0 * aaa0 * y0;
out[3] = gz0 * aaaa0 - 8 * rampValue0 * aaa0 * z0;
double x1 = xi - 0.5;
double y1 = yi - 0.5;
double z1 = zi - 0.5;
double a1 = 0.75 - x1 * x1 - y1 * y1 - z1 * z1;
double aa1 = a1 * a1, aaa1 = aa1 * a1, aaaa1 = aa1 * aa1;
int gi1 = gradCoordIndex(seed2, i + PRIME_X, j + PRIME_Y, k + PRIME_Z);
double gx1 = GRADIENTS_3D[gi1], gy1 = GRADIENTS_3D[gi1 | 1], gz1 = GRADIENTS_3D[gi1 | 2];
double rampValue1 = gx1 * x1 + gy1 * y1 + gz1 * z1;
out[0] += aaaa1 * rampValue1;
out[1] += gx1 * aaaa1 - 8 * rampValue1 * aaa1 * x1;
out[2] += gy1 * aaaa1 - 8 * rampValue1 * aaa1 * y1;
out[3] += gz1 * aaaa1 - 8 * rampValue1 * aaa1 * z1;
double xAFlipMask0 = ((xNMask | 1) << 1) * x1;
double yAFlipMask0 = ((yNMask | 1) << 1) * y1;
double zAFlipMask0 = ((zNMask | 1) << 1) * z1;
double xAFlipMask1 = (-2 - (xNMask << 2)) * x1 - 1.0;
double yAFlipMask1 = (-2 - (yNMask << 2)) * y1 - 1.0;
double zAFlipMask1 = (-2 - (zNMask << 2)) * z1 - 1.0;
boolean skip5 = false;
double a2 = xAFlipMask0 + a0;
if(a2 > 0) {
double x2 = x0 - (xNMask | 1);
double aa2 = a2 * a2, aaa2 = aa2 * a2, aaaa2 = aa2 * aa2;
int gi2 = gradCoordIndex(seed, i + (~xNMask & PRIME_X), j + (yNMask & PRIME_Y), k + (zNMask & PRIME_Z));
double gx2 = GRADIENTS_3D[gi2], gy2 = GRADIENTS_3D[gi2 | 1], gz2 = GRADIENTS_3D[gi2 | 2];
double rampValue2 = gx2 * x2 + gy2 * y0 + gz2 * z0;
out[0] += aaaa2 * rampValue2;
out[1] += gx2 * aaaa2 - 8 * rampValue2 * aaa2 * x2;
out[2] += gy2 * aaaa2 - 8 * rampValue2 * aaa2 * y0;
out[3] += gz2 * aaaa2 - 8 * rampValue2 * aaa2 * z0;
} else {
double a3 = yAFlipMask0 + zAFlipMask0 + a0;
if(a3 > 0) {
double y3 = y0 - (yNMask | 1);
double z3 = z0 - (zNMask | 1);
double aa3 = a3 * a3, aaa3 = aa3 * a3, aaaa3 = aa3 * aa3;
int gi3 = gradCoordIndex(seed, i + (xNMask & PRIME_X), j + (~yNMask & PRIME_Y), k + (~zNMask & PRIME_Z));
double gx3 = GRADIENTS_3D[gi3], gy3 = GRADIENTS_3D[gi3 | 1], gz3 = GRADIENTS_3D[gi3 | 2];
double rampValue3 = gx3 * x0 + gy3 * y3 + gz3 * z3;
out[0] += aaaa3 * rampValue3;
out[1] += gx3 * aaaa3 - 8 * rampValue3 * aaa3 * x0;
out[2] += gy3 * aaaa3 - 8 * rampValue3 * aaa3 * y3;
out[3] += gz3 * aaaa3 - 8 * rampValue3 * aaa3 * z3;
}
double a4 = xAFlipMask1 + a1;
if(a4 > 0) {
double x4 = (xNMask | 1) + x1;
double aa4 = a4 * a4, aaa4 = aa4 * a4, aaaa4 = aa4 * aa4;
int gi4 = gradCoordIndex(seed2, i + (xNMask & (PRIME_X << 1)), j + PRIME_Y, k + PRIME_Z);
double gx4 = GRADIENTS_3D[gi4], gy4 = GRADIENTS_3D[gi4 | 1], gz4 = GRADIENTS_3D[gi4 | 2];
double rampValue4 = gx4 * x4 + gy4 * y1 + gz4 * z1;
out[0] += aaaa4 * rampValue4;
out[1] += gx4 * aaaa4 - 8 * rampValue4 * aaa4 * x4;
out[2] += gy4 * aaaa4 - 8 * rampValue4 * aaa4 * y1;
out[3] += gz4 * aaaa4 - 8 * rampValue4 * aaa4 * z1;
skip5 = true;
}
}
boolean skip9 = false;
double a6 = yAFlipMask0 + a0;
if(a6 > 0) {
double y6 = y0 - (yNMask | 1);
double aa6 = a6 * a6, aaa6 = aa6 * a6, aaaa6 = aa6 * aa6;
int gi6 = gradCoordIndex(seed, i + (xNMask & PRIME_X), j + (~yNMask & PRIME_Y), k + (zNMask & PRIME_Z));
double gx6 = GRADIENTS_3D[gi6], gy6 = GRADIENTS_3D[gi6 | 1], gz6 = GRADIENTS_3D[gi6 | 2];
double rampValue6 = gx6 * x0 + gy6 * y6 + gz6 * z0;
out[0] += aaaa6 * rampValue6;
out[1] += gx6 * aaaa6 - 8 * rampValue6 * aaa6 * x0;
out[2] += gy6 * aaaa6 - 8 * rampValue6 * aaa6 * y6;
out[3] += gz6 * aaaa6 - 8 * rampValue6 * aaa6 * z0;
} else {
double a7 = xAFlipMask0 + zAFlipMask0 + a0;
if(a7 > 0) {
double x7 = x0 - (xNMask | 1);
double z7 = z0 - (zNMask | 1);
double aa7 = a7 * a7, aaa7 = aa7 * a7, aaaa7 = aa7 * aa7;
int gi7 = gradCoordIndex(seed, i + (~xNMask & PRIME_X), j + (yNMask & PRIME_Y), k + (~zNMask & PRIME_Z));
double gx7 = GRADIENTS_3D[gi7], gy7 = GRADIENTS_3D[gi7 | 1], gz7 = GRADIENTS_3D[gi7 | 2];
double rampValue7 = gx7 * x7 + gy7 * y0 + gz7 * z7;
out[0] += aaaa7 * rampValue7;
out[1] += gx7 * aaaa7 - 8 * rampValue7 * aaa7 * x7;
out[2] += gy7 * aaaa7 - 8 * rampValue7 * aaa7 * y0;
out[3] += gz7 * aaaa7 - 8 * rampValue7 * aaa7 * z7;
}
double a8 = yAFlipMask1 + a1;
if(a8 > 0) {
double y8 = (yNMask | 1) + y1;
double aa8 = a8 * a8, aaa8 = aa8 * a8, aaaa8 = aa8 * aa8;
int gi8 = gradCoordIndex(seed2, i + PRIME_X, j + (yNMask & (PRIME_Y << 1)), k + PRIME_Z);
double gx8 = GRADIENTS_3D[gi8], gy8 = GRADIENTS_3D[gi8 | 1], gz8 = GRADIENTS_3D[gi8 | 2];
double rampValue8 = gx8 * x1 + gy8 * y8 + gz8 * z1;
out[0] += aaaa8 * rampValue8;
out[1] += gx8 * aaaa8 - 8 * rampValue8 * aaa8 * x1;
out[2] += gy8 * aaaa8 - 8 * rampValue8 * aaa8 * y8;
out[3] += gz8 * aaaa8 - 8 * rampValue8 * aaa8 * z1;
skip9 = true;
}
}
boolean skipD = false;
double aA = zAFlipMask0 + a0;
if(aA > 0) {
double zA = z0 - (zNMask | 1);
double aaA = aA * aA, aaaA = aaA * aA, aaaaA = aaA * aaA;
int giA = gradCoordIndex(seed, i + (xNMask & PRIME_X), j + (yNMask & PRIME_Y), k + (~zNMask & PRIME_Z));
double gxA = GRADIENTS_3D[giA], gyA = GRADIENTS_3D[giA | 1], gzA = GRADIENTS_3D[giA | 2];
double rampValueA = gxA * x0 + gyA * y0 + gzA * zA;
out[0] += aaaaA * rampValueA;
out[1] += gxA * aaaaA - 8 * rampValueA * aaaA * x0;
out[2] += gyA * aaaaA - 8 * rampValueA * aaaA * y0;
out[3] += gzA * aaaaA - 8 * rampValueA * aaaA * zA;
} else {
double aB = xAFlipMask0 + yAFlipMask0 + a0;
if(aB > 0) {
double xB = x0 - (xNMask | 1);
double yB = y0 - (yNMask | 1);
double aaB = aB * aB, aaaB = aaB * aB, aaaaB = aaB * aaB;
int giB = gradCoordIndex(seed, i + (~xNMask & PRIME_X), j + (~yNMask & PRIME_Y), k + (zNMask & PRIME_Z));
double gxB = GRADIENTS_3D[giB], gyB = GRADIENTS_3D[giB | 1], gzB = GRADIENTS_3D[giB | 2];
double rampValueB = gxB * xB + gyB * yB + gzB * z0;
out[0] += aaaaB * rampValueB;
out[1] += gxB * aaaaB - 8 * rampValueB * aaaB * xB;
out[2] += gyB * aaaaB - 8 * rampValueB * aaaB * yB;
out[3] += gzB * aaaaB - 8 * rampValueB * aaaB * z0;
}
double aC = zAFlipMask1 + a1;
if(aC > 0) {
double zC = (zNMask | 1) + z1;
double aaC = aC * aC, aaaC = aaC * aC, aaaaC = aaC * aaC;
int giC = gradCoordIndex(seed2, i + PRIME_X, j + PRIME_Y, k + (zNMask & (PRIME_Z << 1)));
double gxC = GRADIENTS_3D[giC], gyC = GRADIENTS_3D[giC | 1], gzC = GRADIENTS_3D[giC | 2];
double rampValueC = gxC * x1 + gyC * y1 + gzC * zC;
out[0] += aaaaC * rampValueC;
out[1] += gxC * aaaaC - 8 * rampValueC * aaaC * x1;
out[2] += gyC * aaaaC - 8 * rampValueC * aaaC * y1;
out[3] += gzC * aaaaC - 8 * rampValueC * aaaC * zC;
skipD = true;
}
}
if(!skip5) {
double a5 = yAFlipMask1 + zAFlipMask1 + a1;
if(a5 > 0) {
double y5 = (yNMask | 1) + y1;
double z5 = (zNMask | 1) + z1;
double aa5 = a5 * a5, aaa5 = aa5 * a5, aaaa5 = aa5 * aa5;
int gi5 = gradCoordIndex(seed2, i + PRIME_X, j + (yNMask & (PRIME_Y << 1)), k + (zNMask & (PRIME_Z << 1)));
double gx5 = GRADIENTS_3D[gi5], gy5 = GRADIENTS_3D[gi5 | 1], gz5 = GRADIENTS_3D[gi5 | 2];
double rampValue5 = gx5 * x1 + gy5 * y5 + gz5 * z5;
out[0] += aaaa5 * rampValue5;
out[1] += gx5 * aaaa5 - 8 * rampValue5 * aaa5 * x1;
out[2] += gy5 * aaaa5 - 8 * rampValue5 * aaa5 * y5;
out[3] += gz5 * aaaa5 - 8 * rampValue5 * aaa5 * z5;
}
}
if(!skip9) {
double a9 = xAFlipMask1 + zAFlipMask1 + a1;
if(a9 > 0) {
double x9 = (xNMask | 1) + x1;
double z9 = (zNMask | 1) + z1;
double aa9 = a9 * a9, aaa9 = aa9 * a9, aaaa9 = aa9 * aa9;
int gi9 = gradCoordIndex(seed2, i + (xNMask & (PRIME_X << 1)), j + PRIME_Y, k + (zNMask & (PRIME_Z << 1)));
double gx9 = GRADIENTS_3D[gi9], gy9 = GRADIENTS_3D[gi9 | 1], gz9 = GRADIENTS_3D[gi9 | 2];
double rampValue9 = gx9 * x9 + gy9 * y1 + gz9 * z9;
out[0] += aaaa9 * rampValue9;
out[1] += gx9 * aaaa9 - 8 * rampValue9 * aaa9 * x9;
out[2] += gy9 * aaaa9 - 8 * rampValue9 * aaa9 * y1;
out[3] += gz9 * aaaa9 - 8 * rampValue9 * aaa9 * z9;
}
}
if(!skipD) {
double aD = xAFlipMask1 + yAFlipMask1 + a1;
if(aD > 0) {
double xD = (xNMask | 1) + x1;
double yD = (yNMask | 1) + y1;
double aaD = aD * aD, aaaD = aaD * aD, aaaaD = aaD * aaD;
int giD = gradCoordIndex(seed2, i + (xNMask & (PRIME_X << 1)), j + (yNMask & (PRIME_Y << 1)), k + PRIME_Z);
double gxD = GRADIENTS_3D[giD], gyD = GRADIENTS_3D[giD | 1], gzD = GRADIENTS_3D[giD | 2];
double rampValueD = gxD * xD + gyD * yD + gzD * z1;
out[0] += aaaaD * rampValueD;
out[1] += gxD * aaaaD - 8 * rampValueD * aaaD * xD;
out[2] += gyD * aaaaD - 8 * rampValueD * aaaD * yD;
out[3] += gzD * aaaaD - 8 * rampValueD * aaaD * z1;
}
}
out[0] *= 9.046026385208288;
out[1] *= 9.046026385208288;
out[2] *= 9.046026385208288;
out[3] *= 9.046026385208288;
return out;
}
}
@@ -37,37 +37,41 @@ public class OpenSimplex2Sampler extends SimplexStyleSampler {
i *= PRIME_X;
j *= PRIME_Y;
double value = 0;
double n0, n1, n2;
double a = 0.5 - x0 * x0 - y0 * y0;
if(a > 0) {
value = (a * a) * (a * a) * gradCoord(seed, i, j, x0, y0);
if(a <= 0) n0 = 0;
else {
n0 = (a * a) * (a * a) * gradCoord(seed, i, j, x0, y0);
}
double c = 2 * (1 - 2 * G2) * (1 / G2 - 2) * t + ((-2 * (1 - 2 * G2) * (1 - 2 * G2)) + a);
if(c > 0) {
if(c <= 0) n2 = 0;
else {
double x2 = x0 + (2 * G2 - 1);
double y2 = y0 + (2 * G2 - 1);
value += (c * c) * (c * c) * gradCoord(seed, i + PRIME_X, j + PRIME_Y, x2, y2);
n2 = (c * c) * (c * c) * gradCoord(seed, i + PRIME_X, j + PRIME_Y, x2, y2);
}
if(y0 > x0) {
double x1 = x0 + G2;
double y1 = y0 + (G2 - 1);
double b = 0.5 - x1 * x1 - y1 * y1;
if(b > 0) {
value += (b * b) * (b * b) * gradCoord(seed, i, j + PRIME_Y, x1, y1);
if(b <= 0) n1 = 0;
else {
n1 = (b * b) * (b * b) * gradCoord(seed, i, j + PRIME_Y, x1, y1);
}
} else {
double x1 = x0 + (G2 - 1);
double y1 = y0 + G2;
double b = 0.5 - x1 * x1 - y1 * y1;
if(b > 0) {
value += (b * b) * (b * b) * gradCoord(seed, i + PRIME_X, j, x1, y1);
if(b <= 0) n1 = 0;
else {
n1 = (b * b) * (b * b) * gradCoord(seed, i + PRIME_X, j, x1, y1);
}
}
return value * 99.83685446303647f;
return (n0 + n1 + n2) * 99.83685446303647f;
}
@Override
@@ -153,208 +157,4 @@ public class OpenSimplex2Sampler extends SimplexStyleSampler {
return value * 32.69428253173828125;
}
@Override
public boolean isDifferentiable() {
return true;
}
@Override
public double[] getNoiseDerivativeRaw(long sl, double x, double y) {
int seed = (int) sl;
// 2D OpenSimplex2 case uses the same algorithm as ordinary Simplex.
final double G2 = (3 - SQRT3) / 6;
final double F2 = 0.5f * (SQRT3 - 1);
double s = (x + y) * F2;
x += s;
y += s;
int i = (int) Math.floor(x);
int j = (int) Math.floor(y);
double xi = x - i;
double yi = y - j;
double t = (xi + yi) * G2;
double x0 = xi - t;
double y0 = yi - t;
i *= PRIME_X;
j *= PRIME_Y;
double[] out = { 0.0f, 0.0f, 0.0f };
double a = 0.5 - x0 * x0 - y0 * y0;
if(a > 0) {
double aa = a * a, aaa = aa * a, aaaa = aa * aa;
int gi = gradCoordIndex(seed, i, j);
double gx = GRADIENTS_2_D[gi], gy = GRADIENTS_2_D[gi | 1];
double rampValue = gx * x0 + gy * y0;
out[0] += aaaa * rampValue;
out[1] += gx * aaaa - 8 * rampValue * aaa * x0;
out[2] += gy * aaaa - 8 * rampValue * aaa * y0;
}
double c = 2 * (1 - 2 * G2) * (1 / G2 - 2) * t + ((-2 * (1 - 2 * G2) * (1 - 2 * G2)) + a);
if(c > 0) {
double x2 = x0 + (2 * G2 - 1);
double y2 = y0 + (2 * G2 - 1);
double cc = c * c, ccc = cc * c, cccc = cc * cc;
int gi = gradCoordIndex(seed, i + PRIME_X, j + PRIME_Y);
double gx = GRADIENTS_2_D[gi], gy = GRADIENTS_2_D[gi | 1];
double rampValue = gx * x2 + gy * y2;
out[0] += cccc * rampValue;
out[1] += gx * cccc - 8 * rampValue * ccc * x2;
out[2] += gy * cccc - 8 * rampValue * ccc * y2;
}
if(y0 > x0) {
double x1 = x0 + G2;
double y1 = y0 + (G2 - 1);
double b = 0.5 - x1 * x1 - y1 * y1;
if(b > 0) {
double bb = b * b, bbb = bb * b, bbbb = bb * bb;
int gi = gradCoordIndex(seed, i, j + PRIME_Y);
double gx = GRADIENTS_2_D[gi], gy = GRADIENTS_2_D[gi | 1];
double rampValue = gx * x1 + gy * y1;
out[0] += bbbb * rampValue;
out[1] += gx * bbbb - 8 * rampValue * bbb * x1;
out[2] += gy * bbbb - 8 * rampValue * bbb * y1;
}
} else {
double x1 = x0 + (G2 - 1);
double y1 = y0 + G2;
double b = 0.5 - x1 * x1 - y1 * y1;
if(b > 0) {
double bb = b * b, bbb = bb * b, bbbb = bb * bb;
int gi = gradCoordIndex(seed, i + PRIME_X, j);
double gx = GRADIENTS_2_D[gi], gy = GRADIENTS_2_D[gi | 1];
double rampValue = gx * x1 + gy * y1;
out[0] += bbbb * rampValue;
out[1] += gx * bbbb - 8 * rampValue * bbb * x1;
out[2] += gy * bbbb - 8 * rampValue * bbb * y1;
}
}
out[0] *= 99.83685446303647f;
out[1] *= 99.83685446303647f;
out[2] *= 99.83685446303647f;
return out;
}
@Override
public double[] getNoiseDerivativeRaw(long sl, double x, double y, double z) {
int seed = (int) sl;
// 3D OpenSimplex2Sampler case uses two offset rotated cube grids.
final double R3 = (2.0 / 3.0);
double r = (x + y + z) * R3; // Rotation, not skew
x = r - x;
y = r - y;
z = r - z;
int i = (int) Math.round(x);
int j = (int) Math.round(y);
int k = (int) Math.round(z);
double x0 = x - i;
double y0 = y - j;
double z0 = z - k;
int xNSign = (int) (-1.0 - x0) | 1;
int yNSign = (int) (-1.0 - y0) | 1;
int zNSign = (int) (-1.0 - z0) | 1;
double ax0 = xNSign * -x0;
double ay0 = yNSign * -y0;
double az0 = zNSign * -z0;
i *= PRIME_X;
j *= PRIME_Y;
k *= PRIME_Z;
double[] out = { 0.0f, 0.0f, 0.0f, 0.0f };
double a = (0.6f - x0 * x0) - (y0 * y0 + z0 * z0);
for(int l = 0; ; l++) {
if(a > 0) {
double aa = a * a, aaa = aa * a, aaaa = aa * aa;
int gi = gradCoordIndex(seed, i, j, k);
double gx = GRADIENTS_3D[gi], gy = GRADIENTS_3D[gi | 1], gz = GRADIENTS_3D[gi | 2];
double rampValue = gx * x0 + gy * y0 + gz * z0;
out[0] += aaaa * rampValue;
out[1] += gx * aaaa - 8 * rampValue * aaa * x0;
out[1] += gy * aaaa - 8 * rampValue * aaa * y0;
out[2] += gz * aaaa - 8 * rampValue * aaa * z0;
}
if(ax0 >= ay0 && ax0 >= az0) {
double b = a + ax0 + ax0;
if(b > 1) {
b -= 1;
double bb = b * b, bbb = bb * b, bbbb = bb * bb;
int gi = gradCoordIndex(seed, i - xNSign * PRIME_X, j, k);
double gx = GRADIENTS_3D[gi], gy = GRADIENTS_3D[gi | 1], gz = GRADIENTS_3D[gi | 2];
double rampValue = gx * (x0 + xNSign) + gy * y0 + gz * z0;
out[0] += bbbb * rampValue;
out[1] += gx * bbbb - 8 * rampValue * bbb * (x0 + xNSign);
out[1] += gy * bbbb - 8 * rampValue * bbb * y0;
out[2] += gz * bbbb - 8 * rampValue * bbb * z0;
}
} else if(ay0 > ax0 && ay0 >= az0) {
double b = a + ay0 + ay0;
if(b > 1) {
b -= 1;
double bb = b * b, bbb = bb * b, bbbb = bb * bb;
int gi = gradCoordIndex(seed, i, j - yNSign * PRIME_Y, k);
double gx = GRADIENTS_3D[gi], gy = GRADIENTS_3D[gi | 1], gz = GRADIENTS_3D[gi | 2];
double rampValue = gx * x0 + gy * (y0 + yNSign) + gz * z0;
out[0] += bbbb * rampValue;
out[1] += gx * bbbb - 8 * rampValue * bbb * x0;
out[1] += gy * bbbb - 8 * rampValue * bbb * (y0 + yNSign);
out[2] += gz * bbbb - 8 * rampValue * bbb * z0;
}
} else {
double b = a + az0 + az0;
if(b > 1) {
b -= 1;
double bb = b * b, bbb = bb * b, bbbb = bb * bb;
int gi = gradCoordIndex(seed, i, j, k - zNSign * PRIME_Z);
double gx = GRADIENTS_3D[gi], gy = GRADIENTS_3D[gi | 1], gz = GRADIENTS_3D[gi | 2];
double rampValue = gx * x0 + gy * y0 + gz * (z0 + zNSign);
out[0] += bbbb * rampValue;
out[1] += gx * bbbb - 8 * rampValue * bbb * x0;
out[1] += gy * bbbb - 8 * rampValue * bbb * y0;
out[2] += gz * bbbb - 8 * rampValue * bbb * (z0 + zNSign);
}
}
if(l == 1) break;
ax0 = 0.5 - ax0;
ay0 = 0.5 - ay0;
az0 = 0.5 - az0;
x0 = xNSign * ax0;
y0 = yNSign * ay0;
z0 = zNSign * az0;
a += (0.75 - ax0) - (ay0 + az0);
i += (xNSign >> 1) & PRIME_X;
j += (yNSign >> 1) & PRIME_Y;
k += (zNSign >> 1) & PRIME_Z;
xNSign = -xNSign;
yNSign = -yNSign;
zNSign = -zNSign;
seed = ~seed;
}
out[0] *= 32.69428253173828125;
out[1] *= 32.69428253173828125;
out[2] *= 32.69428253173828125;
out[3] *= 32.69428253173828125;
return out;
}
}
@@ -33,10 +33,10 @@ public class PerlinSampler extends SimplexStyleSampler {
int x1 = x0 + PRIME_X;
int y1 = y0 + PRIME_Y;
double xf0 = MathUtil.lerp(xs, gradCoord(seed, x0, y0, xd0, yd0), gradCoord(seed, x1, y0, xd1, yd0));
double xf1 = MathUtil.lerp(xs, gradCoord(seed, x0, y1, xd0, yd1), gradCoord(seed, x1, y1, xd1, yd1));
double xf0 = MathUtil.lerp(gradCoord(seed, x0, y0, xd0, yd0), gradCoord(seed, x1, y0, xd1, yd0), xs);
double xf1 = MathUtil.lerp(gradCoord(seed, x0, y1, xd0, yd1), gradCoord(seed, x1, y1, xd1, yd1), xs);
return MathUtil.lerp(ys, xf0, xf1) * 1.4247691104677813;
return MathUtil.lerp(xf0, xf1, ys) * 1.4247691104677813;
}
@Override
@@ -64,14 +64,14 @@ public class PerlinSampler extends SimplexStyleSampler {
int y1 = y0 + PRIME_Y;
int z1 = z0 + PRIME_Z;
double xf00 = MathUtil.lerp(xs, gradCoord(seed, x0, y0, z0, xd0, yd0, zd0), gradCoord(seed, x1, y0, z0, xd1, yd0, zd0));
double xf10 = MathUtil.lerp(xs, gradCoord(seed, x0, y1, z0, xd0, yd1, zd0), gradCoord(seed, x1, y1, z0, xd1, yd1, zd0));
double xf01 = MathUtil.lerp(xs, gradCoord(seed, x0, y0, z1, xd0, yd0, zd1), gradCoord(seed, x1, y0, z1, xd1, yd0, zd1));
double xf11 = MathUtil.lerp(xs, gradCoord(seed, x0, y1, z1, xd0, yd1, zd1), gradCoord(seed, x1, y1, z1, xd1, yd1, zd1));
double xf00 = MathUtil.lerp(gradCoord(seed, x0, y0, z0, xd0, yd0, zd0), gradCoord(seed, x1, y0, z0, xd1, yd0, zd0), xs);
double xf10 = MathUtil.lerp(gradCoord(seed, x0, y1, z0, xd0, yd1, zd0), gradCoord(seed, x1, y1, z0, xd1, yd1, zd0), xs);
double xf01 = MathUtil.lerp(gradCoord(seed, x0, y0, z1, xd0, yd0, zd1), gradCoord(seed, x1, y0, z1, xd1, yd0, zd1), xs);
double xf11 = MathUtil.lerp(gradCoord(seed, x0, y1, z1, xd0, yd1, zd1), gradCoord(seed, x1, y1, z1, xd1, yd1, zd1), xs);
double yf0 = MathUtil.lerp(ys, xf00, xf10);
double yf1 = MathUtil.lerp(ys, xf01, xf11);
double yf0 = MathUtil.lerp(xf00, xf10, ys);
double yf1 = MathUtil.lerp(xf01, xf11, ys);
return MathUtil.lerp(zs, yf0, yf1) * 0.964921414852142333984375;
return MathUtil.lerp(yf0, yf1, zs) * 0.964921414852142333984375;
}
}
@@ -7,13 +7,13 @@
package com.dfsek.terra.addons.noise.samplers.noise.simplex;
import com.dfsek.terra.addons.noise.samplers.noise.DerivativeNoiseFunction;
import com.dfsek.terra.addons.noise.samplers.noise.NoiseFunction;
/**
* Abstract NoiseSampler implementation for simplex-style noise functions.
*/
public abstract class SimplexStyleSampler extends DerivativeNoiseFunction {
public abstract class SimplexStyleSampler extends NoiseFunction {
protected static final double[] GRADIENTS_2_D = {
0.130526192220052d, 0.99144486137381d, 0.38268343236509d, 0.923879532511287d, 0.608761429008721d, 0.793353340291235d,
0.793353340291235d, 0.608761429008721d, 0.923879532511287d, 0.38268343236509d, 0.99144486137381d, 0.130526192220051d,
@@ -79,53 +79,26 @@ public abstract class SimplexStyleSampler extends DerivativeNoiseFunction {
1, 1, 0, 0, 0, -1, 1, 0, -1, 1, 0, 0, 0, -1, -1, 0
};
protected static int gradCoordIndex(int seed, int xPrimed, int yPrimed) {
protected static double gradCoord(int seed, int xPrimed, int yPrimed, double xd, double yd) {
int hash = hash(seed, xPrimed, yPrimed);
hash ^= hash >> 15;
hash &= 127 << 1;
return hash;
}
protected static double gradCoord(int seed, int xPrimed, int yPrimed, double xd, double yd) {
int index = gradCoordIndex(seed, xPrimed, yPrimed);
double xg = GRADIENTS_2_D[index];
double yg = GRADIENTS_2_D[index | 1];
double xg = GRADIENTS_2_D[hash];
double yg = GRADIENTS_2_D[hash | 1];
return xd * xg + yd * yg;
}
protected static int gradCoordIndex(int seed, int xPrimed, int yPrimed, int zPrimed) {
protected static double gradCoord(int seed, int xPrimed, int yPrimed, int zPrimed, double xd, double yd, double zd) {
int hash = hash(seed, xPrimed, yPrimed, zPrimed);
hash ^= hash >> 15;
hash &= 63 << 2;
return hash;
}
protected static double gradCoord(int seed, int xPrimed, int yPrimed, int zPrimed, double xd, double yd, double zd) {
int index = gradCoordIndex(seed, xPrimed, yPrimed, zPrimed);
double xg = GRADIENTS_3D[index];
double yg = GRADIENTS_3D[index | 1];
double zg = GRADIENTS_3D[index | 2];
double xg = GRADIENTS_3D[hash];
double yg = GRADIENTS_3D[hash | 1];
double zg = GRADIENTS_3D[hash | 2];
return xd * xg + yd * yg + zd * zg;
}
@Override
public double[] getNoiseDerivativeRaw(long seed, double x, double y) {
return new double[]{ 0, 0, 0 };
}
@Override
public double[] getNoiseDerivativeRaw(long seed, double x, double y, double z) {
return new double[]{ 0, 0, 0, 0 };
}
@Override
public boolean isDifferentiable() {
return false;
}
}
@@ -25,10 +25,10 @@ public class ValueSampler extends ValueStyleNoise {
int x1 = x0 + PRIME_X;
int y1 = y0 + PRIME_Y;
double xf0 = MathUtil.lerp(xs, valCoord(seed, x0, y0), valCoord(seed, x1, y0));
double xf1 = MathUtil.lerp(xs, valCoord(seed, x0, y1), valCoord(seed, x1, y1));
double xf0 = MathUtil.lerp(valCoord(seed, x0, y0), valCoord(seed, x1, y0), xs);
double xf1 = MathUtil.lerp(valCoord(seed, x0, y1), valCoord(seed, x1, y1), xs);
return MathUtil.lerp(ys, xf0, xf1);
return MathUtil.lerp(xf0, xf1, ys);
}
@Override
@@ -49,14 +49,14 @@ public class ValueSampler extends ValueStyleNoise {
int y1 = y0 + PRIME_Y;
int z1 = z0 + PRIME_Z;
double xf00 = MathUtil.lerp(xs, valCoord(seed, x0, y0, z0), valCoord(seed, x1, y0, z0));
double xf10 = MathUtil.lerp(xs, valCoord(seed, x0, y1, z0), valCoord(seed, x1, y1, z0));
double xf01 = MathUtil.lerp(xs, valCoord(seed, x0, y0, z1), valCoord(seed, x1, y0, z1));
double xf11 = MathUtil.lerp(xs, valCoord(seed, x0, y1, z1), valCoord(seed, x1, y1, z1));
double xf00 = MathUtil.lerp(valCoord(seed, x0, y0, z0), valCoord(seed, x1, y0, z0), xs);
double xf10 = MathUtil.lerp(valCoord(seed, x0, y1, z0), valCoord(seed, x1, y1, z0), xs);
double xf01 = MathUtil.lerp(valCoord(seed, x0, y0, z1), valCoord(seed, x1, y0, z1), xs);
double xf11 = MathUtil.lerp(valCoord(seed, x0, y1, z1), valCoord(seed, x1, y1, z1), xs);
double yf0 = MathUtil.lerp(ys, xf00, xf10);
double yf1 = MathUtil.lerp(ys, xf01, xf11);
double yf0 = MathUtil.lerp(xf00, xf10, ys);
double yf1 = MathUtil.lerp(xf01, xf11, ys);
return MathUtil.lerp(zs, yf0, yf1);
return MathUtil.lerp(yf0, yf1, zs);
}
}
+1 -1
View File
@@ -1,4 +1,4 @@
version = version("1.1.1")
version = version("1.1.0")
dependencies {
compileOnlyApi(project(":common:addons:manifest-addon-loader"))
@@ -8,24 +8,31 @@ import com.dfsek.terra.api.world.WritableWorld;
public class VanillaOreUtils {
private static boolean shouldExpose(Random random, double exposedChance) {
if(exposedChance >= 1.0F) return true;
if(exposedChance <= 0.0F) return false;
return random.nextFloat() < exposedChance;
protected static boolean shouldNotDiscard(Random random, double chance) {
if(chance <= 0.0F) {
return true;
} else if(chance >= 1.0F) {
return false;
} else {
return random.nextFloat() >= chance;
}
}
public static boolean shouldPlace(MaterialSet replaceable, BlockType type, Double exposedChance, Random random, WritableWorld world,
int x,
public static boolean shouldPlace(MaterialSet replaceable, BlockType type, Double exposed, Random random, WritableWorld world, int x,
int y, int z) {
if(!replaceable.contains(type)) return false;
if(shouldExpose(random, exposedChance)) return true; // Exposed blocks can be placed regardless of adjacency to air
// Adjacency is checked after determining not exposed rather than vice-versa, assuming block checks are more expensive
boolean adjacentAir = world.getBlockState(x, y, z - 1).isAir() ||
world.getBlockState(x, y, z + 1).isAir() ||
world.getBlockState(x, y - 1, z).isAir() ||
world.getBlockState(x, y + 1, z).isAir() ||
world.getBlockState(x - 1, y, z).isAir() ||
world.getBlockState(x + 1, y, z).isAir();
return !adjacentAir; // Exposed check did not pass earlier so only blocks not adjacent air should place
if(!replaceable.contains(type)) {
return false;
} else if(shouldNotDiscard(random, exposed)) {
return true;
} else {
return !(world.getBlockState(x, y, z - 1).isAir() ||
world.getBlockState(x, y, z + 1).isAir() ||
world.getBlockState(x, y - 1, z).isAir() ||
world.getBlockState(x, y + 1, z).isAir() ||
world.getBlockState(x - 1, y, z).isAir() ||
world.getBlockState(x + 1, y, z).isAir());
}
}
}
@@ -11,6 +11,13 @@ import com.dfsek.tectonic.api.config.template.dynamic.DynamicTemplate;
import com.dfsek.tectonic.api.config.template.dynamic.DynamicValue;
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import com.dfsek.terra.addons.generation.feature.config.BiomeFeatures;
import com.dfsek.terra.addons.generation.feature.config.FeatureStageTemplate;
import com.dfsek.terra.addons.manifest.api.AddonInitializer;
@@ -28,9 +35,6 @@ import com.dfsek.terra.api.util.reflection.TypeKey;
import com.dfsek.terra.api.world.biome.Biome;
import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage;
import java.util.*;
import java.util.function.Supplier;
public class FeatureGenerationAddon implements AddonInitializer {
public static final TypeKey<Supplier<ObjectTemplate<GenerationStage>>> STAGE_TYPE_KEY = new TypeKey<>() {
@@ -7,9 +7,11 @@
package com.dfsek.terra.addons.generation.feature;
import java.util.Collections;
import java.util.Random;
import com.dfsek.terra.addons.generation.feature.config.BiomeFeatures;
import com.dfsek.terra.api.Platform;
import com.dfsek.terra.api.noise.NoiseSampler;
import com.dfsek.terra.api.properties.PropertyKey;
import com.dfsek.terra.api.registry.key.StringIdentifiable;
import com.dfsek.terra.api.util.Rotation;
@@ -19,9 +21,6 @@ import com.dfsek.terra.api.world.chunk.generation.ProtoWorld;
import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage;
import com.dfsek.terra.api.world.chunk.generation.util.Column;
import java.util.Collections;
import java.util.Random;
public class FeatureGenerationStage implements GenerationStage, StringIdentifiable {
private final Platform platform;
@@ -32,20 +31,13 @@ public class FeatureGenerationStage implements GenerationStage, StringIdentifiab
private final int resolution;
private final PropertyKey<BiomeFeatures> biomeFeaturesKey;
private final NoiseSampler blendSampler;
private final boolean doBlending;
private final double blendAmplitude;
public FeatureGenerationStage(Platform platform, String id, int resolution, PropertyKey<BiomeFeatures> biomeFeaturesKey,
NoiseSampler blendSampler, double blendAmplitude) {
public FeatureGenerationStage(Platform platform, String id, int resolution, PropertyKey<BiomeFeatures> biomeFeaturesKey) {
this.platform = platform;
this.id = id;
this.profile = "feature_stage:" + id;
this.resolution = resolution;
this.biomeFeaturesKey = biomeFeaturesKey;
this.blendSampler = blendSampler;
this.doBlending = blendAmplitude != 0d;
this.blendAmplitude = blendAmplitude;
}
@Override
@@ -60,10 +52,7 @@ public class FeatureGenerationStage implements GenerationStage, StringIdentifiab
int tx = cx + chunkX;
int tz = cz + chunkZ;
world.getBiomeProvider()
.getColumn(
tx + (doBlending ? (int) (blendSampler.noise(seed, tx, tz) * blendAmplitude) : 0),
tz + (doBlending ? (int) (blendSampler.noise(seed + 1, tx, tz) * blendAmplitude) : 0),
world)
.getColumn(tx, tz, world)
.forRanges(resolution, (min, max, biome) -> {
for(int subChunkX = 0; subChunkX < resolution; subChunkX++) {
for(int subChunkZ = 0; subChunkZ < resolution; subChunkZ++) {
@@ -8,7 +8,6 @@ import com.dfsek.tectonic.api.exception.ValidationException;
import com.dfsek.terra.addons.generation.feature.FeatureGenerationStage;
import com.dfsek.terra.api.Platform;
import com.dfsek.terra.api.noise.NoiseSampler;
import com.dfsek.terra.api.properties.PropertyKey;
import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage;
@@ -23,24 +22,6 @@ public class FeatureStageTemplate implements ObjectTemplate<GenerationStage>, Va
@Default
private int resolution = 4;
@Value("blend.sampler")
@Default
private NoiseSampler blendSampler = new NoiseSampler() {
@Override
public double noise(long seed, double x, double y) {
return 0;
}
@Override
public double noise(long seed, double x, double y, double z) {
return 0;
}
};
@Value("blend.amplitude")
@Default
private double blendAmplitude = 0d;
public FeatureStageTemplate(Platform platform, PropertyKey<BiomeFeatures> biomeFeaturesKey) {
this.platform = platform;
this.biomeFeaturesKey = biomeFeaturesKey;
@@ -49,7 +30,7 @@ public class FeatureStageTemplate implements ObjectTemplate<GenerationStage>, Va
@Override
public FeatureGenerationStage get() {
return new FeatureGenerationStage(platform, id, resolution, biomeFeaturesKey, blendSampler, blendAmplitude);
return new FeatureGenerationStage(platform, id, resolution, biomeFeaturesKey);
}
@Override
@@ -1,5 +1,7 @@
package com.dfsek.terra.addons.structure.mutator;
import java.util.Random;
import com.dfsek.terra.api.registry.key.Keyed;
import com.dfsek.terra.api.registry.key.RegistryKey;
import com.dfsek.terra.api.structure.Structure;
@@ -9,8 +11,6 @@ import com.dfsek.terra.api.world.WritableWorld;
import com.dfsek.terra.api.world.util.ReadInterceptor;
import com.dfsek.terra.api.world.util.WriteInterceptor;
import java.util.Random;
public class MutatedStructure implements Structure, Keyed<MutatedStructure> {
private final RegistryKey key;
@@ -7,13 +7,13 @@
package com.dfsek.terra.addons.terrascript.script.builders;
import java.util.List;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder;
import com.dfsek.terra.addons.terrascript.script.functions.CheckBlockFunction;
import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import java.util.List;
public class CheckBlockFunctionBuilder implements FunctionBuilder<CheckBlockFunction> {
@SuppressWarnings("unchecked")
@@ -10,8 +10,8 @@ package com.dfsek.terra.addons.terrascript.script.functions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import com.dfsek.terra.addons.terrascript.parser.lang.ImplementationArguments;
import com.dfsek.terra.addons.terrascript.parser.lang.Returnable;
@@ -32,7 +32,7 @@ public class BlockFunction implements Function<Void> {
protected final Returnable<Number> x, y, z;
protected final Returnable<String> blockData;
protected final Platform platform;
private final Map<String, BlockState> data = new ConcurrentHashMap<>();
private final Map<String, BlockState> data = new HashMap<>();
private final Returnable<Boolean> overwrite;
private final Returnable<Boolean> physics;
private final Position position;
+2 -2
View File
@@ -2,10 +2,10 @@ dependencies {
api("ca.solo-studios", "strata", Versions.Libraries.strata)
compileOnlyApi("org.slf4j", "slf4j-api", Versions.Libraries.slf4j)
testImplementation("org.slf4j", "slf4j-api", Versions.Libraries.slf4j)
api("org.incendo", "cloud-core", Versions.Libraries.cloud)
api("cloud.commandframework", "cloud-core", Versions.Libraries.cloud)
api("com.dfsek.tectonic", "common", Versions.Libraries.tectonic)
api("com.github.ben-manes.caffeine", "caffeine", Versions.Libraries.caffeine)
api("com.github.ben-manes.caffeine:caffeine:3.1.0")
}
@@ -1,19 +1,18 @@
package com.dfsek.terra.api.command.arguments;
import cloud.commandframework.ArgumentDescription;
import cloud.commandframework.arguments.CommandArgument;
import cloud.commandframework.arguments.parser.ArgumentParseResult;
import cloud.commandframework.arguments.parser.ArgumentParser;
import cloud.commandframework.context.CommandContext;
import io.leangen.geantyref.TypeToken;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.incendo.cloud.component.CommandComponent;
import org.incendo.cloud.component.DefaultValue;
import org.incendo.cloud.context.CommandContext;
import org.incendo.cloud.context.CommandInput;
import org.incendo.cloud.parser.ArgumentParseResult;
import org.incendo.cloud.parser.ArgumentParser;
import org.incendo.cloud.parser.ParserDescriptor;
import org.incendo.cloud.suggestion.Suggestion;
import org.incendo.cloud.suggestion.SuggestionProvider;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.Queue;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -23,22 +22,39 @@ import com.dfsek.terra.api.registry.key.RegistryKey;
import com.dfsek.terra.api.util.reflection.TypeKey;
public class RegistryArgument {
public class RegistryArgument<T, R> extends CommandArgument<T, R> {
private RegistryArgument(
boolean required,
@NonNull String name,
Function<CommandContext<T>, Registry<R>> registryFunction,
TypeToken<R> typeToken,
@NonNull String defaultValue,
@Nullable BiFunction<CommandContext<T>, String, List<String>> suggestionsProvider,
@NonNull ArgumentDescription description
) {
super(required,
name,
new RegistryArgumentParser<>(registryFunction),
defaultValue,
typeToken,
suggestionsProvider,
description);
}
public static <T, R> Builder<T, R> builder(String name, Registry<R> registry) {
return new Builder<>(name, registry);
}
public static <T, R> CommandComponent<T> of(String name, Registry<R> registry) {
public static <T, R> CommandArgument<T, R> of(String name, Registry<R> registry) {
return RegistryArgument.<T, R>builder(name, registry).build();
}
public static <T, R> CommandComponent<T> optional(String name, Registry<R> registry) {
return RegistryArgument.<T, R>builder(name, registry).optional().build();
public static <T, R> CommandArgument<T, R> optional(String name, Registry<R> registry) {
return RegistryArgument.<T, R>builder(name, registry).asOptional().build();
}
public static <T, R> CommandComponent<T> optional(String name, Registry<R> registry, DefaultValue<T, R> defaultKey) {
return RegistryArgument.<T, R>builder(name, registry).optional(defaultKey).build();
public static <T, R> CommandArgument<T, R> optional(String name, Registry<R> registry, String defaultKey) {
return RegistryArgument.<T, R>builder(name, registry).asOptionalWithDefault(defaultKey).build();
}
@SuppressWarnings("unchecked")
@@ -47,36 +63,49 @@ public class RegistryArgument {
return new Builder<>(name, registryFunction, (TypeToken<R>) TypeToken.get(registryType.getType()));
}
public static <T, R> CommandComponent<T> of(String name, Function<CommandContext<T>, Registry<R>> registryFunction,
TypeKey<R> registryType) {
public static <T, R> CommandArgument<T, R> of(String name, Function<CommandContext<T>, Registry<R>> registryFunction,
TypeKey<R> registryType) {
return RegistryArgument.<T, R>builder(name, registryFunction, registryType).build();
}
public static <T, R> CommandComponent<T> optional(String name, Function<CommandContext<T>, Registry<R>> registryFunction,
TypeKey<R> registryType) {
return RegistryArgument.builder(name, registryFunction, registryType).optional().build();
public static <T, R> CommandArgument<T, R> optional(String name, Function<CommandContext<T>, Registry<R>> registryFunction,
TypeKey<R> registryType) {
return RegistryArgument.builder(name, registryFunction, registryType).asOptional().build();
}
public static <T, R> CommandComponent<T> optional(String name, Function<CommandContext<T>, Registry<R>> registryFunction,
TypeKey<R> registryType, DefaultValue<T, R> defaultKey) {
return RegistryArgument.builder(name, registryFunction, registryType).optional(defaultKey).build();
public static <T, R> CommandArgument<T, R> optional(String name, Function<CommandContext<T>, Registry<R>> registryFunction,
TypeKey<R> registryType, String defaultKey) {
return RegistryArgument.builder(name, registryFunction, registryType).asOptionalWithDefault(defaultKey).build();
}
public static final class Builder<T, R> extends CommandComponent.Builder<T, R> {
public static final class Builder<T, R> extends CommandArgument.Builder<T, R> {
private final Function<CommandContext<T>, Registry<R>> registryFunction;
private final TypeToken<R> typeToken;
@SuppressWarnings("unchecked")
private Builder(@NonNull String name, Registry<R> registry) {
super();
this.name(name);
this.parser(ParserDescriptor.of(
new RegistryArgumentParser<>(commandContext -> registry),
(TypeToken<R>) TypeToken.get(registry.getType().getType())));
super((TypeToken<R>) TypeToken.get(registry.getType().getType()), name);
this.registryFunction = commandContext -> registry;
this.typeToken = (TypeToken<R>) TypeToken.get(registry.getType().getType());
}
private Builder(@NonNull String name, Function<CommandContext<T>, Registry<R>> registryFunction, TypeToken<R> typeToken) {
super();
this.name(name);
this.parser(ParserDescriptor.of(new RegistryArgumentParser<>(registryFunction), typeToken));
super(typeToken, name);
this.typeToken = typeToken;
this.registryFunction = registryFunction;
}
@Override
public @NonNull RegistryArgument<T, R> build() {
return new RegistryArgument<>(
isRequired(),
getName(),
registryFunction,
typeToken,
getDefaultValue(),
getSuggestionsProvider(),
getDefaultDescription()
);
}
}
@@ -90,12 +119,12 @@ public class RegistryArgument {
@Override
public @NonNull ArgumentParseResult<@NonNull R> parse(@NonNull CommandContext<@NonNull T> commandContext,
@NonNull CommandInput commandInput) {
String input = commandInput.readString();
String next = commandInput.peekString();
if(next.equals(":")) {
input += commandInput.readString();
input += commandInput.readString();
@NonNull Queue<@NonNull String> inputQueue) {
String input = inputQueue.remove();
String next = inputQueue.peek();
if(next != null && next.equals(":")) {
input += inputQueue.remove();
input += inputQueue.remove();
}
Registry<R> registry = registryFunction.apply(commandContext);
@@ -117,17 +146,8 @@ public class RegistryArgument {
}
@Override
public @NonNull SuggestionProvider<T> suggestionProvider() {
return new SuggestionProvider<>() {
@Override
public @NonNull CompletableFuture<? extends @NonNull Iterable<? extends @NonNull Suggestion>> suggestionsFuture(
@NonNull CommandContext<T> context, @NonNull CommandInput input) {
// TODO: Verify whether this is correct
return CompletableFuture.completedFuture(registryFunction.apply(context).keys().stream().map(
registryKey -> Suggestion.suggestion(registryKey.toString())).sorted().collect(Collectors.toList()));
}
};
public @NonNull List<@NonNull String> suggestions(@NonNull CommandContext<T> commandContext, @NonNull String input) {
return registryFunction.apply(commandContext).keys().stream().map(RegistryKey::toString).sorted().collect(Collectors.toList());
}
}
}
@@ -1,10 +1,10 @@
package com.dfsek.terra.api.event.events.platform;
import cloud.commandframework.CommandManager;
import com.dfsek.terra.api.command.CommandSender;
import com.dfsek.terra.api.event.events.Event;
import org.incendo.cloud.CommandManager;
public class CommandRegistrationEvent implements Event {
private final CommandManager<CommandSender> commandManager;
@@ -1,45 +0,0 @@
package com.dfsek.terra.api.noise;
/**
* A NoiseSampler which additionally may provide a 1st directional derivative
*/
public interface DerivativeNoiseSampler extends NoiseSampler {
static boolean isDifferentiable(NoiseSampler sampler) {
if(sampler instanceof DerivativeNoiseSampler dSampler) {
return dSampler.isDifferentiable();
}
return false;
}
/**
* Samplers may or may not be able to provide a derivative depending on what
* inputs they take, this method signals whether this is the case.
*
* @return If the noise sampler provides a derivative or not
*/
boolean isDifferentiable();
/**
* Derivative return version of standard 2D noise evaluation
*
* @param seed
* @param x
* @param y
*
* @return 3 element array, in index order: noise value, partial x derivative, partial y derivative
*/
double[] noised(long seed, double x, double y);
/**
* Derivative return version of standard 3D noise evaluation
*
* @param seed
* @param x
* @param y
* @param z
*
* @return 4 element array, in index order: noise value, partial x derivative, partial y derivative, partial z derivative
*/
double[] noised(long seed, double x, double y, double z);
}
@@ -8,7 +8,6 @@
package com.dfsek.terra.api.util.reflection;
import org.jetbrains.annotations.NotNull;
import sun.misc.Unsafe;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
@@ -27,18 +26,6 @@ import java.util.stream.Stream;
public final class ReflectionUtil {
private static final Unsafe UNSAFE;
static {
try {
final Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
UNSAFE = (Unsafe) unsafeField.get(null);
} catch(NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
public static Field[] getFields(@NotNull Class<?> type) {
Field[] result = type.getDeclaredFields();
Class<?> parentClass = type.getSuperclass();
@@ -48,14 +35,6 @@ public final class ReflectionUtil {
return result;
}
public static void setFinalField(Object obj, String fieldName, Object value) throws NoSuchFieldException {
Field field = obj.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
long fieldOffset = UNSAFE.objectFieldOffset(field);
UNSAFE.putObject(obj, fieldOffset, value);
}
public static Method[] getMethods(@NotNull Class<?> type) {
Method[] result = type.getDeclaredMethods();
Class<?> parentClass = type.getSuperclass();
@@ -26,33 +26,6 @@ import com.dfsek.tectonic.api.loader.AbstractConfigLoader;
import com.dfsek.tectonic.api.loader.ConfigLoader;
import com.dfsek.tectonic.api.loader.type.TypeLoader;
import com.dfsek.tectonic.yaml.YamlConfiguration;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Multimaps;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import com.dfsek.terra.api.Platform;
import com.dfsek.terra.api.addon.BaseAddon;
@@ -83,16 +56,28 @@ import com.dfsek.terra.config.fileloaders.FolderLoader;
import com.dfsek.terra.config.fileloaders.ZIPLoader;
import com.dfsek.terra.config.loaders.GenericTemplateSupplierLoader;
import com.dfsek.terra.config.loaders.config.BufferedImageLoader;
import com.dfsek.terra.config.preprocessor.MetaListLikePreprocessor;
import com.dfsek.terra.config.preprocessor.MetaMapPreprocessor;
import com.dfsek.terra.config.preprocessor.MetaNumberPreprocessor;
import com.dfsek.terra.config.preprocessor.MetaStringPreprocessor;
import com.dfsek.terra.config.preprocessor.MetaValuePreprocessor;
import com.dfsek.terra.config.preprocessor.*;
import com.dfsek.terra.config.prototype.ProtoConfig;
import com.dfsek.terra.registry.CheckedRegistryImpl;
import com.dfsek.terra.registry.OpenRegistryImpl;
import com.dfsek.terra.registry.ShortcutHolder;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Multimaps;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.awt.image.BufferedImage;
import java.io.*;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
/**
* Represents a Terra configuration pack.
@@ -24,15 +24,14 @@ import com.dfsek.tectonic.api.depth.DepthTracker;
import com.dfsek.tectonic.api.exception.LoadException;
import com.dfsek.tectonic.api.loader.ConfigLoader;
import com.dfsek.tectonic.api.preprocessor.Result;
import com.dfsek.terra.api.config.meta.Meta;
import com.dfsek.terra.api.util.reflection.TypeKey;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.AnnotatedType;
import java.util.Map;
import com.dfsek.terra.api.config.meta.Meta;
import com.dfsek.terra.api.util.reflection.TypeKey;
public class MetaNumberPreprocessor extends MetaPreprocessor<Meta> {
public static final TypeKey<String> META_STRING_KEY = new TypeKey<@Meta String>() {
Binary file not shown.
+1 -2
View File
@@ -1,7 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionSha256Sum=1541fa36599e12857140465f3c91a97409b4512501c26f9631fb113e392c5bd1
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Vendored
+8 -8
View File
@@ -55,7 +55,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
@@ -145,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
# shellcheck disable=SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
@@ -153,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
# shellcheck disable=SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
@@ -202,11 +202,11 @@ fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
Vendored
+10 -10
View File
@@ -43,11 +43,11 @@ set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
@@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
+8 -1
View File
@@ -2,15 +2,22 @@ plugins {
id("xyz.jpenilla.run-paper") version Versions.Bukkit.runPaper
}
repositories {
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") {
name = "Sonatype"
}
}
dependencies {
shaded(project(":platforms:bukkit:common"))
shaded(project(":platforms:bukkit:nms:v1_21", configuration = "reobf"))
shaded(project(":platforms:bukkit:nms:v1_20_R2", configuration = "reobf"))
shaded("xyz.jpenilla", "reflection-remapper", Versions.Bukkit.reflectionRemapper)
}
tasks {
shadowJar {
relocate("io.papermc.lib", "com.dfsek.terra.lib.paperlib")
relocate("com.tcoded.folialib", "com.dfsek.terra.lib.folialib")
relocate("com.google.common", "com.dfsek.terra.lib.google.common")
relocate("org.apache.logging.slf4j", "com.dfsek.terra.lib.slf4j-over-log4j")
exclude("org/slf4j/**")
+4 -2
View File
@@ -8,8 +8,10 @@ dependencies {
compileOnly("io.papermc.paper", "paper-api", Versions.Bukkit.paper)
shadedApi("io.papermc", "paperlib", Versions.Bukkit.paperLib)
// TODO: 2023-11-08 When we drop support for 1.18 and 1.19, we can remove FoliaLib and instead use `RegionScheduler`,
// AsyncScheduler, or GlobalRegionScheduler.
shadedApi("com.tcoded", "FoliaLib", Versions.Bukkit.foliaLib)
shadedApi("com.google.guava", "guava", Versions.Libraries.Internal.guava)
shadedApi("org.incendo", "cloud-paper", Versions.Libraries.cloudPaper)
shadedApi("cloud.commandframework", "cloud-paper", Versions.Libraries.cloud)
}
@@ -84,8 +84,8 @@ public class PlatformImpl extends AbstractPlatform {
}
@Override
public void runPossiblyUnsafeTask(@NotNull Runnable runnable) {
plugin.getGlobalRegionScheduler().run(plugin, task -> runnable.run());
public void runPossiblyUnsafeTask(@NotNull Runnable task) {
plugin.getFoliaLib().getImpl().runAsync(task);
}
@Override
@@ -17,16 +17,14 @@
package com.dfsek.terra.bukkit;
import io.papermc.paper.threadedregions.scheduler.AsyncScheduler;
import io.papermc.paper.threadedregions.scheduler.GlobalRegionScheduler;
import cloud.commandframework.brigadier.CloudBrigadierManager;
import cloud.commandframework.bukkit.CloudBukkitCapabilities;
import cloud.commandframework.execution.CommandExecutionCoordinator;
import cloud.commandframework.paper.PaperCommandManager;
import com.tcoded.folialib.FoliaLib;
import org.bukkit.Bukkit;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.plugin.java.JavaPlugin;
import org.incendo.cloud.SenderMapper;
import org.incendo.cloud.brigadier.CloudBrigadierManager;
import org.incendo.cloud.bukkit.CloudBukkitCapabilities;
import org.incendo.cloud.execution.ExecutionCoordinator;
import org.incendo.cloud.paper.LegacyPaperCommandManager;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
@@ -34,7 +32,6 @@ import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import com.dfsek.terra.api.command.CommandSender;
import com.dfsek.terra.api.config.ConfigPack;
@@ -54,9 +51,7 @@ public class TerraBukkitPlugin extends JavaPlugin {
private final PlatformImpl platform = new PlatformImpl(this);
private final Map<String, com.dfsek.terra.api.world.chunk.generation.ChunkGenerator> generatorMap = new HashMap<>();
private AsyncScheduler asyncScheduler = this.getServer().getAsyncScheduler();
private GlobalRegionScheduler globalRegionScheduler = this.getServer().getGlobalRegionScheduler();
private final FoliaLib foliaLib = new FoliaLib(this);
@Override
public void onEnable() {
@@ -66,20 +61,16 @@ public class TerraBukkitPlugin extends JavaPlugin {
platform.getEventManager().callEvent(new PlatformInitializationEvent());
if(!Initializer.init(platform)) {
Bukkit.getPluginManager().disablePlugin(this);
return;
}
try {
LegacyPaperCommandManager<CommandSender> commandManager = getCommandSenderPaperCommandManager();
PaperCommandManager<CommandSender> commandManager = getCommandSenderPaperCommandManager();
platform.getEventManager().callEvent(new CommandRegistrationEvent(commandManager));
} catch(Exception e) { // This should never happen.
logger.error("""
TERRA HAS BEEN DISABLED
Errors occurred while registering commands.
Please report this to Terra.
""".strip(), e);
@@ -89,29 +80,27 @@ public class TerraBukkitPlugin extends JavaPlugin {
Bukkit.getPluginManager().registerEvents(new CommonListener(), this); // Register master event listener
PaperUtil.checkPaper(this);
Initializer.init(platform);
}
@NotNull
private LegacyPaperCommandManager<CommandSender> getCommandSenderPaperCommandManager() throws Exception {
// TODO: Update to PaperCommandManager
LegacyPaperCommandManager<CommandSender> commandManager = new LegacyPaperCommandManager<>(
this,
ExecutionCoordinator.simpleCoordinator(),
SenderMapper.create(
BukkitAdapter::adapt,
BukkitAdapter::adapt
));
private PaperCommandManager<CommandSender> getCommandSenderPaperCommandManager() throws Exception {
PaperCommandManager<CommandSender> commandManager = new PaperCommandManager<>(this,
CommandExecutionCoordinator.simpleCoordinator(),
BukkitAdapter::adapt,
BukkitAdapter::adapt);
if(commandManager.hasCapability(CloudBukkitCapabilities.NATIVE_BRIGADIER)) {
commandManager.registerBrigadier();
final CloudBrigadierManager<?, ?> brigManager = commandManager.brigadierManager();
if(brigManager != null) {
brigManager.setNativeNumberSuggestions(false);
}
} else if(commandManager.hasCapability(CloudBukkitCapabilities.ASYNCHRONOUS_COMPLETION)) {
commandManager.registerAsynchronousCompletions();
}
if(commandManager.hasCapability(CloudBukkitCapabilities.ASYNCHRONOUS_COMPLETION)) {
commandManager.registerAsynchronousCompletions();
}
return commandManager;
}
@@ -127,9 +116,6 @@ public class TerraBukkitPlugin extends JavaPlugin {
if(!VersionUtil.getSpigotVersionInfo().isSpigot())
logger.error("YOU ARE RUNNING A CRAFTBUKKIT OR BUKKIT SERVER. PLEASE UPGRADE TO PAPER.");
if(!VersionUtil.getSpigotVersionInfo().isPaper())
logger.error("YOU ARE RUNNING A SPIGOT SERVER. PLEASE UPGRADE TO PAPER.");
if(VersionUtil.getSpigotVersionInfo().isMohist()) {
if(System.getProperty("IKnowMohistCausesLotsOfIssuesButIWillUseItAnyways") == null) {
Runnable runnable = () -> { // scary big block of text
@@ -173,7 +159,7 @@ public class TerraBukkitPlugin extends JavaPlugin {
""".strip());
};
runnable.run();
asyncScheduler.runDelayed(this, task -> runnable.run(), 200L, TimeUnit.SECONDS);
foliaLib.getImpl().runLaterAsync(runnable, 200L);
// Bukkit.shutdown(); // we're not *that* evil
Bukkit.getPluginManager().disablePlugin(this);
return false;
@@ -181,7 +167,7 @@ public class TerraBukkitPlugin extends JavaPlugin {
logger.warn("""
You are using Mohist, so we will not give you any support for issues that may arise.
Since you enabled the "IKnowMohistCausesLotsOfIssuesButIWillUseItAnyways" flag, we won't disable Terra. But be warned.
> I felt a great disturbance in the JVM, as if millions of plugins suddenly cried out in stack traces and were suddenly silenced.
> I fear something terrible has happened.
> - Astrash
@@ -194,7 +180,6 @@ public class TerraBukkitPlugin extends JavaPlugin {
@Override
public @Nullable
ChunkGenerator getDefaultWorldGenerator(@NotNull String worldName, String id) {
if(id == null || id.trim().equals("")) { return null; }
return new BukkitChunkGeneratorWrapper(generatorMap.computeIfAbsent(worldName, name -> {
ConfigPack pack = platform.getConfigRegistry().getByID(id).orElseThrow(
() -> new IllegalArgumentException("No such config pack \"" + id + "\""));
@@ -202,11 +187,7 @@ public class TerraBukkitPlugin extends JavaPlugin {
}), platform.getRawConfigRegistry().getByID(id).orElseThrow(), platform.getWorldHandle().air());
}
public AsyncScheduler getAsyncScheduler() {
return asyncScheduler;
}
public GlobalRegionScheduler getGlobalRegionScheduler() {
return globalRegionScheduler;
public FoliaLib getFoliaLib() {
return foliaLib;
}
}
@@ -20,18 +20,17 @@ package com.dfsek.terra.bukkit.handles;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Locale;
import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.entity.EntityType;
import com.dfsek.terra.api.handle.WorldHandle;
import com.dfsek.terra.bukkit.util.BukkitUtils;
import com.dfsek.terra.bukkit.world.block.data.BukkitBlockState;
import com.dfsek.terra.bukkit.world.entity.BukkitEntityType;
public class BukkitWorldHandle implements WorldHandle {
private static final Logger logger = LoggerFactory.getLogger(BukkitWorldHandle.class);
private final BlockState air;
public BukkitWorldHandle() {
@@ -40,13 +39,6 @@ public class BukkitWorldHandle implements WorldHandle {
@Override
public synchronized @NotNull BlockState createBlockState(@NotNull String data) {
if(data.equals("minecraft:grass")) { //TODO: remove in 7.0
data = "minecraft:short_grass";
logger.warn(
"Translating minecraft:grass to minecraft:short_grass. In 1.20.3 minecraft:grass was renamed to minecraft:short_grass" +
". You are advised to perform this rename in your config backs as this translation will be removed in the next major " +
"version of Terra.");
}
org.bukkit.block.data.BlockData bukkitData = Bukkit.createBlockData(
data); // somehow bukkit managed to make this not thread safe! :)
return BukkitBlockState.newInstance(bukkitData);
@@ -59,6 +51,14 @@ public class BukkitWorldHandle implements WorldHandle {
@Override
public @NotNull EntityType getEntity(@NotNull String id) {
return BukkitUtils.getEntityType(id);
if(!id.startsWith("minecraft:")) throw new IllegalArgumentException("Invalid entity identifier " + id);
String entityID = id.toUpperCase(Locale.ROOT).substring(10);
return new BukkitEntityType(switch(entityID) {
case "END_CRYSTAL" -> org.bukkit.entity.EntityType.ENDER_CRYSTAL;
case "ENDER_CRYSTAL" -> throw new IllegalArgumentException(
"Invalid entity identifier " + id); // make sure this issue can't happen the other way around.
default -> org.bukkit.entity.EntityType.valueOf(entityID);
});
}
}
@@ -1,25 +1,20 @@
package com.dfsek.terra.bukkit.nms;
import org.bukkit.Bukkit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.dfsek.terra.bukkit.PlatformImpl;
import com.dfsek.terra.bukkit.util.VersionUtil;
public interface Initializer {
String NMS = VersionUtil.getMinecraftVersionInfo().toString().replace(".", "_");
String NMS = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3];
String TERRA_PACKAGE = Initializer.class.getPackageName();
static boolean init(PlatformImpl platform) {
static void init(PlatformImpl platform) {
Logger logger = LoggerFactory.getLogger(Initializer.class);
try {
String packageVersion = NMS;
if(NMS.equals("v1_21_1")) {
packageVersion = "v1_21";
}
Class<?> initializerClass = Class.forName(TERRA_PACKAGE + "." + packageVersion + ".NMSInitializer");
Class<?> initializerClass = Class.forName(TERRA_PACKAGE + "." + NMS + ".NMSInitializer");
try {
Initializer initializer = (Initializer) initializerClass.getConstructor().newInstance();
initializer.initialize(platform);
@@ -29,27 +24,16 @@ public interface Initializer {
} catch(ClassNotFoundException e) {
logger.error("NMS bindings for version {} do not exist. Support for this version is limited.", NMS);
logger.error("This is usually due to running Terra on an unsupported Minecraft version.");
String bypassKey = "IKnowThereAreNoNMSBindingsFor" + NMS + "ButIWillProceedAnyway";
if(System.getProperty(bypassKey) == null) {
logger.error("Because of this **TERRA HAS BEEN DISABLED**.");
logger.error("Do not come ask us why it is not working.");
logger.error("If you wish to proceed anyways, you can add the JVM System Property \"{}\" to enable the plugin.", bypassKey);
return false;
} else {
logger.error("");
logger.error("");
for(int i = 0; i < 20; i++) {
logger.error("PROCEEDING WITH AN EXISTING TERRA WORLD WILL RESULT IN CORRUPTION!!!");
}
logger.error("");
logger.error("");
logger.error("NMS bindings for version {} do not exist. Support for this version is limited.", NMS);
logger.error("This is usually due to running Terra on an unsupported Minecraft version.");
logger.error("We will not give you any support for issues that may arise.");
logger.error("Since you enabled the \"{}\" flag, we won't disable Terra. But be warned.", bypassKey);
logger.error("");
logger.error("");
for(int i = 0; i < 20; i++) {
logger.error("PROCEEDING WITH AN EXISTING TERRA WORLD WILL RESULT IN CORRUPTION!!!");
}
logger.error("");
logger.error("");
logger.error("NMS bindings for version {} do not exist. Support for this version is limited.", NMS);
logger.error("This is usually due to running Terra on an unsupported Minecraft version.");
}
return true;
}
void initialize(PlatformImpl plugin);
@@ -2,40 +2,11 @@ package com.dfsek.terra.bukkit.util;
import org.bukkit.Material;
import org.bukkit.block.data.BlockData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Locale;
import com.dfsek.terra.api.entity.EntityType;
import com.dfsek.terra.bukkit.world.entity.BukkitEntityType;
public class BukkitUtils {
private static final Logger logger = LoggerFactory.getLogger(BukkitUtils.class);
public static boolean isLiquid(BlockData blockState) {
Material material = blockState.getMaterial();
return material == Material.WATER || material == Material.LAVA;
}
public static EntityType getEntityType(String id) {
if(!id.contains(":")) { //TODO: remove in 7.0
String newid = "minecraft:" + id.toLowerCase();
;
logger.warn(
"Translating " + id + " to " + newid + ". In 1.20.3 entity parsing was reworked" +
". You are advised to perform this rename in your config backs as this translation will be removed in the next major " +
"version of Terra.");
}
if(!id.startsWith("minecraft:")) throw new IllegalArgumentException("Invalid entity identifier " + id);
String entityID = id.toUpperCase(Locale.ROOT).substring(10);
return new BukkitEntityType(switch(entityID) {
case "END_CRYSTAL" -> org.bukkit.entity.EntityType.END_CRYSTAL;
case "ENDER_CRYSTAL" -> throw new IllegalArgumentException(
"Invalid entity identifier " + id); // make sure this issue can't happen the other way around.
default -> org.bukkit.entity.EntityType.valueOf(entityID);
});
}
}
@@ -19,8 +19,6 @@ package com.dfsek.terra.bukkit.util;
import io.papermc.lib.PaperLib;
import java.util.concurrent.TimeUnit;
import com.dfsek.terra.bukkit.TerraBukkitPlugin;
import static io.papermc.lib.PaperLib.suggestPaper;
@@ -28,10 +26,10 @@ import static io.papermc.lib.PaperLib.suggestPaper;
public final class PaperUtil {
public static void checkPaper(TerraBukkitPlugin plugin) {
plugin.getAsyncScheduler().runDelayed(plugin, task -> {
plugin.getFoliaLib().getImpl().runLaterAsync(() -> {
if(!PaperLib.isPaper()) {
suggestPaper(plugin);
}
}, 100L, TimeUnit.SECONDS);
}, 100L);
}
}
@@ -77,13 +77,13 @@ public final class VersionUtil {
public static final class MinecraftVersionInfo {
private static final Logger logger = LoggerFactory.getLogger(MinecraftVersionInfo.class);
private static final Pattern VERSION_PATTERN = Pattern.compile("(\\d+)\\.(\\d+)(?:\\.(\\d+))?");
private static final Pattern VERSION_PATTERN = Pattern.compile("v?(\\d+)_(\\d+)_R(\\d+)");
private final int major;
private final int minor;
private final int patch;
private MinecraftVersionInfo() {
this(Bukkit.getServer().getBukkitVersion().split("-")[0]);
this(Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]);
}
private MinecraftVersionInfo(int major, int minor, int patch) {
@@ -97,7 +97,7 @@ public final class VersionUtil {
if(versionMatcher.find()) {
major = Integer.parseInt(versionMatcher.group(1));
minor = Integer.parseInt(versionMatcher.group(2));
patch = versionMatcher.group(3) != null ? Integer.parseInt(versionMatcher.group(3)) : -1;
patch = Integer.parseInt(versionMatcher.group(3));
} else {
logger.warn("Error while parsing minecraft version info. Continuing launch, but setting all versions to -1.");
@@ -112,11 +112,7 @@ public final class VersionUtil {
if(major == -1 && minor == -1 && patch == -1)
return "Unknown";
if(patch >= 0) {
return String.format("v%d.%d.%d", major, minor, patch);
} else {
return String.format("v%d.%d", major, minor);
}
return String.format("v%d.%d.%d", major, minor, patch);
}
public int getMajor() {
@@ -20,6 +20,7 @@ package com.dfsek.terra.bukkit.world;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.TreeType;
import org.bukkit.entity.Player;
import org.bukkit.generator.WorldInfo;
import org.bukkit.util.Vector;
@@ -45,12 +46,27 @@ import com.dfsek.terra.bukkit.world.block.BukkitBlockTypeAndItem;
import com.dfsek.terra.bukkit.world.block.data.BukkitBlockState;
import com.dfsek.terra.bukkit.world.inventory.BukkitItemStack;
import com.dfsek.terra.bukkit.world.inventory.meta.BukkitEnchantment;
import com.dfsek.terra.transform.MapTransform;
import com.dfsek.terra.transform.TransformerImpl;
/**
* Utility class to adapt Bukkit enums to Terra enums.
*/
public final class BukkitAdapter {
public static TransformerImpl<TreeType, String> TREE_TRANSFORMER = new TransformerImpl.Builder<TreeType, String>()
.addTransform(new MapTransform<TreeType, String>()
.add(TreeType.COCOA_TREE, "JUNGLE_COCOA")
.add(TreeType.BIG_TREE, "LARGE_OAK")
.add(TreeType.TALL_REDWOOD, "LARGE_SPRUCE")
.add(TreeType.REDWOOD, "SPRUCE")
.add(TreeType.TREE, "OAK")
.add(TreeType.MEGA_REDWOOD, "MEGA_SPRUCE")
.add(TreeType.SWAMP, "SWAMP_OAK"))
.addTransform(TreeType::toString)
.build();
public static BlockState adapt(org.bukkit.block.data.BlockData data) {
return BukkitBlockState.newInstance(data);
}
@@ -1,9 +1,9 @@
package com.dfsek.terra.bukkit.world;
import com.dfsek.terra.api.world.info.WorldProperties;
import org.bukkit.generator.WorldInfo;
import com.dfsek.terra.api.world.info.WorldProperties;
public class BukkitWorldProperties implements WorldProperties {
private final WorldInfo delegate;
@@ -23,7 +23,6 @@ import org.jetbrains.annotations.NotNull;
import com.dfsek.terra.api.block.entity.MobSpawner;
import com.dfsek.terra.api.block.entity.SerialState;
import com.dfsek.terra.api.entity.EntityType;
import com.dfsek.terra.bukkit.util.BukkitUtils;
import com.dfsek.terra.bukkit.world.entity.BukkitEntityType;
@@ -116,7 +115,7 @@ public class BukkitMobSpawner extends BukkitBlockEntity implements MobSpawner {
public void applyState(String state) {
SerialState.parse(state).forEach((k, v) -> {
switch(k) {
case "type" -> setSpawnedType(BukkitUtils.getEntityType(v));
case "type" -> setSpawnedType(new BukkitEntityType(org.bukkit.entity.EntityType.valueOf(v.toUpperCase())));
case "delay" -> setDelay(Integer.parseInt(v));
case "min_delay" -> setMinSpawnDelay(Integer.parseInt(v));
case "max_delay" -> setMaxSpawnDelay(Integer.parseInt(v));
@@ -2,8 +2,8 @@ name: "Terra"
main: "com.dfsek.terra.bukkit.TerraBukkitPlugin"
version: "@VERSION@"
load: "STARTUP"
authors: [ "dfsek", "duplexsystem", "Astrash", "solonovamax", "Sancires", "Aureus", "RogueShade" ]
author: dfsek
website: "@WIKI@"
api-version: "1.21.1"
api-version: "1.13"
description: "@DESCRIPTION@"
folia-supported: true
@@ -1,5 +1,9 @@
apply(plugin = "io.papermc.paperweight.userdev")
repositories {
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
}
dependencies {
api(project(":platforms:bukkit:common"))
paperDevBundle(Versions.Bukkit.paperDevBundle)
@@ -1,10 +1,10 @@
package com.dfsek.terra.bukkit.nms.v1_21;
package com.dfsek.terra.bukkit.nms.v1_20_R2;
import com.google.common.collect.ImmutableMap;
import com.mojang.serialization.Lifecycle;
import net.minecraft.core.Holder;
import net.minecraft.core.Holder.Reference;
import net.minecraft.core.MappedRegistry;
import net.minecraft.core.RegistrationInfo;
import net.minecraft.core.WritableRegistry;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
@@ -41,16 +41,15 @@ public class AwfulBukkitHacks {
try {
BukkitPlatformBiome platformBiome = (BukkitPlatformBiome) biome.getPlatformBiome();
NamespacedKey vanillaBukkitKey = platformBiome.getHandle().getKey();
ResourceLocation vanillaMinecraftKey = ResourceLocation.fromNamespaceAndPath(vanillaBukkitKey.getNamespace(),
vanillaBukkitKey.getKey());
ResourceLocation vanillaMinecraftKey = new ResourceLocation(vanillaBukkitKey.getNamespace(), vanillaBukkitKey.getKey());
Biome platform = NMSBiomeInjector.createBiome(biome, Objects.requireNonNull(biomeRegistry.get(vanillaMinecraftKey)));
ResourceKey<Biome> delegateKey = ResourceKey.create(
Registries.BIOME,
ResourceLocation.fromNamespaceAndPath("terra", NMSBiomeInjector.createBiomeID(pack, key))
new ResourceLocation("terra", NMSBiomeInjector.createBiomeID(pack, key))
);
Reference<Biome> holder = biomeRegistry.register(delegateKey, platform, RegistrationInfo.BUILT_IN);
Reference<Biome> holder = biomeRegistry.register(delegateKey, platform, Lifecycle.stable());
Reflection.REFERENCE.invokeBindValue(holder, platform); // IMPORTANT: bind holder.
platformBiome.getContext().put(new NMSBiomeInfo(delegateKey));
@@ -1,4 +1,4 @@
package com.dfsek.terra.bukkit.nms.v1_21;
package com.dfsek.terra.bukkit.nms.v1_20_R2;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.biome.Biome;
@@ -1,4 +1,4 @@
package com.dfsek.terra.bukkit.nms.v1_21;
package com.dfsek.terra.bukkit.nms.v1_20_R2;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
@@ -1,6 +1,6 @@
package com.dfsek.terra.bukkit.nms.v1_21;
package com.dfsek.terra.bukkit.nms.v1_20_R2;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.Codec;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.world.level.biome.Biome;
@@ -35,12 +35,8 @@ public class NMSBiomeProvider extends BiomeSource {
}
@Override
protected @NotNull MapCodec<? extends BiomeSource> codec() {
return MapCodec.assumeMapUnsafe(BiomeSource.CODEC);
// return MapCodec.unit(null);
// BuiltInRegistries.BIOME_SOURCE.byNameCodec().dispatchMap(this::codec, Function.identity());
// BuiltInRegistries.BIOME_SOURCE.byNameCodec().dispatchStable(BiomeSource::codec, Function.identity());
// return BiomeSource.CODEC;
protected @NotNull Codec<? extends BiomeSource> codec() {
return BiomeSource.CODEC;
}
@Override
@@ -1,6 +1,6 @@
package com.dfsek.terra.bukkit.nms.v1_21;
package com.dfsek.terra.bukkit.nms.v1_20_R2;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.Codec;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.world.level.LevelAccessor;
@@ -19,13 +19,14 @@ import net.minecraft.world.level.levelgen.GenerationStep.Carving;
import net.minecraft.world.level.levelgen.Heightmap.Types;
import net.minecraft.world.level.levelgen.RandomState;
import net.minecraft.world.level.levelgen.blending.Blender;
import org.bukkit.craftbukkit.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_20_R2.block.data.CraftBlockData;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
@@ -53,8 +54,8 @@ public class NMSChunkGeneratorDelegate extends ChunkGenerator {
}
@Override
protected @NotNull MapCodec<? extends ChunkGenerator> codec() {
return MapCodec.assumeMapUnsafe(ChunkGenerator.CODEC);
protected @NotNull Codec<? extends ChunkGenerator> codec() {
return ChunkGenerator.CODEC;
}
@Override
@@ -86,10 +87,10 @@ public class NMSChunkGeneratorDelegate extends ChunkGenerator {
}
@Override
public CompletableFuture<ChunkAccess> fillFromNoise(@NotNull Blender blender,
@NotNull RandomState noiseConfig,
@NotNull StructureManager structureAccessor, @NotNull ChunkAccess chunk) {
return vanilla.fillFromNoise(blender, noiseConfig, structureAccessor, chunk)
public @NotNull CompletableFuture<ChunkAccess> fillFromNoise(@NotNull Executor executor, @NotNull Blender blender,
@NotNull RandomState noiseConfig,
@NotNull StructureManager structureAccessor, @NotNull ChunkAccess chunk) {
return vanilla.fillFromNoise(executor, blender, noiseConfig, structureAccessor, chunk)
.thenApply(c -> {
LevelAccessor level = Reflection.STRUCTURE_MANAGER.getLevel(structureAccessor);
BiomeProvider biomeProvider = pack.getBiomeProvider();
@@ -1,4 +1,4 @@
package com.dfsek.terra.bukkit.nms.v1_21;
package com.dfsek.terra.bukkit.nms.v1_20_R2;
import org.bukkit.Bukkit;
@@ -1,11 +1,9 @@
package com.dfsek.terra.bukkit.nms.v1_21;
package com.dfsek.terra.bukkit.nms.v1_20_R2;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.chunk.status.WorldGenContext;
import org.bukkit.World;
import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.craftbukkit.v1_20_R2.CraftWorld;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.world.WorldInitEvent;
@@ -17,7 +15,6 @@ import java.util.Set;
import java.util.concurrent.locks.ReentrantLock;
import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.util.reflection.ReflectionUtil;
import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper;
@@ -40,20 +37,8 @@ public class NMSInjectListener implements Listener {
ChunkGenerator vanilla = serverWorld.getChunkSource().getGenerator();
NMSBiomeProvider provider = new NMSBiomeProvider(pack.getBiomeProvider(), craftWorld.getSeed());
ChunkMap chunkMap = serverWorld.getChunkSource().chunkMap;
WorldGenContext worldGenContext = chunkMap.worldGenContext;
try {
ReflectionUtil.setFinalField(chunkMap, "worldGenContext", new WorldGenContext(
worldGenContext.level(),
new NMSChunkGeneratorDelegate(vanilla, pack, provider, craftWorld.getSeed()),
worldGenContext.structureManager(),
worldGenContext.lightEngine(),
worldGenContext.mainThreadMailBox()
));
} catch(NoSuchFieldException e) {
throw new RuntimeException(e);
}
serverWorld.getChunkSource().chunkMap.generator = new NMSChunkGeneratorDelegate(vanilla, pack, provider, craftWorld.getSeed());
LOGGER.info("Successfully injected into world.");
@@ -1,4 +1,4 @@
package com.dfsek.terra.bukkit.nms.v1_21;
package com.dfsek.terra.bukkit.nms.v1_20_R2;
import net.minecraft.world.level.LevelHeightAccessor;
@@ -1,4 +1,4 @@
package com.dfsek.terra.bukkit.nms.v1_21;
package com.dfsek.terra.bukkit.nms.v1_20_R2;
import net.minecraft.core.Holder;
import net.minecraft.core.Holder.Reference;
@@ -1,4 +1,4 @@
package com.dfsek.terra.bukkit.nms.v1_21;
package com.dfsek.terra.bukkit.nms.v1_20_R2;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.Registries;
@@ -6,7 +6,7 @@ import net.minecraft.resources.ResourceKey;
import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraft.world.level.biome.Biome;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.craftbukkit.v1_20_R2.CraftServer;
public class RegistryFetcher {
@@ -0,0 +1,28 @@
package com.dfsek.terra.bukkit.nms.v1_20_R2.config;
import com.dfsek.tectonic.api.config.template.annotations.Default;
import com.dfsek.tectonic.api.config.template.annotations.Value;
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.level.biome.AmbientAdditionsSettings;
public class BiomeAdditionsSoundTemplate implements ObjectTemplate<AmbientAdditionsSettings> {
@Value("sound")
@Default
private SoundEvent sound = null;
@Value("sound-chance")
@Default
private Double soundChance = null;
@Override
public AmbientAdditionsSettings get() {
if(sound == null || soundChance == null) {
return null;
} else {
return new AmbientAdditionsSettings(BuiltInRegistries.SOUND_EVENT.wrapAsHolder(sound), soundChance);
}
}
}
@@ -0,0 +1,36 @@
package com.dfsek.terra.bukkit.nms.v1_20_R2.config;
import com.dfsek.tectonic.api.config.template.annotations.Default;
import com.dfsek.tectonic.api.config.template.annotations.Value;
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.level.biome.AmbientMoodSettings;
public class BiomeMoodSoundTemplate implements ObjectTemplate<AmbientMoodSettings> {
@Value("sound")
@Default
private SoundEvent sound = null;
@Value("cultivation-ticks")
@Default
private Integer soundCultivationTicks = null;
@Value("spawn-range")
@Default
private Integer soundSpawnRange = null;
@Value("extra-distance")
@Default
private Double soundExtraDistance = null;
@Override
public AmbientMoodSettings get() {
if(sound == null || soundCultivationTicks == null || soundSpawnRange == null || soundExtraDistance == null) {
return null;
} else {
return new AmbientMoodSettings(BuiltInRegistries.SOUND_EVENT.wrapAsHolder(sound), soundCultivationTicks, soundSpawnRange, soundExtraDistance);
}
}
}
@@ -0,0 +1,34 @@
package com.dfsek.terra.bukkit.nms.v1_20_R2.config;
import com.dfsek.tectonic.api.config.template.annotations.Default;
import com.dfsek.tectonic.api.config.template.annotations.Value;
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.commands.arguments.ParticleArgument;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.world.level.biome.AmbientParticleSettings;
public class BiomeParticleConfigTemplate implements ObjectTemplate<AmbientParticleSettings> {
@Value("particle")
@Default
private String particle = null;
@Value("probability")
@Default
private Integer probability = null;
@Override
public AmbientParticleSettings get() {
if(particle == null || probability == null) {
return null;
}
try {
return new AmbientParticleSettings(ParticleArgument.readParticle(new StringReader(particle), BuiltInRegistries.PARTICLE_TYPE.asLookup()), probability);
} catch(CommandSyntaxException e) {
throw new RuntimeException(e);
}
}
}

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