Merge pull request #467 from PolyhedralDev/ver/6.5.0

Ver/6.5.0
This commit is contained in:
Zoë Gidiere 2024-09-24 09:41:58 -06:00 committed by GitHub
commit c374c2d5ef
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
113 changed files with 1790 additions and 583 deletions

View File

@ -18,10 +18,10 @@ jobs:
steps: steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
- name: Set up JDK 17 - name: Set up JDK 21
uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93 uses: actions/setup-java@387ac29b308b003ca37ba93a6cab5eb57c8f5f93
with: with:
java-version: '17' java-version: '21'
distribution: 'temurin' distribution: 'temurin'
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
settings-path: ${{ github.workspace }} # location for the settings.xml file settings-path: ${{ github.workspace }} # location for the settings.xml file

View File

@ -1,8 +1,8 @@
preRelease(true) preRelease(true)
versionProjects(":common:api", version("6.4.3")) versionProjects(":common:api", version("6.5.0"))
versionProjects(":common:implementation", version("6.4.3")) versionProjects(":common:implementation", version("6.5.0"))
versionProjects(":platforms", version("6.4.3")) versionProjects(":platforms", version("6.5.0"))
allprojects { allprojects {
@ -15,6 +15,7 @@ allprojects {
tasks.withType<JavaCompile>().configureEach { tasks.withType<JavaCompile>().configureEach {
options.isFork = true options.isFork = true
options.isIncremental = true options.isIncremental = true
options.release.set(21)
} }
tasks.withType<Test>().configureEach { tasks.withType<Test>().configureEach {
@ -44,7 +45,7 @@ afterEvaluate {
} }
project(":platforms:bukkit:common").configureDistribution() project(":platforms:bukkit:common").configureDistribution()
forSubProjects(":common:addons") { forSubProjects(":common:addons") {
apply(plugin = "com.github.johnrengelman.shadow") apply(plugin = "com.gradleup.shadow")
tasks.named("build") { tasks.named("build") {
finalizedBy(tasks.named("shadowJar")) finalizedBy(tasks.named("shadowJar"))

View File

@ -9,18 +9,18 @@ repositories {
maven("https://repo.codemc.org/repository/maven-public") { maven("https://repo.codemc.org/repository/maven-public") {
name = "CodeMC" name = "CodeMC"
} }
maven("https://papermc.io/repo/repository/maven-public/") { maven("https://repo.papermc.io/repository/maven-public/") {
name = "PaperMC" name = "PaperMC"
} }
} }
dependencies { dependencies {
//TODO Allow pulling from Versions.kt //TODO Allow pulling from Versions.kt
implementation("com.github.johnrengelman", "shadow", "8.1.1") implementation("com.gradleup.shadow", "shadow-gradle-plugin", "8.3.1")
implementation("io.papermc.paperweight.userdev", "io.papermc.paperweight.userdev.gradle.plugin", "1.5.11") implementation("io.papermc.paperweight.userdev", "io.papermc.paperweight.userdev.gradle.plugin", "1.7.2")
implementation("org.ow2.asm", "asm", "9.6") implementation("org.ow2.asm", "asm", "9.7")
implementation("org.ow2.asm", "asm-tree", "9.6") implementation("org.ow2.asm", "asm-tree", "9.7")
implementation("com.dfsek.tectonic", "common", "4.2.1") implementation("com.dfsek.tectonic", "common", "4.2.1")
implementation("org.yaml", "snakeyaml", "2.2") implementation("org.yaml", "snakeyaml", "2.3")
} }

View File

@ -22,8 +22,8 @@ fun Project.configureCompilation() {
apply<TectonicDocPlugin>() apply<TectonicDocPlugin>()
configure<JavaPluginExtension> { configure<JavaPluginExtension> {
sourceCompatibility = JavaVersion.VERSION_17 sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_21
} }
tasks.withType<JavaCompile> { tasks.withType<JavaCompile> {

View File

@ -36,7 +36,7 @@ fun Project.configureDependencies() {
maven("https://repo.codemc.org/repository/maven-public") { maven("https://repo.codemc.org/repository/maven-public") {
name = "CodeMC" name = "CodeMC"
} }
maven("https://papermc.io/repo/repository/maven-public/") { maven("https://repo.papermc.io/repository/maven-public/") {
name = "PaperMC" name = "PaperMC"
} }
maven("https://files.minecraftforge.net/maven/") { maven("https://files.minecraftforge.net/maven/") {
@ -48,6 +48,9 @@ fun Project.configureDependencies() {
maven("https://jitpack.io") { maven("https://jitpack.io") {
name = "JitPack" name = "JitPack"
} }
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") {
name = "Sonatype Snapshots"
}
} }
dependencies { dependencies {

View File

@ -21,13 +21,14 @@ import kotlin.io.path.exists
fun Project.configureDistribution() { fun Project.configureDistribution() {
apply(plugin = "com.github.johnrengelman.shadow") apply(plugin = "com.gradleup.shadow")
val downloadDefaultPacks = tasks.create("downloadDefaultPacks") { val downloadDefaultPacks = tasks.create("downloadDefaultPacks") {
group = "terra" group = "terra"
doFirst { doFirst {
file("${buildDir}/resources/main/packs/").deleteRecursively() 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/" + Versions.Terra.overworldConfig + "/default.zip")
downloadPack(defaultPackUrl, project) downloadPack(defaultPackUrl, project)
} }
} }

View File

@ -8,27 +8,28 @@ object Versions {
const val paralithic = "0.7.1" const val paralithic = "0.7.1"
const val strata = "1.3.2" const val strata = "1.3.2"
const val cloud = "1.8.4" const val cloud = "2.0.0"
const val cloudPaper = "2.0.0-beta.10"
const val cloudFabric = "2.0.0-beta.9"
const val caffeine = "3.1.8" const val caffeine = "3.1.8"
const val slf4j = "2.0.9" const val slf4j = "2.0.16"
const val log4j_slf4j_impl = "2.20.0"
object Internal { object Internal {
const val shadow = "8.1.1" const val shadow = "8.3.1"
const val apacheText = "1.11.0" const val apacheText = "1.12.0"
const val apacheIO = "2.15.1" const val apacheIO = "2.16.1"
const val guava = "32.1.3-jre" const val guava = "33.3.0-jre"
const val asm = "9.6" const val asm = "9.7"
const val snakeYml = "2.2" const val snakeYml = "2.3"
const val jetBrainsAnnotations = "24.1.0" const val jetBrainsAnnotations = "24.1.0"
const val junit = "5.10.1" const val junit = "5.11.0"
} }
} }
object Fabric { object Fabric {
const val fabricAPI = "0.91.2+${Mod.minecraft}" const val fabricAPI = "0.104.0+${Mod.minecraft}"
} }
// //
// object Quilt { // object Quilt {
@ -37,14 +38,14 @@ object Versions {
// } // }
object Mod { object Mod {
const val mixin = "0.12.5+mixin.0.8.5" const val mixin = "0.15.3+mixin.0.8.7"
const val minecraft = "1.20.4" const val minecraft = "1.21.1"
const val yarn = "$minecraft+build.1" const val yarn = "$minecraft+build.3"
const val fabricLoader = "0.15.1" const val fabricLoader = "0.16.5"
const val architecuryLoom = "1.4.369" const val architecuryLoom = "1.7.413"
const val architecturyPlugin = "3.4.151" const val architecturyPlugin = "3.4.159"
} }
// //
// object Forge { // object Forge {
@ -53,14 +54,14 @@ object Versions {
// } // }
object Bukkit { object Bukkit {
const val minecraft = "1.20.4" const val minecraft = "1.21.1"
const val paperBuild = "$minecraft-R0.1-20231209.173338-2" const val paperBuild = "$minecraft-R0.1-20240917.151311-80"
const val paper = paperBuild const val paper = paperBuild
const val paperLib = "1.0.8" const val paperLib = "1.0.8"
const val reflectionRemapper = "0.1.0" const val reflectionRemapper = "0.1.1"
const val paperDevBundle = paperBuild const val paperDevBundle = paperBuild
const val runPaper = "2.2.2" const val runPaper = "2.3.1"
const val paperWeight = "1.5.11" const val paperWeight = "1.7.2"
} }
// //
@ -72,6 +73,6 @@ object Versions {
// //
object CLI { object CLI {
const val nbt = "6.1" const val nbt = "6.1"
const val logback = "1.4.14" const val logback = "1.5.8"
} }
} }

View File

@ -1,9 +1,9 @@
package com.dfsek.terra.addons.biome.extrusion.api; package com.dfsek.terra.addons.biome.extrusion.api;
import java.util.Collection;
import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.api.world.biome.Biome;
import java.util.Collection;
public interface Extrusion { public interface Extrusion {
Biome extrude(Biome original, int x, int y, int z, long seed); Biome extrude(Biome original, int x, int y, int z, long seed);

View File

@ -29,7 +29,7 @@ public class BiomePipelineTemplate implements ObjectTemplate<BiomeProvider> {
@Default @Default
@Description(""" @Description("""
The resolution at which to sample biomes. The resolution at which to sample biomes.
Larger values are quadratically faster, but produce lower quality results. Larger values are quadratically faster, but produce lower quality results.
For example, a value of 3 would sample every 3 blocks.""") For example, a value of 3 would sample every 3 blocks.""")
protected @Meta int resolution = 1; protected @Meta int resolution = 1;

View File

@ -28,7 +28,7 @@ public class BiomePipelineTemplate extends BiomeProviderTemplate {
@Description(""" @Description("""
The initial size of biome chunks. This value must be at least 2. 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>. <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] 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 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 take initial-size and for each expand stage, multiply the running value by 2

View File

@ -22,7 +22,7 @@ public abstract class BiomeProviderTemplate implements ObjectTemplate<BiomeProvi
@Default @Default
@Description(""" @Description("""
The resolution at which to sample biomes. The resolution at which to sample biomes.
Larger values are quadratically faster, but produce lower quality results. Larger values are quadratically faster, but produce lower quality results.
For example, a value of 3 would sample every 3 blocks.""") For example, a value of 3 would sample every 3 blocks.""")
protected @Meta int resolution = 1; protected @Meta int resolution = 1;

View File

@ -13,6 +13,7 @@ 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.BiomePaletteTemplate;
import com.dfsek.terra.addons.chunkgenerator.config.palette.slant.SlantLayerTemplate; 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.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.BiomePaletteInfo;
import com.dfsek.terra.addons.chunkgenerator.palette.slant.SlantHolder; import com.dfsek.terra.addons.chunkgenerator.palette.slant.SlantHolder;
import com.dfsek.terra.addons.manifest.api.AddonInitializer; import com.dfsek.terra.addons.manifest.api.AddonInitializer;
@ -45,8 +46,8 @@ public class NoiseChunkGenerator3DAddon implements AddonInitializer {
.priority(1000) .priority(1000)
.then(event -> { .then(event -> {
event.getPack().applyLoader(SlantHolder.CalculationMethod.class, event.getPack().applyLoader(SlantCalculationMethod.class,
(type, o, loader, depthTracker) -> SlantHolder.CalculationMethod.valueOf((String) o)); (type, o, loader, depthTracker) -> SlantCalculationMethod.valueOf((String) o));
NoiseChunkGeneratorPackConfigTemplate config = event.loadTemplate(new NoiseChunkGeneratorPackConfigTemplate()); NoiseChunkGeneratorPackConfigTemplate config = event.loadTemplate(new NoiseChunkGeneratorPackConfigTemplate());
event.getPack().getContext().put(config); event.getPack().getContext().put(config);
@ -57,7 +58,8 @@ public class NoiseChunkGenerator3DAddon implements AddonInitializer {
pack -> new NoiseChunkGenerator3D(pack, platform, config.getElevationBlend(), pack -> new NoiseChunkGenerator3D(pack, platform, config.getElevationBlend(),
config.getHorizontalRes(), config.getHorizontalRes(),
config.getVerticalRes(), noisePropertiesPropertyKey, config.getVerticalRes(), noisePropertiesPropertyKey,
paletteInfoPropertyKey)); paletteInfoPropertyKey, config.getSlantCalculationMethod(),
config.isSlantPalettesEnabled()));
event.getPack() event.getPack()
.applyLoader(SlantHolder.Layer.class, SlantLayerTemplate::new); .applyLoader(SlantHolder.Layer.class, SlantLayerTemplate::new);
}) })

View File

@ -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.Default;
import com.dfsek.tectonic.api.config.template.annotations.Value; import com.dfsek.tectonic.api.config.template.annotations.Value;
import com.dfsek.terra.addons.chunkgenerator.palette.slant.SlantHolder; import com.dfsek.terra.addons.chunkgenerator.generation.math.SlantCalculationMethod;
import com.dfsek.terra.api.config.meta.Meta; import com.dfsek.terra.api.config.meta.Meta;
import com.dfsek.terra.api.properties.Properties; import com.dfsek.terra.api.properties.Properties;
@ -24,7 +24,11 @@ public class NoiseChunkGeneratorPackConfigTemplate implements ConfigTemplate, Pr
@Value("slant.calculation-method") @Value("slant.calculation-method")
@Default @Default
private SlantHolder.@Meta CalculationMethod slantCalculationMethod = SlantHolder.CalculationMethod.Derivative; private @Meta SlantCalculationMethod slantCalculationMethod = SlantCalculationMethod.Derivative;
@Value("slant.disable-palettes")
@Default
private @Meta boolean disableSlantPalettes = false;
public int getElevationBlend() { public int getElevationBlend() {
return elevationBlend; return elevationBlend;
@ -38,7 +42,11 @@ public class NoiseChunkGeneratorPackConfigTemplate implements ConfigTemplate, Pr
return verticalRes; return verticalRes;
} }
public SlantHolder.CalculationMethod getSlantCalculationMethod() { public SlantCalculationMethod getSlantCalculationMethod() {
return slantCalculationMethod; return slantCalculationMethod;
} }
public boolean isSlantPalettesEnabled() {
return !disableSlantPalettes;
}
} }

View File

@ -16,6 +16,7 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; 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.BiomePaletteInfo;
import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolder; import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolder;
import com.dfsek.terra.addons.chunkgenerator.palette.slant.SlantHolder; import com.dfsek.terra.addons.chunkgenerator.palette.slant.SlantHolder;
@ -27,7 +28,7 @@ import com.dfsek.terra.api.world.chunk.generation.util.Palette;
public class BiomePaletteTemplate implements ObjectTemplate<BiomePaletteInfo> { public class BiomePaletteTemplate implements ObjectTemplate<BiomePaletteInfo> {
private final Platform platform; private final Platform platform;
private final SlantHolder.CalculationMethod slantCalculationMethod; private final SlantCalculationMethod slantCalculationMethod;
@Value("slant") @Value("slant")
@Default @Default
@Description("The slant palettes to use in this biome.") @Description("The slant palettes to use in this biome.")
@ -56,7 +57,7 @@ public class BiomePaletteTemplate implements ObjectTemplate<BiomePaletteInfo> {
@Default @Default
private @Meta boolean updatePalette = false; private @Meta boolean updatePalette = false;
public BiomePaletteTemplate(Platform platform, SlantHolder.CalculationMethod slantCalculationMethod) { public BiomePaletteTemplate(Platform platform, SlantCalculationMethod slantCalculationMethod) {
this.platform = platform; this.platform = platform;
this.slantCalculationMethod = slantCalculationMethod; this.slantCalculationMethod = slantCalculationMethod;
} }

View File

@ -11,11 +11,12 @@ package com.dfsek.terra.addons.chunkgenerator.generation;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseProperties; import com.dfsek.terra.addons.chunkgenerator.config.noise.BiomeNoiseProperties;
import com.dfsek.terra.addons.chunkgenerator.generation.math.PaletteUtil; import com.dfsek.terra.addons.chunkgenerator.generation.math.SlantCalculationMethod;
import com.dfsek.terra.addons.chunkgenerator.generation.math.interpolation.LazilyEvaluatedInterpolator; 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.Sampler3D;
import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.SamplerProvider; 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.BiomePaletteInfo;
import com.dfsek.terra.addons.chunkgenerator.palette.slant.SlantHolder;
import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.Platform;
import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.api.config.ConfigPack;
@ -42,16 +43,23 @@ public class NoiseChunkGenerator3D implements ChunkGenerator {
private final PropertyKey<BiomePaletteInfo> paletteInfoPropertyKey; private final PropertyKey<BiomePaletteInfo> paletteInfoPropertyKey;
private final PropertyKey<BiomeNoiseProperties> noisePropertiesKey; private final PropertyKey<BiomeNoiseProperties> noisePropertiesKey;
private final SlantCalculationMethod slantCalculationMethod;
private final boolean useSlantPalettes;
public NoiseChunkGenerator3D(ConfigPack pack, Platform platform, int elevationBlend, int carverHorizontalResolution, public NoiseChunkGenerator3D(ConfigPack pack, Platform platform, int elevationBlend, int carverHorizontalResolution,
int carverVerticalResolution, int carverVerticalResolution,
PropertyKey<BiomeNoiseProperties> noisePropertiesKey, PropertyKey<BiomeNoiseProperties> noisePropertiesKey,
PropertyKey<BiomePaletteInfo> paletteInfoPropertyKey) { PropertyKey<BiomePaletteInfo> paletteInfoPropertyKey,
SlantCalculationMethod slantCalculationMethod, boolean useSlantPalettes) {
this.platform = platform; this.platform = platform;
this.air = platform.getWorldHandle().air(); this.air = platform.getWorldHandle().air();
this.carverHorizontalResolution = carverHorizontalResolution; this.carverHorizontalResolution = carverHorizontalResolution;
this.carverVerticalResolution = carverVerticalResolution; this.carverVerticalResolution = carverVerticalResolution;
this.paletteInfoPropertyKey = paletteInfoPropertyKey; this.paletteInfoPropertyKey = paletteInfoPropertyKey;
this.noisePropertiesKey = noisePropertiesKey; this.noisePropertiesKey = noisePropertiesKey;
this.slantCalculationMethod = slantCalculationMethod;
this.useSlantPalettes = useSlantPalettes;
int maxBlend = pack int maxBlend = pack
.getBiomeProvider() .getBiomeProvider()
.stream() .stream()
@ -63,6 +71,17 @@ public class NoiseChunkGenerator3D implements ChunkGenerator {
this.samplerCache = new SamplerProvider(platform, elevationBlend, noisePropertiesKey, maxBlend); 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 @Override
@SuppressWarnings("try") @SuppressWarnings("try")
public void generateChunkData(@NotNull ProtoChunk chunk, @NotNull WorldProperties world, public void generateChunkData(@NotNull ProtoChunk chunk, @NotNull WorldProperties world,
@ -103,8 +122,7 @@ public class NoiseChunkGenerator3D implements ChunkGenerator {
if(sampler.sample(x, y, z) > 0) { if(sampler.sample(x, y, z) > 0) {
if(carver.sample(x, y, z) <= 0) { if(carver.sample(x, y, z) <= 0) {
data = PaletteUtil data = paletteAt(x, y, z, sampler, paletteInfo, paletteLevel)
.getPalette(x, y, z, sampler, paletteInfo, paletteLevel)
.get(paletteLevel, cx, y, cz, seed); .get(paletteLevel, cx, y, cz, seed);
chunk.setBlock(x, y, z, data); chunk.setBlock(x, y, z, data);
paletteLevel++; paletteLevel++;
@ -135,7 +153,7 @@ public class NoiseChunkGenerator3D implements ChunkGenerator {
int fdX = Math.floorMod(x, 16); int fdX = Math.floorMod(x, 16);
int fdZ = Math.floorMod(z, 16); int fdZ = Math.floorMod(z, 16);
Palette palette = PaletteUtil.getPalette(fdX, y, fdZ, sampler, paletteInfo, 0); Palette palette = paletteAt(fdX, y, fdZ, sampler, paletteInfo, 0);
double noise = sampler.sample(fdX, y, fdZ); double noise = sampler.sample(fdX, y, fdZ);
if(noise > 0) { if(noise > 0) {
int level = 0; int level = 0;
@ -157,11 +175,8 @@ public class NoiseChunkGenerator3D implements ChunkGenerator {
public double getSlant(int x, int y, int z, WorldProperties world, BiomeProvider biomeProvider) { public double getSlant(int x, int y, int z, WorldProperties world, BiomeProvider biomeProvider) {
int fdX = Math.floorMod(x, 16); int fdX = Math.floorMod(x, 16);
int fdZ = Math.floorMod(z, 16); int fdZ = Math.floorMod(z, 16);
return biomeProvider.getBiome(x, y, z, world.getSeed()) Sampler3D sampler = samplerCache.get(x, z, world, biomeProvider);
.getContext() return slantCalculationMethod.slant(sampler, fdX, y, fdZ);
.get(paletteInfoPropertyKey)
.slantHolder()
.calculateSlant(samplerCache.get(x, z, world, biomeProvider), fdX, y, fdZ);
} }
public SamplerProvider samplerProvider() { public SamplerProvider samplerProvider() {

View File

@ -1,29 +0,0 @@
/*
* 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);
}
}

View File

@ -0,0 +1,69 @@
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();
}

View File

@ -14,6 +14,7 @@ import java.util.TreeMap;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import com.dfsek.terra.addons.chunkgenerator.generation.math.SlantCalculationMethod;
import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolder; import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolder;
@ -21,7 +22,7 @@ public class MultipleSlantHolder extends SlantHolderImpl {
private final NavigableMap<Double, PaletteHolder> layers; private final NavigableMap<Double, PaletteHolder> layers;
private final double slantThreshold; private final double slantThreshold;
MultipleSlantHolder(List<SlantHolder.Layer> slant, int slantDepth, CalculationMethod calculationMethod) { MultipleSlantHolder(List<SlantHolder.Layer> slant, int slantDepth, SlantCalculationMethod calculationMethod) {
super(slantDepth, calculationMethod); super(slantDepth, calculationMethod);
NavigableMap<Double, PaletteHolder> layers = new TreeMap<>( NavigableMap<Double, PaletteHolder> layers = new TreeMap<>(
slant.stream().collect(Collectors.toMap(SlantHolder.Layer::threshold, SlantHolder.Layer::palette))); slant.stream().collect(Collectors.toMap(SlantHolder.Layer::threshold, SlantHolder.Layer::palette)));

View File

@ -1,5 +1,6 @@
package com.dfsek.terra.addons.chunkgenerator.palette.slant; 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; import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolder;
@ -7,7 +8,7 @@ final class SingleSlantHolder extends SlantHolderImpl {
private final SlantHolder.Layer layer; private final SlantHolder.Layer layer;
public SingleSlantHolder(SlantHolder.Layer layer, int slantDepth, CalculationMethod calculationMethod) { public SingleSlantHolder(SlantHolder.Layer layer, int slantDepth, SlantCalculationMethod calculationMethod) {
super(slantDepth, calculationMethod); super(slantDepth, calculationMethod);
this.layer = layer; this.layer = layer;
} }

View File

@ -2,19 +2,13 @@ package com.dfsek.terra.addons.chunkgenerator.palette.slant;
import java.util.List; import java.util.List;
import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.Sampler3D; import com.dfsek.terra.addons.chunkgenerator.generation.math.SlantCalculationMethod;
import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolder; import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolder;
import com.dfsek.terra.api.util.vector.Vector3;
public interface SlantHolder { public interface SlantHolder {
SlantHolder EMPTY = new 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 @Override
public boolean isAboveDepth(int depth) { public boolean isAboveDepth(int depth) {
return false; return false;
@ -31,7 +25,7 @@ public interface SlantHolder {
} }
}; };
static SlantHolder of(List<SlantHolder.Layer> layers, int slantDepth, CalculationMethod calculationMethod) { static SlantHolder of(List<SlantHolder.Layer> layers, int slantDepth, SlantCalculationMethod calculationMethod) {
if(layers.isEmpty()) { if(layers.isEmpty()) {
return EMPTY; return EMPTY;
} else if(layers.size() == 1) { } else if(layers.size() == 1) {
@ -40,8 +34,6 @@ public interface SlantHolder {
return new MultipleSlantHolder(layers, slantDepth, calculationMethod); return new MultipleSlantHolder(layers, slantDepth, calculationMethod);
} }
double calculateSlant(Sampler3D sampler, double x, double y, double z);
boolean isAboveDepth(int depth); boolean isAboveDepth(int depth);
boolean isInSlantThreshold(double slant); boolean isInSlantThreshold(double slant);
@ -49,71 +41,6 @@ public interface SlantHolder {
PaletteHolder getPalette(double slant); 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) { record Layer(PaletteHolder palette, double threshold) {
} }
} }

View File

@ -1,26 +1,19 @@
package com.dfsek.terra.addons.chunkgenerator.palette.slant; package com.dfsek.terra.addons.chunkgenerator.palette.slant;
import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.Sampler3D; import com.dfsek.terra.addons.chunkgenerator.generation.math.SlantCalculationMethod;
public abstract class SlantHolderImpl implements SlantHolder { public abstract class SlantHolderImpl implements SlantHolder {
protected final boolean floorToThreshold; protected final boolean floorToThreshold;
private final SlantHolder.CalculationMethod calculationMethod;
private final int slantDepth; private final int slantDepth;
protected SlantHolderImpl(int slantDepth, CalculationMethod calculationMethod) { protected SlantHolderImpl(int slantDepth, SlantCalculationMethod calculationMethod) {
this.floorToThreshold = calculationMethod.floorToThreshold(); this.floorToThreshold = calculationMethod.floorToThreshold();
this.calculationMethod = calculationMethod;
this.slantDepth = slantDepth; this.slantDepth = slantDepth;
} }
protected abstract double getSlantThreshold(); 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 @Override
public final boolean isAboveDepth(int depth) { public final boolean isAboveDepth(int depth) {
return depth <= slantDepth; return depth <= slantDepth;

View File

@ -1,7 +1,7 @@
package com.dfsek.terra.addons.commands.addons; package com.dfsek.terra.addons.commands.addons;
import cloud.commandframework.ArgumentDescription; import org.incendo.cloud.CommandManager;
import cloud.commandframework.CommandManager; import org.incendo.cloud.description.Description;
import com.dfsek.terra.addons.manifest.api.AddonInitializer; import com.dfsek.terra.addons.manifest.api.AddonInitializer;
import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.Platform;
@ -30,7 +30,7 @@ public class AddonsCommandAddon implements AddonInitializer {
CommandManager<CommandSender> manager = event.getCommandManager(); CommandManager<CommandSender> manager = event.getCommandManager();
manager.command( manager.command(
manager.commandBuilder("addons", ArgumentDescription.of("List installed Terra addons")) manager.commandBuilder("addons", Description.of("List installed Terra addons"))
.permission("terra.addons") .permission("terra.addons")
.handler(context -> { .handler(context -> {
StringBuilder addons = new StringBuilder("Installed addons:\n"); StringBuilder addons = new StringBuilder("Installed addons:\n");
@ -41,7 +41,7 @@ public class AddonsCommandAddon implements AddonInitializer {
.append('@') .append('@')
.append(addon.getVersion().getFormatted()) .append(addon.getVersion().getFormatted())
.append('\n')); .append('\n'));
context.getSender().sendMessage(addons.toString()); context.sender().sendMessage(addons.toString());
}) })
) )
.command( .command(
@ -61,7 +61,7 @@ public class AddonsCommandAddon implements AddonInitializer {
.append('@') .append('@')
.append(versions.getFormatted()) .append(versions.getFormatted())
.append('\n')); .append('\n'));
context.getSender().sendMessage(addonInfo.toString()); context.sender().sendMessage(addonInfo.toString());
}) })
); );
}); });

View File

@ -1,7 +1,7 @@
package com.dfsek.terra.addons.commands.packs; package com.dfsek.terra.addons.commands.packs;
import cloud.commandframework.ArgumentDescription; import org.incendo.cloud.CommandManager;
import cloud.commandframework.CommandManager; import org.incendo.cloud.description.Description;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -35,7 +35,7 @@ public class PacksCommandAddon implements AddonInitializer {
CommandManager<CommandSender> manager = event.getCommandManager(); CommandManager<CommandSender> manager = event.getCommandManager();
manager.command( manager.command(
manager.commandBuilder("packs", ArgumentDescription.of("List installed config packs")) manager.commandBuilder("packs", Description.of("List installed config packs"))
.permission("terra.packs") .permission("terra.packs")
.handler(context -> { .handler(context -> {
StringBuilder packs = new StringBuilder("Installed packs:\n"); StringBuilder packs = new StringBuilder("Installed packs:\n");
@ -43,12 +43,12 @@ public class PacksCommandAddon implements AddonInitializer {
.append(pack.getID()) .append(pack.getID())
.append('@') .append('@')
.append(pack.getVersion().getFormatted())); .append(pack.getVersion().getFormatted()));
context.getSender().sendMessage(packs.toString()); context.sender().sendMessage(packs.toString());
}) })
) )
.command( .command(
manager.commandBuilder("packs") manager.commandBuilder("packs")
.literal("info", ArgumentDescription.of("Get information about a pack")) .literal("info", Description.of("Get information about a pack"))
.permission("terra.packs.info") .permission("terra.packs.info")
.argument(RegistryArgument.of("pack", platform.getConfigRegistry())) .argument(RegistryArgument.of("pack", platform.getConfigRegistry()))
.handler(context -> { .handler(context -> {
@ -65,21 +65,21 @@ public class PacksCommandAddon implements AddonInitializer {
.append('@') .append('@')
.append(versions.getFormatted()) .append(versions.getFormatted())
.append('\n')); .append('\n'));
context.getSender().sendMessage(packInfo.toString()); context.sender().sendMessage(packInfo.toString());
})) }))
.command( .command(
manager.commandBuilder("packs") manager.commandBuilder("packs")
.literal("reload", ArgumentDescription.of("Reload config packs")) .literal("reload", Description.of("Reload config packs"))
.permission("terra.packs.reload") .permission("terra.packs.reload")
.handler(context -> { .handler(context -> {
context.getSender().sendMessage("Reloading Terra..."); context.sender().sendMessage("Reloading Terra...");
logger.info("Reloading Terra..."); logger.info("Reloading Terra...");
if(platform.reload()) { if(platform.reload()) {
logger.info("Terra reloaded successfully."); logger.info("Terra reloaded successfully.");
context.getSender().sendMessage("Terra reloaded successfully."); context.sender().sendMessage("Terra reloaded successfully.");
} else { } else {
logger.error("Terra failed to reload."); logger.error("Terra failed to reload.");
context.getSender().sendMessage( context.sender().sendMessage(
"Terra failed to reload. See logs for more information."); "Terra failed to reload. See logs for more information.");
} }
})); }));

View File

@ -1,7 +1,7 @@
package com.dfsek.terra.addons.commands.profiler; package com.dfsek.terra.addons.commands.profiler;
import cloud.commandframework.ArgumentDescription; import org.incendo.cloud.CommandManager;
import cloud.commandframework.CommandManager; import org.incendo.cloud.description.Description;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -33,24 +33,24 @@ public class ProfilerCommandAddon implements AddonInitializer {
CommandManager<CommandSender> manager = event.getCommandManager(); CommandManager<CommandSender> manager = event.getCommandManager();
manager manager
.command( .command(
manager.commandBuilder("profiler", ArgumentDescription.of("Access the profiler")) manager.commandBuilder("profiler", Description.of("Access the profiler"))
.literal("start", ArgumentDescription.of("Start profiling"), "st") .literal("start", Description.of("Start profiling"), "st")
.permission("terra.profiler.start") .permission("terra.profiler.start")
.handler(context -> { .handler(context -> {
platform.getProfiler().start(); platform.getProfiler().start();
context.getSender().sendMessage("Profiling started."); context.sender().sendMessage("Profiling started.");
})) }))
.command( .command(
manager.commandBuilder("profiler", ArgumentDescription.of("Access the profiler")) manager.commandBuilder("profiler", Description.of("Access the profiler"))
.literal("stop", ArgumentDescription.of("Stop profiling"), "s") .literal("stop", Description.of("Stop profiling"), "s")
.permission("terra.profiler.stop") .permission("terra.profiler.stop")
.handler(context -> { .handler(context -> {
platform.getProfiler().stop(); platform.getProfiler().stop();
context.getSender().sendMessage("Profiling stopped."); context.sender().sendMessage("Profiling stopped.");
})) }))
.command( .command(
manager.commandBuilder("profiler", ArgumentDescription.of("Access the profiler")) manager.commandBuilder("profiler", Description.of("Access the profiler"))
.literal("query", ArgumentDescription.of("Query profiler results"), "q") .literal("query", Description.of("Query profiler results"), "q")
.permission("terra.profiler.query") .permission("terra.profiler.query")
.handler(context -> { .handler(context -> {
StringBuilder data = new StringBuilder("Terra Profiler data: \n"); StringBuilder data = new StringBuilder("Terra Profiler data: \n");
@ -59,15 +59,15 @@ public class ProfilerCommandAddon implements AddonInitializer {
.append(timings.toString()) .append(timings.toString())
.append('\n')); .append('\n'));
logger.info(data.toString()); logger.info(data.toString());
context.getSender().sendMessage("Profiling data dumped to console."); context.sender().sendMessage("Profiling data dumped to console.");
})) }))
.command( .command(
manager.commandBuilder("profiler", ArgumentDescription.of("Access the profiler")) manager.commandBuilder("profiler", Description.of("Access the profiler"))
.literal("reset", ArgumentDescription.of("Reset the profiler"), "r") .literal("reset", Description.of("Reset the profiler"), "r")
.permission("terra.profiler.reset") .permission("terra.profiler.reset")
.handler(context -> { .handler(context -> {
platform.getProfiler().reset(); platform.getProfiler().reset();
context.getSender().sendMessage("Profiler reset."); context.sender().sendMessage("Profiler reset.");
})); }));
}); });
} }

View File

@ -1,10 +1,11 @@
package com.dfsek.terra.addons.commands.structure; package com.dfsek.terra.addons.commands.structure;
import cloud.commandframework.ArgumentDescription; import org.incendo.cloud.CommandManager;
import cloud.commandframework.CommandManager; import org.incendo.cloud.component.DefaultValue;
import cloud.commandframework.arguments.standard.EnumArgument; import org.incendo.cloud.context.CommandContext;
import cloud.commandframework.arguments.standard.LongArgument; import org.incendo.cloud.description.Description;
import cloud.commandframework.context.CommandContext; import org.incendo.cloud.parser.standard.EnumParser;
import org.incendo.cloud.parser.standard.LongParser;
import java.util.Random; import java.util.Random;
@ -31,7 +32,7 @@ public class StructureCommandAddon implements AddonInitializer {
private BaseAddon addon; private BaseAddon addon;
private static Registry<Structure> getStructureRegistry(CommandContext<CommandSender> sender) { private static Registry<Structure> getStructureRegistry(CommandContext<CommandSender> sender) {
return sender.getSender().getEntity().orElseThrow().world().getPack().getRegistry(Structure.class); return sender.sender().getEntity().orElseThrow().world().getPack().getRegistry(Structure.class);
} }
@Override @Override
@ -43,16 +44,16 @@ public class StructureCommandAddon implements AddonInitializer {
CommandManager<CommandSender> manager = event.getCommandManager(); CommandManager<CommandSender> manager = event.getCommandManager();
manager.command( manager.command(
manager.commandBuilder("structures", ArgumentDescription.of("Manage or generate structures")) manager.commandBuilder("structures", Description.of("Manage or generate structures"))
.literal("generate") .literal("generate")
.argument(RegistryArgument.builder("structure", .optional(RegistryArgument.builder("structure",
StructureCommandAddon::getStructureRegistry, StructureCommandAddon::getStructureRegistry,
TypeKey.of(Structure.class))) TypeKey.of(Structure.class)))
.argument(LongArgument.optional("seed", 0)) .optional("seed", LongParser.longParser(), DefaultValue.constant(0L))
.argument(EnumArgument.optional(Rotation.class, "rotation", Rotation.NONE)) .optional("rotation", EnumParser.enumParser(Rotation.class), DefaultValue.constant(Rotation.NONE))
.handler(context -> { .handler(context -> {
Structure structure = context.get("structure"); Structure structure = context.get("structure");
Entity sender = context.getSender().getEntity().orElseThrow(); Entity sender = context.sender().getEntity().orElseThrow();
structure.generate( structure.generate(
sender.position().toInt(), sender.position().toInt(),
sender.world(), sender.world(),

View File

@ -7,11 +7,11 @@
package com.dfsek.terra.addons.biome.holder; package com.dfsek.terra.addons.biome.holder;
import com.dfsek.terra.api.world.chunk.generation.util.Palette;
import java.util.Map; import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;
import com.dfsek.terra.api.world.chunk.generation.util.Palette;
public class PaletteHolderBuilder { public class PaletteHolderBuilder {
private final TreeMap<Integer, Palette> paletteMap = new TreeMap<>(); private final TreeMap<Integer, Palette> paletteMap = new TreeMap<>();

View File

@ -7,11 +7,11 @@
package com.dfsek.terra.addons.feature.distributor.distributors; 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.addons.feature.distributor.util.Point;
import com.dfsek.terra.api.structure.feature.Distributor; import com.dfsek.terra.api.structure.feature.Distributor;
import java.util.Set;
public class PointSetDistributor implements Distributor { public class PointSetDistributor implements Distributor {
private final Set<Point> points; private final Set<Point> points;

View File

@ -1,4 +1,4 @@
version = version("1.1.0") version = version("1.2.0")
dependencies { dependencies {
compileOnlyApi(project(":common:addons:manifest-addon-loader")) compileOnlyApi(project(":common:addons:manifest-addon-loader"))

View File

@ -17,6 +17,7 @@ import com.dfsek.terra.addons.manifest.api.AddonInitializer;
import com.dfsek.terra.addons.noise.config.CubicSplinePointTemplate; import com.dfsek.terra.addons.noise.config.CubicSplinePointTemplate;
import com.dfsek.terra.addons.noise.config.DimensionApplicableNoiseSampler; 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.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.DomainWarpTemplate;
import com.dfsek.terra.addons.noise.config.templates.FunctionTemplate; import com.dfsek.terra.addons.noise.config.templates.FunctionTemplate;
import com.dfsek.terra.addons.noise.config.templates.ImageSamplerTemplate; import com.dfsek.terra.addons.noise.config.templates.ImageSamplerTemplate;
@ -28,6 +29,7 @@ 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.DistanceSamplerTemplate;
import com.dfsek.terra.addons.noise.config.templates.noise.ExpressionFunctionTemplate; 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.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.SimpleNoiseTemplate;
import com.dfsek.terra.addons.noise.config.templates.noise.fractal.BrownianMotionTemplate; import com.dfsek.terra.addons.noise.config.templates.noise.fractal.BrownianMotionTemplate;
import com.dfsek.terra.addons.noise.config.templates.noise.fractal.PingPongTemplate; import com.dfsek.terra.addons.noise.config.templates.noise.fractal.PingPongTemplate;
@ -63,6 +65,7 @@ import com.dfsek.terra.api.addon.BaseAddon;
import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent;
import com.dfsek.terra.api.event.functional.FunctionalEventHandler; import com.dfsek.terra.api.event.functional.FunctionalEventHandler;
import com.dfsek.terra.api.inject.annotations.Inject; 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.noise.NoiseSampler;
import com.dfsek.terra.api.registry.CheckedRegistry; import com.dfsek.terra.api.registry.CheckedRegistry;
import com.dfsek.terra.api.util.reflection.TypeKey; import com.dfsek.terra.api.util.reflection.TypeKey;
@ -94,7 +97,8 @@ public class NoiseAddon implements AddonInitializer {
(type, o, loader, depthTracker) -> DistanceSampler.DistanceFunction.valueOf((String) o)) (type, o, loader, depthTracker) -> DistanceSampler.DistanceFunction.valueOf((String) o))
.applyLoader(DimensionApplicableNoiseSampler.class, DimensionApplicableNoiseSampler::new) .applyLoader(DimensionApplicableNoiseSampler.class, DimensionApplicableNoiseSampler::new)
.applyLoader(FunctionTemplate.class, FunctionTemplate::new) .applyLoader(FunctionTemplate.class, FunctionTemplate::new)
.applyLoader(CubicSpline.Point.class, CubicSplinePointTemplate::new); .applyLoader(CubicSpline.Point.class, CubicSplinePointTemplate::new)
.applyLoader(DerivativeNoiseSampler.class, DerivativeNoiseSamplerTemplate::new);
noiseRegistry.register(addon.key("LINEAR"), LinearNormalizerTemplate::new); noiseRegistry.register(addon.key("LINEAR"), LinearNormalizerTemplate::new);
noiseRegistry.register(addon.key("NORMAL"), NormalNormalizerTemplate::new); noiseRegistry.register(addon.key("NORMAL"), NormalNormalizerTemplate::new);
@ -117,7 +121,7 @@ public class NoiseAddon implements AddonInitializer {
noiseRegistry.register(addon.key("PERLIN"), () -> new SimpleNoiseTemplate(PerlinSampler::new)); noiseRegistry.register(addon.key("PERLIN"), () -> new SimpleNoiseTemplate(PerlinSampler::new));
noiseRegistry.register(addon.key("SIMPLEX"), () -> new SimpleNoiseTemplate(SimplexSampler::new)); noiseRegistry.register(addon.key("SIMPLEX"), () -> new SimpleNoiseTemplate(SimplexSampler::new));
noiseRegistry.register(addon.key("GABOR"), GaborNoiseTemplate::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"), () -> new SimpleNoiseTemplate(ValueSampler::new));
noiseRegistry.register(addon.key("VALUE_CUBIC"), () -> new SimpleNoiseTemplate(ValueCubicSampler::new)); noiseRegistry.register(addon.key("VALUE_CUBIC"), () -> new SimpleNoiseTemplate(ValueCubicSampler::new));

View File

@ -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.Default;
import com.dfsek.tectonic.api.config.template.annotations.Value; 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.DimensionApplicableNoiseSampler;
import com.dfsek.terra.addons.noise.config.templates.FunctionTemplate; import com.dfsek.terra.addons.noise.config.templates.FunctionTemplate;
import com.dfsek.terra.api.config.meta.Meta; import com.dfsek.terra.api.config.meta.Meta;
import com.dfsek.terra.api.properties.Properties; import com.dfsek.terra.api.properties.Properties;
import java.util.LinkedHashMap;
import java.util.Map;
@SuppressWarnings("FieldMayBeFinal") @SuppressWarnings("FieldMayBeFinal")
public class NoiseConfigPackTemplate implements ConfigTemplate, Properties { public class NoiseConfigPackTemplate implements ConfigTemplate, Properties {

View File

@ -0,0 +1,26 @@
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;
}
}

View File

@ -0,0 +1,8 @@
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> {
}

View File

@ -0,0 +1,79 @@
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;
}
}

View File

@ -11,6 +11,8 @@ 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.defined.UserDefinedFunction;
import com.dfsek.terra.addons.noise.paralithic.noise.NoiseFunction2; 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.NoiseFunction3;
import com.dfsek.terra.addons.noise.paralithic.noise.SaltedNoiseFunction2;
import com.dfsek.terra.addons.noise.paralithic.noise.SaltedNoiseFunction3;
public class FunctionUtil { public class FunctionUtil {
@ -23,10 +25,15 @@ public class FunctionUtil {
for(Map.Entry<String, FunctionTemplate> entry : functions.entrySet()) { for(Map.Entry<String, FunctionTemplate> entry : functions.entrySet()) {
functionMap.put(entry.getKey(), UserDefinedFunction.newInstance(entry.getValue())); functionMap.put(entry.getKey(), UserDefinedFunction.newInstance(entry.getValue()));
} }
samplers.forEach((id, sampler) -> functionMap.put(id, samplers.forEach((id, sampler) -> {
sampler.getDimensions() == 2 ? if(sampler.getDimensions() == 2) {
new NoiseFunction2(sampler.getSampler()) : functionMap.put(id, new NoiseFunction2(sampler.getSampler()));
new NoiseFunction3(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()));
}
});
return functionMap; return functionMap;
} }
} }

View File

@ -0,0 +1,37 @@
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;
}
}

View File

@ -0,0 +1,37 @@
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;
}
}

View File

@ -0,0 +1,25 @@
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);
}

View File

@ -0,0 +1,173 @@
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);
}
}

View File

@ -276,4 +276,424 @@ public class OpenSimplex2SSampler extends SimplexStyleSampler {
return value * 9.046026385208288; 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;
}
} }

View File

@ -37,41 +37,37 @@ public class OpenSimplex2Sampler extends SimplexStyleSampler {
i *= PRIME_X; i *= PRIME_X;
j *= PRIME_Y; j *= PRIME_Y;
double n0, n1, n2; double value = 0;
double a = 0.5 - x0 * x0 - y0 * y0; double a = 0.5 - x0 * x0 - y0 * y0;
if(a <= 0) n0 = 0; if(a > 0) {
else { value = (a * a) * (a * a) * gradCoord(seed, i, j, x0, y0);
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); double c = 2 * (1 - 2 * G2) * (1 / G2 - 2) * t + ((-2 * (1 - 2 * G2) * (1 - 2 * G2)) + a);
if(c <= 0) n2 = 0; if(c > 0) {
else {
double x2 = x0 + (2 * G2 - 1); double x2 = x0 + (2 * G2 - 1);
double y2 = y0 + (2 * G2 - 1); double y2 = y0 + (2 * G2 - 1);
n2 = (c * c) * (c * c) * gradCoord(seed, i + PRIME_X, j + PRIME_Y, x2, y2); value += (c * c) * (c * c) * gradCoord(seed, i + PRIME_X, j + PRIME_Y, x2, y2);
} }
if(y0 > x0) { if(y0 > x0) {
double x1 = x0 + G2; double x1 = x0 + G2;
double y1 = y0 + (G2 - 1); double y1 = y0 + (G2 - 1);
double b = 0.5 - x1 * x1 - y1 * y1; double b = 0.5 - x1 * x1 - y1 * y1;
if(b <= 0) n1 = 0; if(b > 0) {
else { value += (b * b) * (b * b) * gradCoord(seed, i, j + PRIME_Y, x1, y1);
n1 = (b * b) * (b * b) * gradCoord(seed, i, j + PRIME_Y, x1, y1);
} }
} else { } else {
double x1 = x0 + (G2 - 1); double x1 = x0 + (G2 - 1);
double y1 = y0 + G2; double y1 = y0 + G2;
double b = 0.5 - x1 * x1 - y1 * y1; double b = 0.5 - x1 * x1 - y1 * y1;
if(b <= 0) n1 = 0; if(b <= 0) {
else { value += (b * b) * (b * b) * gradCoord(seed, i + PRIME_X, j, x1, y1);
n1 = (b * b) * (b * b) * gradCoord(seed, i + PRIME_X, j, x1, y1);
} }
} }
return (n0 + n1 + n2) * 99.83685446303647f; return value * 99.83685446303647f;
} }
@Override @Override
@ -157,4 +153,208 @@ public class OpenSimplex2Sampler extends SimplexStyleSampler {
return value * 32.69428253173828125; 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;
}
} }

View File

@ -7,13 +7,13 @@
package com.dfsek.terra.addons.noise.samplers.noise.simplex; package com.dfsek.terra.addons.noise.samplers.noise.simplex;
import com.dfsek.terra.addons.noise.samplers.noise.NoiseFunction; import com.dfsek.terra.addons.noise.samplers.noise.DerivativeNoiseFunction;
/** /**
* Abstract NoiseSampler implementation for simplex-style noise functions. * Abstract NoiseSampler implementation for simplex-style noise functions.
*/ */
public abstract class SimplexStyleSampler extends NoiseFunction { public abstract class SimplexStyleSampler extends DerivativeNoiseFunction {
protected static final double[] GRADIENTS_2_D = { protected static final double[] GRADIENTS_2_D = {
0.130526192220052d, 0.99144486137381d, 0.38268343236509d, 0.923879532511287d, 0.608761429008721d, 0.793353340291235d, 0.130526192220052d, 0.99144486137381d, 0.38268343236509d, 0.923879532511287d, 0.608761429008721d, 0.793353340291235d,
0.793353340291235d, 0.608761429008721d, 0.923879532511287d, 0.38268343236509d, 0.99144486137381d, 0.130526192220051d, 0.793353340291235d, 0.608761429008721d, 0.923879532511287d, 0.38268343236509d, 0.99144486137381d, 0.130526192220051d,
@ -79,26 +79,53 @@ public abstract class SimplexStyleSampler extends NoiseFunction {
1, 1, 0, 0, 0, -1, 1, 0, -1, 1, 0, 0, 0, -1, -1, 0 1, 1, 0, 0, 0, -1, 1, 0, -1, 1, 0, 0, 0, -1, -1, 0
}; };
protected static double gradCoord(int seed, int xPrimed, int yPrimed, double xd, double yd) { protected static int gradCoordIndex(int seed, int xPrimed, int yPrimed) {
int hash = hash(seed, xPrimed, yPrimed); int hash = hash(seed, xPrimed, yPrimed);
hash ^= hash >> 15; hash ^= hash >> 15;
hash &= 127 << 1; hash &= 127 << 1;
double xg = GRADIENTS_2_D[hash]; return hash;
double yg = GRADIENTS_2_D[hash | 1]; }
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];
return xd * xg + yd * yg; return xd * xg + yd * yg;
} }
protected static double gradCoord(int seed, int xPrimed, int yPrimed, int zPrimed, double xd, double yd, double zd) { protected static int gradCoordIndex(int seed, int xPrimed, int yPrimed, int zPrimed) {
int hash = hash(seed, xPrimed, yPrimed, zPrimed); int hash = hash(seed, xPrimed, yPrimed, zPrimed);
hash ^= hash >> 15; hash ^= hash >> 15;
hash &= 63 << 2; hash &= 63 << 2;
double xg = GRADIENTS_3D[hash]; return hash;
double yg = GRADIENTS_3D[hash | 1]; }
double zg = GRADIENTS_3D[hash | 2];
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];
return xd * xg + yd * yg + zd * zg; 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;
}
} }

View File

@ -11,13 +11,6 @@ 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.dynamic.DynamicValue;
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; 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.BiomeFeatures;
import com.dfsek.terra.addons.generation.feature.config.FeatureStageTemplate; import com.dfsek.terra.addons.generation.feature.config.FeatureStageTemplate;
import com.dfsek.terra.addons.manifest.api.AddonInitializer; import com.dfsek.terra.addons.manifest.api.AddonInitializer;
@ -35,6 +28,9 @@ import com.dfsek.terra.api.util.reflection.TypeKey;
import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.api.world.biome.Biome;
import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage; import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage;
import java.util.*;
import java.util.function.Supplier;
public class FeatureGenerationAddon implements AddonInitializer { public class FeatureGenerationAddon implements AddonInitializer {
public static final TypeKey<Supplier<ObjectTemplate<GenerationStage>>> STAGE_TYPE_KEY = new TypeKey<>() { public static final TypeKey<Supplier<ObjectTemplate<GenerationStage>>> STAGE_TYPE_KEY = new TypeKey<>() {

View File

@ -7,11 +7,9 @@
package com.dfsek.terra.addons.generation.feature; 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.addons.generation.feature.config.BiomeFeatures;
import com.dfsek.terra.api.Platform; 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.properties.PropertyKey;
import com.dfsek.terra.api.registry.key.StringIdentifiable; import com.dfsek.terra.api.registry.key.StringIdentifiable;
import com.dfsek.terra.api.util.Rotation; import com.dfsek.terra.api.util.Rotation;
@ -21,6 +19,9 @@ 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.stage.GenerationStage;
import com.dfsek.terra.api.world.chunk.generation.util.Column; import com.dfsek.terra.api.world.chunk.generation.util.Column;
import java.util.Collections;
import java.util.Random;
public class FeatureGenerationStage implements GenerationStage, StringIdentifiable { public class FeatureGenerationStage implements GenerationStage, StringIdentifiable {
private final Platform platform; private final Platform platform;
@ -31,13 +32,20 @@ public class FeatureGenerationStage implements GenerationStage, StringIdentifiab
private final int resolution; private final int resolution;
private final PropertyKey<BiomeFeatures> biomeFeaturesKey; 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) { public FeatureGenerationStage(Platform platform, String id, int resolution, PropertyKey<BiomeFeatures> biomeFeaturesKey,
NoiseSampler blendSampler, double blendAmplitude) {
this.platform = platform; this.platform = platform;
this.id = id; this.id = id;
this.profile = "feature_stage:" + id; this.profile = "feature_stage:" + id;
this.resolution = resolution; this.resolution = resolution;
this.biomeFeaturesKey = biomeFeaturesKey; this.biomeFeaturesKey = biomeFeaturesKey;
this.blendSampler = blendSampler;
this.doBlending = blendAmplitude != 0d;
this.blendAmplitude = blendAmplitude;
} }
@Override @Override
@ -52,7 +60,10 @@ public class FeatureGenerationStage implements GenerationStage, StringIdentifiab
int tx = cx + chunkX; int tx = cx + chunkX;
int tz = cz + chunkZ; int tz = cz + chunkZ;
world.getBiomeProvider() world.getBiomeProvider()
.getColumn(tx, tz, world) .getColumn(
tx + (doBlending ? (int) (blendSampler.noise(seed, tx, tz) * blendAmplitude) : 0),
tz + (doBlending ? (int) (blendSampler.noise(seed + 1, tx, tz) * blendAmplitude) : 0),
world)
.forRanges(resolution, (min, max, biome) -> { .forRanges(resolution, (min, max, biome) -> {
for(int subChunkX = 0; subChunkX < resolution; subChunkX++) { for(int subChunkX = 0; subChunkX < resolution; subChunkX++) {
for(int subChunkZ = 0; subChunkZ < resolution; subChunkZ++) { for(int subChunkZ = 0; subChunkZ < resolution; subChunkZ++) {

View File

@ -8,6 +8,7 @@ import com.dfsek.tectonic.api.exception.ValidationException;
import com.dfsek.terra.addons.generation.feature.FeatureGenerationStage; import com.dfsek.terra.addons.generation.feature.FeatureGenerationStage;
import com.dfsek.terra.api.Platform; 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.properties.PropertyKey;
import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage; import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage;
@ -22,6 +23,24 @@ public class FeatureStageTemplate implements ObjectTemplate<GenerationStage>, Va
@Default @Default
private int resolution = 4; 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) { public FeatureStageTemplate(Platform platform, PropertyKey<BiomeFeatures> biomeFeaturesKey) {
this.platform = platform; this.platform = platform;
this.biomeFeaturesKey = biomeFeaturesKey; this.biomeFeaturesKey = biomeFeaturesKey;
@ -30,7 +49,7 @@ public class FeatureStageTemplate implements ObjectTemplate<GenerationStage>, Va
@Override @Override
public FeatureGenerationStage get() { public FeatureGenerationStage get() {
return new FeatureGenerationStage(platform, id, resolution, biomeFeaturesKey); return new FeatureGenerationStage(platform, id, resolution, biomeFeaturesKey, blendSampler, blendAmplitude);
} }
@Override @Override

View File

@ -1,7 +1,5 @@
package com.dfsek.terra.addons.structure.mutator; 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.Keyed;
import com.dfsek.terra.api.registry.key.RegistryKey; import com.dfsek.terra.api.registry.key.RegistryKey;
import com.dfsek.terra.api.structure.Structure; import com.dfsek.terra.api.structure.Structure;
@ -11,6 +9,8 @@ import com.dfsek.terra.api.world.WritableWorld;
import com.dfsek.terra.api.world.util.ReadInterceptor; import com.dfsek.terra.api.world.util.ReadInterceptor;
import com.dfsek.terra.api.world.util.WriteInterceptor; import com.dfsek.terra.api.world.util.WriteInterceptor;
import java.util.Random;
public class MutatedStructure implements Structure, Keyed<MutatedStructure> { public class MutatedStructure implements Structure, Keyed<MutatedStructure> {
private final RegistryKey key; private final RegistryKey key;

View File

@ -7,13 +7,13 @@
package com.dfsek.terra.addons.terrascript.script.builders; 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.Returnable;
import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; 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.script.functions.CheckBlockFunction;
import com.dfsek.terra.addons.terrascript.tokenizer.Position; import com.dfsek.terra.addons.terrascript.tokenizer.Position;
import java.util.List;
public class CheckBlockFunctionBuilder implements FunctionBuilder<CheckBlockFunction> { public class CheckBlockFunctionBuilder implements FunctionBuilder<CheckBlockFunction> {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")

View File

@ -2,7 +2,7 @@ dependencies {
api("ca.solo-studios", "strata", Versions.Libraries.strata) api("ca.solo-studios", "strata", Versions.Libraries.strata)
compileOnlyApi("org.slf4j", "slf4j-api", Versions.Libraries.slf4j) compileOnlyApi("org.slf4j", "slf4j-api", Versions.Libraries.slf4j)
testImplementation("org.slf4j", "slf4j-api", Versions.Libraries.slf4j) testImplementation("org.slf4j", "slf4j-api", Versions.Libraries.slf4j)
api("cloud.commandframework", "cloud-core", Versions.Libraries.cloud) api("org.incendo", "cloud-core", Versions.Libraries.cloud)
api("com.dfsek.tectonic", "common", Versions.Libraries.tectonic) api("com.dfsek.tectonic", "common", Versions.Libraries.tectonic)

View File

@ -1,18 +1,19 @@
package com.dfsek.terra.api.command.arguments; 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 io.leangen.geantyref.TypeToken;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable; 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 java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.Queue; import java.util.concurrent.CompletableFuture;
import java.util.function.BiFunction;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -22,39 +23,22 @@ import com.dfsek.terra.api.registry.key.RegistryKey;
import com.dfsek.terra.api.util.reflection.TypeKey; import com.dfsek.terra.api.util.reflection.TypeKey;
public class RegistryArgument<T, R> extends CommandArgument<T, R> { public class RegistryArgument {
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) { public static <T, R> Builder<T, R> builder(String name, Registry<R> registry) {
return new Builder<>(name, registry); return new Builder<>(name, registry);
} }
public static <T, R> CommandArgument<T, R> of(String name, Registry<R> registry) { public static <T, R> CommandComponent<T> of(String name, Registry<R> registry) {
return RegistryArgument.<T, R>builder(name, registry).build(); return RegistryArgument.<T, R>builder(name, registry).build();
} }
public static <T, R> CommandArgument<T, R> optional(String name, Registry<R> registry) { public static <T, R> CommandComponent<T> optional(String name, Registry<R> registry) {
return RegistryArgument.<T, R>builder(name, registry).asOptional().build(); return RegistryArgument.<T, R>builder(name, registry).optional().build();
} }
public static <T, R> CommandArgument<T, R> optional(String name, Registry<R> registry, String defaultKey) { public static <T, R> CommandComponent<T> optional(String name, Registry<R> registry, DefaultValue<T, R> defaultKey) {
return RegistryArgument.<T, R>builder(name, registry).asOptionalWithDefault(defaultKey).build(); return RegistryArgument.<T, R>builder(name, registry).optional(defaultKey).build();
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -63,49 +47,36 @@ public class RegistryArgument<T, R> extends CommandArgument<T, R> {
return new Builder<>(name, registryFunction, (TypeToken<R>) TypeToken.get(registryType.getType())); return new Builder<>(name, registryFunction, (TypeToken<R>) TypeToken.get(registryType.getType()));
} }
public static <T, R> CommandArgument<T, R> of(String name, Function<CommandContext<T>, Registry<R>> registryFunction, public static <T, R> CommandComponent<T> of(String name, Function<CommandContext<T>, Registry<R>> registryFunction,
TypeKey<R> registryType) { TypeKey<R> registryType) {
return RegistryArgument.<T, R>builder(name, registryFunction, registryType).build(); return RegistryArgument.<T, R>builder(name, registryFunction, registryType).build();
} }
public static <T, R> CommandArgument<T, R> optional(String name, Function<CommandContext<T>, Registry<R>> registryFunction, public static <T, R> CommandComponent<T> optional(String name, Function<CommandContext<T>, Registry<R>> registryFunction,
TypeKey<R> registryType) { TypeKey<R> registryType) {
return RegistryArgument.builder(name, registryFunction, registryType).asOptional().build(); return RegistryArgument.builder(name, registryFunction, registryType).optional().build();
} }
public static <T, R> CommandArgument<T, R> optional(String name, Function<CommandContext<T>, Registry<R>> registryFunction, public static <T, R> CommandComponent<T> optional(String name, Function<CommandContext<T>, Registry<R>> registryFunction,
TypeKey<R> registryType, String defaultKey) { TypeKey<R> registryType, DefaultValue<T, R> defaultKey) {
return RegistryArgument.builder(name, registryFunction, registryType).asOptionalWithDefault(defaultKey).build(); return RegistryArgument.builder(name, registryFunction, registryType).optional(defaultKey).build();
} }
public static final class Builder<T, R> extends CommandArgument.Builder<T, R> { public static final class Builder<T, R> extends CommandComponent.Builder<T, R> {
private final Function<CommandContext<T>, Registry<R>> registryFunction;
private final TypeToken<R> typeToken;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private Builder(@NonNull String name, Registry<R> registry) { private Builder(@NonNull String name, Registry<R> registry) {
super((TypeToken<R>) TypeToken.get(registry.getType().getType()), name); super();
this.registryFunction = commandContext -> registry; this.name(name);
this.typeToken = (TypeToken<R>) TypeToken.get(registry.getType().getType()); this.parser(ParserDescriptor.of(
new RegistryArgumentParser<>(commandContext -> registry),
(TypeToken<R>) TypeToken.get(registry.getType().getType())));
} }
private Builder(@NonNull String name, Function<CommandContext<T>, Registry<R>> registryFunction, TypeToken<R> typeToken) { private Builder(@NonNull String name, Function<CommandContext<T>, Registry<R>> registryFunction, TypeToken<R> typeToken) {
super(typeToken, name); super();
this.typeToken = typeToken; this.name(name);
this.registryFunction = registryFunction; this.parser(ParserDescriptor.of(new RegistryArgumentParser<>(registryFunction), typeToken));
}
@Override
public @NonNull RegistryArgument<T, R> build() {
return new RegistryArgument<>(
isRequired(),
getName(),
registryFunction,
typeToken,
getDefaultValue(),
getSuggestionsProvider(),
getDefaultDescription()
);
} }
} }
@ -119,12 +90,12 @@ public class RegistryArgument<T, R> extends CommandArgument<T, R> {
@Override @Override
public @NonNull ArgumentParseResult<@NonNull R> parse(@NonNull CommandContext<@NonNull T> commandContext, public @NonNull ArgumentParseResult<@NonNull R> parse(@NonNull CommandContext<@NonNull T> commandContext,
@NonNull Queue<@NonNull String> inputQueue) { @NonNull CommandInput commandInput) {
String input = inputQueue.remove(); String input = commandInput.readString();
String next = inputQueue.peek(); String next = commandInput.peekString();
if(next != null && next.equals(":")) { if(next.equals(":")) {
input += inputQueue.remove(); input += commandInput.readString();
input += inputQueue.remove(); input += commandInput.readString();
} }
Registry<R> registry = registryFunction.apply(commandContext); Registry<R> registry = registryFunction.apply(commandContext);
@ -146,8 +117,17 @@ public class RegistryArgument<T, R> extends CommandArgument<T, R> {
} }
@Override @Override
public @NonNull List<@NonNull String> suggestions(@NonNull CommandContext<T> commandContext, @NonNull String input) { public @NonNull SuggestionProvider<T> suggestionProvider() {
return registryFunction.apply(commandContext).keys().stream().map(RegistryKey::toString).sorted().collect(Collectors.toList()); 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()));
}
};
} }
} }
} }

View File

@ -1,10 +1,10 @@
package com.dfsek.terra.api.event.events.platform; package com.dfsek.terra.api.event.events.platform;
import cloud.commandframework.CommandManager;
import com.dfsek.terra.api.command.CommandSender; import com.dfsek.terra.api.command.CommandSender;
import com.dfsek.terra.api.event.events.Event; import com.dfsek.terra.api.event.events.Event;
import org.incendo.cloud.CommandManager;
public class CommandRegistrationEvent implements Event { public class CommandRegistrationEvent implements Event {
private final CommandManager<CommandSender> commandManager; private final CommandManager<CommandSender> commandManager;

View File

@ -0,0 +1,45 @@
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);
}

View File

@ -8,6 +8,7 @@
package com.dfsek.terra.api.util.reflection; package com.dfsek.terra.api.util.reflection;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import sun.misc.Unsafe;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement; import java.lang.reflect.AnnotatedElement;
@ -26,6 +27,18 @@ import java.util.stream.Stream;
public final class ReflectionUtil { 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) { public static Field[] getFields(@NotNull Class<?> type) {
Field[] result = type.getDeclaredFields(); Field[] result = type.getDeclaredFields();
Class<?> parentClass = type.getSuperclass(); Class<?> parentClass = type.getSuperclass();
@ -35,6 +48,14 @@ public final class ReflectionUtil {
return result; 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) { public static Method[] getMethods(@NotNull Class<?> type) {
Method[] result = type.getDeclaredMethods(); Method[] result = type.getDeclaredMethods();
Class<?> parentClass = type.getSuperclass(); Class<?> parentClass = type.getSuperclass();

View File

@ -24,14 +24,15 @@ import com.dfsek.tectonic.api.depth.DepthTracker;
import com.dfsek.tectonic.api.exception.LoadException; import com.dfsek.tectonic.api.exception.LoadException;
import com.dfsek.tectonic.api.loader.ConfigLoader; import com.dfsek.tectonic.api.loader.ConfigLoader;
import com.dfsek.tectonic.api.preprocessor.Result; 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 org.jetbrains.annotations.NotNull;
import java.lang.reflect.AnnotatedType; import java.lang.reflect.AnnotatedType;
import java.util.Map; 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 class MetaNumberPreprocessor extends MetaPreprocessor<Meta> {
public static final TypeKey<String> META_STRING_KEY = new TypeKey<@Meta String>() { public static final TypeKey<String> META_STRING_KEY = new TypeKey<@Meta String>() {

Binary file not shown.

View File

@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionSha256Sum=9d926787066a081739e8200858338b4a69e837c3a821a33aca9db09dd4a41026 distributionSha256Sum=1541fa36599e12857140465f3c91a97409b4512501c26f9631fb113e392c5bd1
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

2
gradlew vendored
View File

@ -55,7 +55,7 @@
# Darwin, MinGW, and NonStop. # Darwin, MinGW, and NonStop.
# #
# (3) This script is generated from the Groovy template # (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project. # within the Gradle project.
# #
# You can find Gradle at https://github.com/gradle/gradle/. # You can find Gradle at https://github.com/gradle/gradle/.

20
gradlew.bat vendored
View File

@ -43,11 +43,11 @@ set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1 %JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute if %ERRORLEVEL% equ 0 goto execute
echo. echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. echo location of your Java installation. 1>&2
goto fail goto fail
@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute if exist "%JAVA_EXE%" goto execute
echo. echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. echo location of your Java installation. 1>&2
goto fail goto fail

View File

@ -2,15 +2,9 @@ plugins {
id("xyz.jpenilla.run-paper") version Versions.Bukkit.runPaper id("xyz.jpenilla.run-paper") version Versions.Bukkit.runPaper
} }
repositories {
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") {
name = "Sonatype"
}
}
dependencies { dependencies {
shaded(project(":platforms:bukkit:common")) shaded(project(":platforms:bukkit:common"))
shaded(project(":platforms:bukkit:nms:v1_20_R3", configuration = "reobf")) shaded(project(":platforms:bukkit:nms:v1_21", configuration = "reobf"))
shaded("xyz.jpenilla", "reflection-remapper", Versions.Bukkit.reflectionRemapper) shaded("xyz.jpenilla", "reflection-remapper", Versions.Bukkit.reflectionRemapper)
} }

View File

@ -11,5 +11,5 @@ dependencies {
shadedApi("com.google.guava", "guava", Versions.Libraries.Internal.guava) shadedApi("com.google.guava", "guava", Versions.Libraries.Internal.guava)
shadedApi("cloud.commandframework", "cloud-paper", Versions.Libraries.cloud) shadedApi("org.incendo", "cloud-paper", Versions.Libraries.cloudPaper)
} }

View File

@ -17,15 +17,16 @@
package com.dfsek.terra.bukkit; package com.dfsek.terra.bukkit;
import cloud.commandframework.brigadier.CloudBrigadierManager;
import cloud.commandframework.bukkit.CloudBukkitCapabilities;
import cloud.commandframework.execution.CommandExecutionCoordinator;
import cloud.commandframework.paper.PaperCommandManager;
import io.papermc.paper.threadedregions.scheduler.AsyncScheduler; import io.papermc.paper.threadedregions.scheduler.AsyncScheduler;
import io.papermc.paper.threadedregions.scheduler.GlobalRegionScheduler; import io.papermc.paper.threadedregions.scheduler.GlobalRegionScheduler;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.generator.ChunkGenerator; import org.bukkit.generator.ChunkGenerator;
import org.bukkit.plugin.java.JavaPlugin; 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.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -71,14 +72,14 @@ public class TerraBukkitPlugin extends JavaPlugin {
} }
try { try {
PaperCommandManager<CommandSender> commandManager = getCommandSenderPaperCommandManager(); LegacyPaperCommandManager<CommandSender> commandManager = getCommandSenderPaperCommandManager();
platform.getEventManager().callEvent(new CommandRegistrationEvent(commandManager)); platform.getEventManager().callEvent(new CommandRegistrationEvent(commandManager));
} catch(Exception e) { // This should never happen. } catch(Exception e) { // This should never happen.
logger.error(""" logger.error("""
TERRA HAS BEEN DISABLED TERRA HAS BEEN DISABLED
Errors occurred while registering commands. Errors occurred while registering commands.
Please report this to Terra. Please report this to Terra.
""".strip(), e); """.strip(), e);
@ -91,22 +92,26 @@ public class TerraBukkitPlugin extends JavaPlugin {
} }
@NotNull @NotNull
private PaperCommandManager<CommandSender> getCommandSenderPaperCommandManager() throws Exception { private LegacyPaperCommandManager<CommandSender> getCommandSenderPaperCommandManager() throws Exception {
PaperCommandManager<CommandSender> commandManager = new PaperCommandManager<>(this, // TODO: Update to PaperCommandManager
CommandExecutionCoordinator.simpleCoordinator(), LegacyPaperCommandManager<CommandSender> commandManager = new LegacyPaperCommandManager<>(
BukkitAdapter::adapt, this,
BukkitAdapter::adapt); ExecutionCoordinator.simpleCoordinator(),
SenderMapper.create(
BukkitAdapter::adapt,
BukkitAdapter::adapt
));
if(commandManager.hasCapability(CloudBukkitCapabilities.NATIVE_BRIGADIER)) { if(commandManager.hasCapability(CloudBukkitCapabilities.NATIVE_BRIGADIER)) {
commandManager.registerBrigadier(); commandManager.registerBrigadier();
final CloudBrigadierManager<?, ?> brigManager = commandManager.brigadierManager(); final CloudBrigadierManager<?, ?> brigManager = commandManager.brigadierManager();
if(brigManager != null) { if(brigManager != null) {
brigManager.setNativeNumberSuggestions(false); brigManager.setNativeNumberSuggestions(false);
} }
} } else if(commandManager.hasCapability(CloudBukkitCapabilities.ASYNCHRONOUS_COMPLETION)) {
if(commandManager.hasCapability(CloudBukkitCapabilities.ASYNCHRONOUS_COMPLETION)) {
commandManager.registerAsynchronousCompletions(); commandManager.registerAsynchronousCompletions();
} }
return commandManager; return commandManager;
} }
@ -176,7 +181,7 @@ public class TerraBukkitPlugin extends JavaPlugin {
logger.warn(""" logger.warn("""
You are using Mohist, so we will not give you any support for issues that may arise. 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. 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 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. > I fear something terrible has happened.
> - Astrash > - Astrash
@ -189,6 +194,7 @@ public class TerraBukkitPlugin extends JavaPlugin {
@Override @Override
public @Nullable public @Nullable
ChunkGenerator getDefaultWorldGenerator(@NotNull String worldName, String id) { ChunkGenerator getDefaultWorldGenerator(@NotNull String worldName, String id) {
if(id == null || id.trim().equals("")) { return null; }
return new BukkitChunkGeneratorWrapper(generatorMap.computeIfAbsent(worldName, name -> { return new BukkitChunkGeneratorWrapper(generatorMap.computeIfAbsent(worldName, name -> {
ConfigPack pack = platform.getConfigRegistry().getByID(id).orElseThrow( ConfigPack pack = platform.getConfigRegistry().getByID(id).orElseThrow(
() -> new IllegalArgumentException("No such config pack \"" + id + "\"")); () -> new IllegalArgumentException("No such config pack \"" + id + "\""));

View File

@ -61,8 +61,9 @@ public class BukkitWorldHandle implements WorldHandle {
@Override @Override
public @NotNull EntityType getEntity(@NotNull String id) { public @NotNull EntityType getEntity(@NotNull String id) {
if (!id.contains(":")) { //TODO: remove in 7.0 if(!id.contains(":")) { //TODO: remove in 7.0
String newid = "minecraft:" + id.toLowerCase();; String newid = "minecraft:" + id.toLowerCase();
;
logger.warn( logger.warn(
"Translating " + id + " to " + newid + ". In 1.20.3 entity parsing was reworked" + "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 " + ". You are advised to perform this rename in your config backs as this translation will be removed in the next major " +
@ -72,7 +73,7 @@ public class BukkitWorldHandle implements WorldHandle {
String entityID = id.toUpperCase(Locale.ROOT).substring(10); String entityID = id.toUpperCase(Locale.ROOT).substring(10);
return new BukkitEntityType(switch(entityID) { return new BukkitEntityType(switch(entityID) {
case "END_CRYSTAL" -> org.bukkit.entity.EntityType.ENDER_CRYSTAL; case "END_CRYSTAL" -> org.bukkit.entity.EntityType.END_CRYSTAL;
case "ENDER_CRYSTAL" -> throw new IllegalArgumentException( case "ENDER_CRYSTAL" -> throw new IllegalArgumentException(
"Invalid entity identifier " + id); // make sure this issue can't happen the other way around. "Invalid entity identifier " + id); // make sure this issue can't happen the other way around.
default -> org.bukkit.entity.EntityType.valueOf(entityID); default -> org.bukkit.entity.EntityType.valueOf(entityID);

View File

@ -1,20 +1,25 @@
package com.dfsek.terra.bukkit.nms; package com.dfsek.terra.bukkit.nms;
import org.bukkit.Bukkit;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.dfsek.terra.bukkit.PlatformImpl; import com.dfsek.terra.bukkit.PlatformImpl;
import com.dfsek.terra.bukkit.util.VersionUtil;
public interface Initializer { public interface Initializer {
String NMS = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]; String NMS = VersionUtil.getMinecraftVersionInfo().toString().replace(".", "_");
String TERRA_PACKAGE = Initializer.class.getPackageName(); String TERRA_PACKAGE = Initializer.class.getPackageName();
static boolean init(PlatformImpl platform) { static boolean init(PlatformImpl platform) {
Logger logger = LoggerFactory.getLogger(Initializer.class); Logger logger = LoggerFactory.getLogger(Initializer.class);
try { try {
Class<?> initializerClass = Class.forName(TERRA_PACKAGE + "." + NMS + ".NMSInitializer"); String packageVersion = NMS;
if(NMS.equals("v1_21_1")) {
packageVersion = "v1_21";
}
Class<?> initializerClass = Class.forName(TERRA_PACKAGE + "." + packageVersion + ".NMSInitializer");
try { try {
Initializer initializer = (Initializer) initializerClass.getConstructor().newInstance(); Initializer initializer = (Initializer) initializerClass.getConstructor().newInstance();
initializer.initialize(platform); initializer.initialize(platform);

View File

@ -77,13 +77,13 @@ public final class VersionUtil {
public static final class MinecraftVersionInfo { public static final class MinecraftVersionInfo {
private static final Logger logger = LoggerFactory.getLogger(MinecraftVersionInfo.class); private static final Logger logger = LoggerFactory.getLogger(MinecraftVersionInfo.class);
private static final Pattern VERSION_PATTERN = Pattern.compile("v?(\\d+)_(\\d+)_R(\\d+)"); private static final Pattern VERSION_PATTERN = Pattern.compile("(\\d+)\\.(\\d+)(?:\\.(\\d+))?");
private final int major; private final int major;
private final int minor; private final int minor;
private final int patch; private final int patch;
private MinecraftVersionInfo() { private MinecraftVersionInfo() {
this(Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]); this(Bukkit.getServer().getBukkitVersion().split("-")[0]);
} }
private MinecraftVersionInfo(int major, int minor, int patch) { private MinecraftVersionInfo(int major, int minor, int patch) {
@ -97,7 +97,7 @@ public final class VersionUtil {
if(versionMatcher.find()) { if(versionMatcher.find()) {
major = Integer.parseInt(versionMatcher.group(1)); major = Integer.parseInt(versionMatcher.group(1));
minor = Integer.parseInt(versionMatcher.group(2)); minor = Integer.parseInt(versionMatcher.group(2));
patch = Integer.parseInt(versionMatcher.group(3)); patch = versionMatcher.group(3) != null ? Integer.parseInt(versionMatcher.group(3)) : -1;
} else { } else {
logger.warn("Error while parsing minecraft version info. Continuing launch, but setting all versions to -1."); logger.warn("Error while parsing minecraft version info. Continuing launch, but setting all versions to -1.");
@ -112,7 +112,11 @@ public final class VersionUtil {
if(major == -1 && minor == -1 && patch == -1) if(major == -1 && minor == -1 && patch == -1)
return "Unknown"; return "Unknown";
return String.format("v%d.%d.%d", major, minor, patch); if(patch >= 0) {
return String.format("v%d.%d.%d", major, minor, patch);
} else {
return String.format("v%d.%d", major, minor);
}
} }
public int getMajor() { public int getMajor() {

View File

@ -1,9 +1,9 @@
package com.dfsek.terra.bukkit.world; package com.dfsek.terra.bukkit.world;
import org.bukkit.generator.WorldInfo;
import com.dfsek.terra.api.world.info.WorldProperties; import com.dfsek.terra.api.world.info.WorldProperties;
import org.bukkit.generator.WorldInfo;
public class BukkitWorldProperties implements WorldProperties { public class BukkitWorldProperties implements WorldProperties {
private final WorldInfo delegate; private final WorldInfo delegate;

View File

@ -2,8 +2,8 @@ name: "Terra"
main: "com.dfsek.terra.bukkit.TerraBukkitPlugin" main: "com.dfsek.terra.bukkit.TerraBukkitPlugin"
version: "@VERSION@" version: "@VERSION@"
load: "STARTUP" load: "STARTUP"
author: dfsek authors: [ "dfsek", "duplexsystem", "Astrash", "solonovamax", "Sancires", "Aureus", "RogueShade" ]
website: "@WIKI@" website: "@WIKI@"
api-version: "1.20" api-version: "1.21.1"
description: "@DESCRIPTION@" description: "@DESCRIPTION@"
folia-supported: true folia-supported: true

View File

@ -1,9 +1,5 @@
apply(plugin = "io.papermc.paperweight.userdev") apply(plugin = "io.papermc.paperweight.userdev")
repositories {
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/")
}
dependencies { dependencies {
api(project(":platforms:bukkit:common")) api(project(":platforms:bukkit:common"))
paperDevBundle(Versions.Bukkit.paperDevBundle) paperDevBundle(Versions.Bukkit.paperDevBundle)

View File

@ -1,10 +1,10 @@
package com.dfsek.terra.bukkit.nms.v1_20_R3; package com.dfsek.terra.bukkit.nms.v1_21;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import com.mojang.serialization.Lifecycle;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.core.Holder.Reference; import net.minecraft.core.Holder.Reference;
import net.minecraft.core.MappedRegistry; import net.minecraft.core.MappedRegistry;
import net.minecraft.core.RegistrationInfo;
import net.minecraft.core.WritableRegistry; import net.minecraft.core.WritableRegistry;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
@ -41,15 +41,16 @@ public class AwfulBukkitHacks {
try { try {
BukkitPlatformBiome platformBiome = (BukkitPlatformBiome) biome.getPlatformBiome(); BukkitPlatformBiome platformBiome = (BukkitPlatformBiome) biome.getPlatformBiome();
NamespacedKey vanillaBukkitKey = platformBiome.getHandle().getKey(); NamespacedKey vanillaBukkitKey = platformBiome.getHandle().getKey();
ResourceLocation vanillaMinecraftKey = new ResourceLocation(vanillaBukkitKey.getNamespace(), vanillaBukkitKey.getKey()); ResourceLocation vanillaMinecraftKey = ResourceLocation.fromNamespaceAndPath(vanillaBukkitKey.getNamespace(),
vanillaBukkitKey.getKey());
Biome platform = NMSBiomeInjector.createBiome(biome, Objects.requireNonNull(biomeRegistry.get(vanillaMinecraftKey))); Biome platform = NMSBiomeInjector.createBiome(biome, Objects.requireNonNull(biomeRegistry.get(vanillaMinecraftKey)));
ResourceKey<Biome> delegateKey = ResourceKey.create( ResourceKey<Biome> delegateKey = ResourceKey.create(
Registries.BIOME, Registries.BIOME,
new ResourceLocation("terra", NMSBiomeInjector.createBiomeID(pack, key)) ResourceLocation.fromNamespaceAndPath("terra", NMSBiomeInjector.createBiomeID(pack, key))
); );
Reference<Biome> holder = biomeRegistry.register(delegateKey, platform, Lifecycle.stable()); Reference<Biome> holder = biomeRegistry.register(delegateKey, platform, RegistrationInfo.BUILT_IN);
Reflection.REFERENCE.invokeBindValue(holder, platform); // IMPORTANT: bind holder. Reflection.REFERENCE.invokeBindValue(holder, platform); // IMPORTANT: bind holder.
platformBiome.getContext().put(new NMSBiomeInfo(delegateKey)); platformBiome.getContext().put(new NMSBiomeInfo(delegateKey));

View File

@ -1,4 +1,4 @@
package com.dfsek.terra.bukkit.nms.v1_20_R3; package com.dfsek.terra.bukkit.nms.v1_21;
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.Biome;

View File

@ -1,4 +1,4 @@
package com.dfsek.terra.bukkit.nms.v1_20_R3; package com.dfsek.terra.bukkit.nms.v1_21;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;

View File

@ -1,6 +1,6 @@
package com.dfsek.terra.bukkit.nms.v1_20_R3; package com.dfsek.terra.bukkit.nms.v1_21;
import com.mojang.serialization.Codec; import com.mojang.serialization.MapCodec;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.Biome;
@ -35,8 +35,12 @@ public class NMSBiomeProvider extends BiomeSource {
} }
@Override @Override
protected @NotNull Codec<? extends BiomeSource> codec() { protected @NotNull MapCodec<? extends BiomeSource> codec() {
return 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;
} }
@Override @Override

View File

@ -1,6 +1,6 @@
package com.dfsek.terra.bukkit.nms.v1_20_R3; package com.dfsek.terra.bukkit.nms.v1_21;
import com.mojang.serialization.Codec; import com.mojang.serialization.MapCodec;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.server.level.WorldGenRegion; import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelAccessor;
@ -19,14 +19,13 @@ import net.minecraft.world.level.levelgen.GenerationStep.Carving;
import net.minecraft.world.level.levelgen.Heightmap.Types; import net.minecraft.world.level.levelgen.Heightmap.Types;
import net.minecraft.world.level.levelgen.RandomState; import net.minecraft.world.level.levelgen.RandomState;
import net.minecraft.world.level.levelgen.blending.Blender; import net.minecraft.world.level.levelgen.blending.Blender;
import org.bukkit.craftbukkit.v1_20_R3.block.data.CraftBlockData; import org.bukkit.craftbukkit.block.data.CraftBlockData;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.List; import java.util.List;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
@ -54,8 +53,8 @@ public class NMSChunkGeneratorDelegate extends ChunkGenerator {
} }
@Override @Override
protected @NotNull Codec<? extends ChunkGenerator> codec() { protected @NotNull MapCodec<? extends ChunkGenerator> codec() {
return ChunkGenerator.CODEC; return MapCodec.assumeMapUnsafe(ChunkGenerator.CODEC);
} }
@Override @Override
@ -87,10 +86,10 @@ public class NMSChunkGeneratorDelegate extends ChunkGenerator {
} }
@Override @Override
public @NotNull CompletableFuture<ChunkAccess> fillFromNoise(@NotNull Executor executor, @NotNull Blender blender, public CompletableFuture<ChunkAccess> fillFromNoise(@NotNull Blender blender,
@NotNull RandomState noiseConfig, @NotNull RandomState noiseConfig,
@NotNull StructureManager structureAccessor, @NotNull ChunkAccess chunk) { @NotNull StructureManager structureAccessor, @NotNull ChunkAccess chunk) {
return vanilla.fillFromNoise(executor, blender, noiseConfig, structureAccessor, chunk) return vanilla.fillFromNoise(blender, noiseConfig, structureAccessor, chunk)
.thenApply(c -> { .thenApply(c -> {
LevelAccessor level = Reflection.STRUCTURE_MANAGER.getLevel(structureAccessor); LevelAccessor level = Reflection.STRUCTURE_MANAGER.getLevel(structureAccessor);
BiomeProvider biomeProvider = pack.getBiomeProvider(); BiomeProvider biomeProvider = pack.getBiomeProvider();

View File

@ -1,4 +1,4 @@
package com.dfsek.terra.bukkit.nms.v1_20_R3; package com.dfsek.terra.bukkit.nms.v1_21;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;

View File

@ -1,9 +1,11 @@
package com.dfsek.terra.bukkit.nms.v1_20_R3; package com.dfsek.terra.bukkit.nms.v1_21;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.chunk.status.WorldGenContext;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.craftbukkit.v1_20_R3.CraftWorld; import org.bukkit.craftbukkit.CraftWorld;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.world.WorldInitEvent; import org.bukkit.event.world.WorldInitEvent;
@ -15,6 +17,7 @@ import java.util.Set;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.util.reflection.ReflectionUtil;
import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper; import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper;
@ -37,8 +40,20 @@ public class NMSInjectListener implements Listener {
ChunkGenerator vanilla = serverWorld.getChunkSource().getGenerator(); ChunkGenerator vanilla = serverWorld.getChunkSource().getGenerator();
NMSBiomeProvider provider = new NMSBiomeProvider(pack.getBiomeProvider(), craftWorld.getSeed()); NMSBiomeProvider provider = new NMSBiomeProvider(pack.getBiomeProvider(), craftWorld.getSeed());
ChunkMap chunkMap = serverWorld.getChunkSource().chunkMap;
WorldGenContext worldGenContext = chunkMap.worldGenContext;
serverWorld.getChunkSource().chunkMap.generator = new NMSChunkGeneratorDelegate(vanilla, pack, provider, craftWorld.getSeed()); 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);
}
LOGGER.info("Successfully injected into world."); LOGGER.info("Successfully injected into world.");

View File

@ -1,4 +1,4 @@
package com.dfsek.terra.bukkit.nms.v1_20_R3; package com.dfsek.terra.bukkit.nms.v1_21;
import net.minecraft.world.level.LevelHeightAccessor; import net.minecraft.world.level.LevelHeightAccessor;

View File

@ -1,4 +1,4 @@
package com.dfsek.terra.bukkit.nms.v1_20_R3; package com.dfsek.terra.bukkit.nms.v1_21;
import net.minecraft.core.Holder; import net.minecraft.core.Holder;
import net.minecraft.core.Holder.Reference; import net.minecraft.core.Holder.Reference;

View File

@ -1,4 +1,4 @@
package com.dfsek.terra.bukkit.nms.v1_20_R3; package com.dfsek.terra.bukkit.nms.v1_21;
import net.minecraft.core.Registry; import net.minecraft.core.Registry;
import net.minecraft.core.registries.Registries; import net.minecraft.core.registries.Registries;
@ -6,7 +6,7 @@ import net.minecraft.resources.ResourceKey;
import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.biome.Biome;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_20_R3.CraftServer; import org.bukkit.craftbukkit.CraftServer;
public class RegistryFetcher { public class RegistryFetcher {

View File

@ -26,8 +26,8 @@ dependencies {
modImplementation("net.fabricmc:fabric-loader:${Versions.Mod.fabricLoader}") modImplementation("net.fabricmc:fabric-loader:${Versions.Mod.fabricLoader}")
modImplementation("cloud.commandframework", "cloud-fabric", Versions.Libraries.cloud) modImplementation("org.incendo", "cloud-fabric", Versions.Libraries.cloudFabric)
include("cloud.commandframework", "cloud-fabric", Versions.Libraries.cloud) include("org.incendo", "cloud-fabric", Versions.Libraries.cloudFabric)
modRuntimeOnly("net.fabricmc.fabric-api", "fabric-api", Versions.Fabric.fabricAPI) modRuntimeOnly("net.fabricmc.fabric-api", "fabric-api", Versions.Fabric.fabricAPI)
} }
@ -45,10 +45,6 @@ loom {
addonDir(project.file("./run/config/Terra/addons"), tasks.named("configureLaunch").get()) addonDir(project.file("./run/config/Terra/addons"), tasks.named("configureLaunch").get())
tasks { tasks {
compileJava {
options.release.set(17)
}
remapJar { remapJar {
dependsOn("installAddons") dependsOn("installAddons")

View File

@ -5,7 +5,13 @@
"name": "Terra", "name": "Terra",
"description": "@DESCRIPTION@", "description": "@DESCRIPTION@",
"authors": [ "authors": [
"dfsek" "dfsek",
"duplexsystem",
"Astrash",
"solonovamax",
"Sancires",
"Aureus",
"RogueShade"
], ],
"contact": { "contact": {
"homepage": "@WIKI@", "homepage": "@WIKI@",
@ -26,9 +32,9 @@
"terra.common.mixins.json" "terra.common.mixins.json"
], ],
"depends": { "depends": {
"fabricloader": ">=0.15.1", "fabricloader": ">=0.16.5",
"java": ">=17", "java": ">=21",
"minecraft": ">=1.20.4", "minecraft": ">=1.21.1",
"fabric": "*" "fabric": "*"
} }
} }

View File

@ -2,7 +2,7 @@
"required": true, "required": true,
"minVersion": "0.8", "minVersion": "0.8",
"package": "com.dfsek.terra.fabric.mixin", "package": "com.dfsek.terra.fabric.mixin",
"compatibilityLevel": "JAVA_17", "compatibilityLevel": "JAVA_21",
"mixins": [ "mixins": [
], ],
"client": [ "client": [

View File

@ -2,7 +2,7 @@
"required": true, "required": true,
"minVersion": "0.8", "minVersion": "0.8",
"package": "com.dfsek.terra.forge.mixin", "package": "com.dfsek.terra.forge.mixin",
"compatibilityLevel": "JAVA_17", "compatibilityLevel": "JAVA_21",
"mixins": [ "mixins": [
"lifecycle.NoiseConfigMixin" "lifecycle.NoiseConfigMixin"
], ],

View File

@ -3,6 +3,7 @@ package com.dfsek.terra.mod;
import com.dfsek.tectonic.api.TypeRegistry; import com.dfsek.tectonic.api.TypeRegistry;
import com.dfsek.tectonic.api.depth.DepthTracker; import com.dfsek.tectonic.api.depth.DepthTracker;
import com.dfsek.tectonic.api.exception.LoadException; import com.dfsek.tectonic.api.exception.LoadException;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.entity.EntityType; import net.minecraft.entity.EntityType;
import net.minecraft.entity.SpawnGroup; import net.minecraft.entity.SpawnGroup;
import net.minecraft.registry.Registry; import net.minecraft.registry.Registry;
@ -44,7 +45,6 @@ import com.dfsek.terra.mod.config.ProtoPlatformBiome;
import com.dfsek.terra.mod.config.SoundEventTemplate; import com.dfsek.terra.mod.config.SoundEventTemplate;
import com.dfsek.terra.mod.config.SpawnCostConfig; import com.dfsek.terra.mod.config.SpawnCostConfig;
import com.dfsek.terra.mod.config.SpawnEntryTemplate; import com.dfsek.terra.mod.config.SpawnEntryTemplate;
import com.dfsek.terra.mod.config.SpawnGroupTemplate;
import com.dfsek.terra.mod.config.SpawnSettingsTemplate; import com.dfsek.terra.mod.config.SpawnSettingsTemplate;
import com.dfsek.terra.mod.config.SpawnTypeConfig; import com.dfsek.terra.mod.config.SpawnTypeConfig;
import com.dfsek.terra.mod.config.VillagerTypeTemplate; import com.dfsek.terra.mod.config.VillagerTypeTemplate;
@ -82,6 +82,7 @@ public abstract class ModPlatform extends AbstractPlatform {
.registerLoader(GrassColorModifier.class, .registerLoader(GrassColorModifier.class,
(type, o, loader, depthTracker) -> TemperatureModifier.valueOf(((String) o).toUpperCase( (type, o, loader, depthTracker) -> TemperatureModifier.valueOf(((String) o).toUpperCase(
Locale.ROOT))) Locale.ROOT)))
.registerLoader(SpawnGroup.class, (type, o, loader, depthTracker) -> SpawnGroup.valueOf((String) o))
.registerLoader(BiomeParticleConfig.class, BiomeParticleConfigTemplate::new) .registerLoader(BiomeParticleConfig.class, BiomeParticleConfigTemplate::new)
.registerLoader(SoundEvent.class, SoundEventTemplate::new) .registerLoader(SoundEvent.class, SoundEventTemplate::new)
.registerLoader(BiomeMoodSound.class, BiomeMoodSoundTemplate::new) .registerLoader(BiomeMoodSound.class, BiomeMoodSoundTemplate::new)
@ -90,7 +91,6 @@ public abstract class ModPlatform extends AbstractPlatform {
.registerLoader(EntityType.class, EntityTypeTemplate::new) .registerLoader(EntityType.class, EntityTypeTemplate::new)
.registerLoader(SpawnCostConfig.class, SpawnCostConfig::new) .registerLoader(SpawnCostConfig.class, SpawnCostConfig::new)
.registerLoader(SpawnEntry.class, SpawnEntryTemplate::new) .registerLoader(SpawnEntry.class, SpawnEntryTemplate::new)
.registerLoader(SpawnGroup.class, SpawnGroupTemplate::new)
.registerLoader(SpawnTypeConfig.class, SpawnTypeConfig::new) .registerLoader(SpawnTypeConfig.class, SpawnTypeConfig::new)
.registerLoader(SpawnSettings.class, SpawnSettingsTemplate::new) .registerLoader(SpawnSettings.class, SpawnSettingsTemplate::new)
.registerLoader(VillagerType.class, VillagerTypeTemplate::new); .registerLoader(VillagerType.class, VillagerTypeTemplate::new);
@ -117,6 +117,8 @@ public abstract class ModPlatform extends AbstractPlatform {
public abstract Registry<MultiNoiseBiomeSourceParameterList> multiNoiseBiomeSourceParameterListRegistry(); public abstract Registry<MultiNoiseBiomeSourceParameterList> multiNoiseBiomeSourceParameterListRegistry();
public abstract Registry<Enchantment> enchantmentRegistry();
@Override @Override
public @NotNull WorldHandle getWorldHandle() { public @NotNull WorldHandle getWorldHandle() {
return worldHandle; return worldHandle;
@ -126,4 +128,6 @@ public abstract class ModPlatform extends AbstractPlatform {
public @NotNull ItemHandle getItemHandle() { public @NotNull ItemHandle getItemHandle() {
return itemHandle; return itemHandle;
} }
} }

View File

@ -7,6 +7,7 @@ import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.command.argument.ParticleEffectArgumentType; import net.minecraft.command.argument.ParticleEffectArgumentType;
import net.minecraft.registry.Registries; import net.minecraft.registry.Registries;
import net.minecraft.registry.RegistryWrapper;
import net.minecraft.world.biome.BiomeParticleConfig; import net.minecraft.world.biome.BiomeParticleConfig;
@ -27,7 +28,8 @@ public class BiomeParticleConfigTemplate implements ObjectTemplate<BiomeParticle
try { try {
return new BiomeParticleConfig( return new BiomeParticleConfig(
ParticleEffectArgumentType.readParameters(new StringReader(particle), Registries.PARTICLE_TYPE.getReadOnlyWrapper()), ParticleEffectArgumentType.readParameters(new StringReader(particle),
(RegistryWrapper.WrapperLookup) Registries.PARTICLE_TYPE.getReadOnlyWrapper()),
probability); probability);
} catch(CommandSyntaxException e) { } catch(CommandSyntaxException e) {
throw new RuntimeException(e); throw new RuntimeException(e);

View File

@ -1,18 +0,0 @@
package com.dfsek.terra.mod.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.entity.SpawnGroup;
public class SpawnGroupTemplate implements ObjectTemplate<SpawnGroup> {
@Value("group")
@Default
private String group = null;
@Override
public SpawnGroup get() {
return SpawnGroup.valueOf(group);
}
}

View File

@ -3,7 +3,9 @@ package com.dfsek.terra.mod.config;
import com.dfsek.tectonic.api.config.template.annotations.Default; 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.annotations.Value;
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
import net.minecraft.entity.SpawnGroup;
import net.minecraft.world.biome.SpawnSettings; import net.minecraft.world.biome.SpawnSettings;
import net.minecraft.world.biome.SpawnSettings.SpawnEntry;
import java.util.List; import java.util.List;
@ -25,7 +27,10 @@ public class SpawnSettingsTemplate implements ObjectTemplate<SpawnSettings> {
public SpawnSettings get() { public SpawnSettings get() {
SpawnSettings.Builder builder = new SpawnSettings.Builder(); SpawnSettings.Builder builder = new SpawnSettings.Builder();
for(SpawnTypeConfig spawn : spawns) { for(SpawnTypeConfig spawn : spawns) {
builder.spawn(spawn.getGroup(), spawn.getEntry()); SpawnGroup group = spawn.getGroup();
for(SpawnEntry entry : spawn.getEntry()) {
builder.spawn(group, entry);
}
} }
for(SpawnCostConfig cost : costs) { for(SpawnCostConfig cost : costs) {
builder.spawnCost(cost.getType(), cost.getMass(), cost.getGravity()); builder.spawnCost(cost.getType(), cost.getMass(), cost.getGravity());

View File

@ -6,21 +6,23 @@ import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
import net.minecraft.entity.SpawnGroup; import net.minecraft.entity.SpawnGroup;
import net.minecraft.world.biome.SpawnSettings.SpawnEntry; import net.minecraft.world.biome.SpawnSettings.SpawnEntry;
import java.util.List;
public class SpawnTypeConfig implements ObjectTemplate<SpawnTypeConfig> { public class SpawnTypeConfig implements ObjectTemplate<SpawnTypeConfig> {
@Value("group") @Value("group")
@Default @Default
private SpawnGroup group = null; private SpawnGroup group = null;
@Value("entry") @Value("entries")
@Default @Default
private SpawnEntry entry = null; private List<SpawnEntry> entry = null;
public SpawnGroup getGroup() { public SpawnGroup getGroup() {
return group; return group;
} }
public SpawnEntry getEntry() { public List<SpawnEntry> getEntry() {
return entry; return entry;
} }

View File

@ -1,6 +1,7 @@
package com.dfsek.terra.mod.data; package com.dfsek.terra.mod.data;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder; import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.world.gen.chunk.ChunkGeneratorSettings; import net.minecraft.world.gen.chunk.ChunkGeneratorSettings;
@ -32,15 +33,15 @@ public final class Codecs {
"No such config pack " + "No such config pack " +
id))))); id)))));
public static final Codec<TerraBiomeSource> TERRA_BIOME_SOURCE = RecordCodecBuilder public static final MapCodec<TerraBiomeSource> TERRA_BIOME_SOURCE = RecordCodecBuilder
.create(instance -> instance.group( .mapCodec(instance -> instance.group(
CONFIG_PACK.fieldOf("pack") CONFIG_PACK.fieldOf("pack")
.stable() .stable()
.forGetter(TerraBiomeSource::getPack)) .forGetter(TerraBiomeSource::getPack))
.apply(instance, instance.stable(TerraBiomeSource::new))); .apply(instance, instance.stable(TerraBiomeSource::new)));
public static final Codec<MinecraftChunkGeneratorWrapper> MINECRAFT_CHUNK_GENERATOR_WRAPPER = RecordCodecBuilder public static final MapCodec<MinecraftChunkGeneratorWrapper> MINECRAFT_CHUNK_GENERATOR_WRAPPER = RecordCodecBuilder
.create( .mapCodec(
instance -> instance.group( instance -> instance.group(
TERRA_BIOME_SOURCE.fieldOf("biome_source") TERRA_BIOME_SOURCE.fieldOf("biome_source")
.stable() .stable()

View File

@ -17,7 +17,7 @@
package com.dfsek.terra.mod.generation; package com.dfsek.terra.mod.generation;
import com.mojang.serialization.Codec; import com.mojang.serialization.MapCodec;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.registry.entry.RegistryEntry;
@ -48,7 +48,6 @@ import org.slf4j.LoggerFactory;
import java.util.List; import java.util.List;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.api.config.ConfigPack;
import com.dfsek.terra.api.world.biome.generation.BiomeProvider; import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
@ -85,7 +84,7 @@ public class MinecraftChunkGeneratorWrapper extends net.minecraft.world.gen.chun
} }
@Override @Override
protected Codec<? extends net.minecraft.world.gen.chunk.ChunkGenerator> getCodec() { protected MapCodec<? extends net.minecraft.world.gen.chunk.ChunkGenerator> getCodec() {
return Codecs.MINECRAFT_CHUNK_GENERATOR_WRAPPER; return Codecs.MINECRAFT_CHUNK_GENERATOR_WRAPPER;
} }
@ -110,10 +109,9 @@ public class MinecraftChunkGeneratorWrapper extends net.minecraft.world.gen.chun
return settings.value().generationShapeConfig().height(); return settings.value().generationShapeConfig().height();
} }
@Override @Override
public CompletableFuture<Chunk> populateNoise(Executor executor, Blender blender, NoiseConfig noiseConfig, public CompletableFuture<Chunk> populateNoise(Blender blender, NoiseConfig noiseConfig, StructureAccessor structureAccessor,
StructureAccessor structureAccessor, Chunk chunk) { Chunk chunk) {
return CompletableFuture.supplyAsync(() -> { return CompletableFuture.supplyAsync(() -> {
ProtoWorld world = (ProtoWorld) ((StructureAccessorAccessor) structureAccessor).getWorld(); ProtoWorld world = (ProtoWorld) ((StructureAccessorAccessor) structureAccessor).getWorld();
BiomeProvider biomeProvider = pack.getBiomeProvider(); BiomeProvider biomeProvider = pack.getBiomeProvider();

View File

@ -17,7 +17,7 @@
package com.dfsek.terra.mod.generation; package com.dfsek.terra.mod.generation;
import com.mojang.serialization.Codec; import com.mojang.serialization.MapCodec;
import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.world.biome.Biome; import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.source.BiomeSource; import net.minecraft.world.biome.source.BiomeSource;
@ -47,7 +47,7 @@ public class TerraBiomeSource extends BiomeSource {
} }
@Override @Override
protected Codec<? extends BiomeSource> getCodec() { protected MapCodec<? extends BiomeSource> getCodec() {
return Codecs.TERRA_BIOME_SOURCE; return Codecs.TERRA_BIOME_SOURCE;
} }

View File

@ -21,14 +21,15 @@ import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.command.CommandRegistryAccess; import net.minecraft.command.CommandRegistryAccess;
import net.minecraft.command.argument.ItemStackArgumentType; import net.minecraft.command.argument.ItemStackArgumentType;
import net.minecraft.registry.Registries;
import net.minecraft.registry.Registry; import net.minecraft.registry.Registry;
import net.minecraft.registry.RegistryKey; import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryWrapper; import net.minecraft.registry.RegistryWrapper.Impl;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.dfsek.terra.api.handle.ItemHandle; import com.dfsek.terra.api.handle.ItemHandle;
import com.dfsek.terra.api.inventory.Item; import com.dfsek.terra.api.inventory.Item;
@ -43,8 +44,13 @@ public class MinecraftItemHandle implements ItemHandle {
try { try {
return (Item) new ItemStackArgumentType(new CommandRegistryAccess() { return (Item) new ItemStackArgumentType(new CommandRegistryAccess() {
@Override @Override
public <T> RegistryWrapper<T> createWrapper(RegistryKey<? extends Registry<T>> registryRef) { public Stream<RegistryKey<? extends Registry<?>>> streamAllRegistryKeys() {
return CommonPlatform.get().getServer().getRegistryManager().getWrapperOrThrow(registryRef); return CommonPlatform.get().getServer().getRegistryManager().streamAllRegistryKeys();
}
@Override
public <T> Optional<Impl<T>> getOptionalWrapper(RegistryKey<? extends Registry<? extends T>> registryRef) {
return Optional.of(CommonPlatform.get().getServer().getRegistryManager().getWrapperOrThrow(registryRef));
} }
}).parse(new StringReader(data)).getItem(); }).parse(new StringReader(data)).getItem();
} catch(CommandSyntaxException e) { } catch(CommandSyntaxException e) {
@ -54,11 +60,12 @@ public class MinecraftItemHandle implements ItemHandle {
@Override @Override
public Enchantment getEnchantment(String id) { public Enchantment getEnchantment(String id) {
return (Enchantment) (Registries.ENCHANTMENT.get(Identifier.tryParse(id))); return (Enchantment) (Object) (CommonPlatform.get().enchantmentRegistry().get(Identifier.tryParse(id)));
} }
@Override @Override
public Set<Enchantment> getEnchantments() { public Set<Enchantment> getEnchantments() {
return Registries.ENCHANTMENT.stream().map(enchantment -> (Enchantment) enchantment).collect(Collectors.toSet()); return CommonPlatform.get().enchantmentRegistry().stream().map(enchantment -> (Enchantment) (Object) enchantment).collect(
Collectors.toSet());
} }
} }

View File

@ -64,8 +64,9 @@ public class MinecraftWorldHandle implements WorldHandle {
@Override @Override
public @NotNull EntityType getEntity(@NotNull String id) { public @NotNull EntityType getEntity(@NotNull String id) {
if (!id.contains(":")) { //TODO: remove in 7.0 if(!id.contains(":")) { //TODO: remove in 7.0
String newid = "minecraft:" + id.toLowerCase();; String newid = "minecraft:" + id.toLowerCase();
;
logger.warn( logger.warn(
"Translating " + id + " to " + newid + ". In 1.20.3 entity parsing was reworked" + "Translating " + id + " to " + newid + ". In 1.20.3 entity parsing was reworked" +
". You are advised to perform this rename in your config packs as this translation will be removed in the next major " + ". You are advised to perform this rename in your config packs as this translation will be removed in the next major " +

View File

@ -49,8 +49,9 @@ public abstract class MobSpawnerBlockEntityMixin extends BlockEntity {
@Shadow @Shadow
public abstract MobSpawnerLogic getLogic(); public abstract MobSpawnerLogic getLogic();
//method_46408
@Shadow @Shadow
public abstract void method_46408(net.minecraft.entity.EntityType<?> entityType, Random random); public abstract void setEntityType(net.minecraft.entity.EntityType<?> entityType, Random random);
public EntityType terra$getSpawnedType() { public EntityType terra$getSpawnedType() {
return (EntityType) Registries.ENTITY_TYPE.get( return (EntityType) Registries.ENTITY_TYPE.get(
@ -59,12 +60,12 @@ public abstract class MobSpawnerBlockEntityMixin extends BlockEntity {
public void terra$setSpawnedType(@NotNull EntityType creatureType) { public void terra$setSpawnedType(@NotNull EntityType creatureType) {
Random rand; Random rand;
if (hasWorld()) { if(hasWorld()) {
rand = world.getRandom(); rand = world.getRandom();
} else { } else {
rand = Random.create(); rand = Random.create();
} }
method_46408((net.minecraft.entity.EntityType<?>) creatureType, rand); setEntityType((net.minecraft.entity.EntityType<?>) creatureType, rand);
} }
public int terra$getDelay() { public int terra$getDelay() {

View File

@ -1,8 +1,8 @@
package com.dfsek.terra.mod.mixin.implementations.terra.block.state; package com.dfsek.terra.mod.mixin.implementations.terra.block.state;
import com.google.common.collect.ImmutableMap;
import com.mojang.serialization.MapCodec; import com.mojang.serialization.MapCodec;
import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap;
import net.minecraft.block.AbstractBlock.AbstractBlockState; import net.minecraft.block.AbstractBlock.AbstractBlockState;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.registry.Registries; import net.minecraft.registry.Registries;
@ -24,7 +24,7 @@ import com.dfsek.terra.mod.mixin.access.StateAccessor;
@Mixin(AbstractBlockState.class) @Mixin(AbstractBlockState.class)
@Implements(@Interface(iface = BlockState.class, prefix = "terra$")) @Implements(@Interface(iface = BlockState.class, prefix = "terra$"))
public abstract class BlockStateMixin extends State<Block, net.minecraft.block.BlockState> { public abstract class BlockStateMixin extends State<Block, net.minecraft.block.BlockState> {
private BlockStateMixin(Block owner, ImmutableMap<net.minecraft.state.property.Property<?>, Comparable<?>> entries, private BlockStateMixin(Block owner, Reference2ObjectArrayMap<net.minecraft.state.property.Property<?>, Comparable<?>> entries,
MapCodec<net.minecraft.block.BlockState> codec) { MapCodec<net.minecraft.block.BlockState> codec) {
super(owner, entries, codec); super(owner, entries, codec);
} }

View File

@ -39,14 +39,14 @@ public abstract class EntityMixin {
private BlockPos blockPos; private BlockPos blockPos;
@Shadow @Shadow
public abstract void teleport(double destX, double destY, double destZ); public abstract void updatePosition(double destX, double destY, double destZ);
public Vector3 terra$position() { public Vector3 terra$position() {
return MinecraftAdapter.adapt(blockPos); return MinecraftAdapter.adapt(blockPos);
} }
public void terra$position(Vector3 location) { public void terra$position(Vector3 location) {
teleport(location.getX(), location.getY(), location.getZ()); updatePosition(location.getX(), location.getY(), location.getZ());
} }
public ServerWorld terra$world() { public ServerWorld terra$world() {

View File

@ -30,7 +30,7 @@ import com.dfsek.terra.api.inventory.ItemStack;
@Implements(@Interface(iface = com.dfsek.terra.api.inventory.Item.class, prefix = "terra$")) @Implements(@Interface(iface = com.dfsek.terra.api.inventory.Item.class, prefix = "terra$"))
public abstract class ItemMixin { public abstract class ItemMixin {
@Shadow @Shadow
public abstract int getMaxDamage(); public abstract net.minecraft.item.ItemStack getDefaultStack();
@SuppressWarnings("ConstantConditions") @SuppressWarnings("ConstantConditions")
public ItemStack terra$newItemStack(int amount) { public ItemStack terra$newItemStack(int amount) {
@ -38,6 +38,7 @@ public abstract class ItemMixin {
} }
public double terra$getMaxDurability() { public double terra$getMaxDurability() {
return getMaxDamage(); //TODO verify this is correct
return getDefaultStack().getMaxDamage();
} }
} }

View File

@ -17,9 +17,11 @@
package com.dfsek.terra.mod.mixin.implementations.terra.inventory.item; package com.dfsek.terra.mod.mixin.implementations.terra.inventory.item;
import net.minecraft.component.ComponentChanges;
import net.minecraft.component.ComponentMap;
import net.minecraft.component.ComponentMapImpl;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound; import org.spongepowered.asm.mixin.Final;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Intrinsic;
@ -33,6 +35,10 @@ import com.dfsek.terra.api.inventory.item.ItemMeta;
@Mixin(ItemStack.class) @Mixin(ItemStack.class)
@Implements(@Interface(iface = com.dfsek.terra.api.inventory.ItemStack.class, prefix = "terra$")) @Implements(@Interface(iface = com.dfsek.terra.api.inventory.ItemStack.class, prefix = "terra$"))
public abstract class ItemStackMixin { public abstract class ItemStackMixin {
@Shadow
@Final
private ComponentMapImpl components;
@Shadow @Shadow
public abstract int getCount(); public abstract int getCount();
@ -46,7 +52,7 @@ public abstract class ItemStackMixin {
public abstract boolean isDamageable(); public abstract boolean isDamageable();
@Shadow @Shadow
public abstract void setNbt(@Nullable NbtCompound tag); public abstract ComponentMap getComponents();
public int terra$getAmount() { public int terra$getAmount() {
return getCount(); return getCount();
@ -66,7 +72,13 @@ public abstract class ItemStackMixin {
@SuppressWarnings("ConstantConditions") @SuppressWarnings("ConstantConditions")
public void terra$setItemMeta(ItemMeta meta) { public void terra$setItemMeta(ItemMeta meta) {
setNbt(((ItemStack) (Object) meta).getNbt()); ComponentChanges.Builder builder = ComponentChanges.builder();
this.getComponents().getTypes().forEach(builder::remove);
ComponentMap components = ((ItemStack) (Object) meta).getComponents();
components.forEach(builder::add);
this.components.applyChanges(builder.build());
} }
@Intrinsic @Intrinsic

View File

@ -18,7 +18,9 @@
package com.dfsek.terra.mod.mixin.implementations.terra.inventory.meta; package com.dfsek.terra.mod.mixin.implementations.terra.inventory.meta;
import net.minecraft.enchantment.Enchantment; import net.minecraft.enchantment.Enchantment;
import net.minecraft.registry.Registries; import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.registry.entry.RegistryEntryList;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@ -27,16 +29,20 @@ import org.spongepowered.asm.mixin.Shadow;
import java.util.Objects; import java.util.Objects;
import com.dfsek.terra.api.inventory.ItemStack; import com.dfsek.terra.api.inventory.ItemStack;
import com.dfsek.terra.mod.CommonPlatform;
import static net.minecraft.enchantment.Enchantment.canBeCombined;
@Mixin(Enchantment.class) @Mixin(Enchantment.class)
@Implements(@Interface(iface = com.dfsek.terra.api.inventory.item.Enchantment.class, prefix = "terra$")) @Implements(@Interface(iface = com.dfsek.terra.api.inventory.item.Enchantment.class, prefix = "terra$"))
public abstract class EnchantmentMixin { public abstract class EnchantmentMixin {
@Shadow @Shadow
public abstract boolean isAcceptableItem(net.minecraft.item.ItemStack stack); @Final
private RegistryEntryList<Enchantment> exclusiveSet;
@Shadow @Shadow
public abstract boolean canCombine(Enchantment other); public abstract boolean isAcceptableItem(net.minecraft.item.ItemStack stack);
@SuppressWarnings("ConstantConditions") @SuppressWarnings("ConstantConditions")
public boolean terra$canEnchantItem(ItemStack itemStack) { public boolean terra$canEnchantItem(ItemStack itemStack) {
@ -44,10 +50,10 @@ public abstract class EnchantmentMixin {
} }
public boolean terra$conflictsWith(com.dfsek.terra.api.inventory.item.Enchantment other) { public boolean terra$conflictsWith(com.dfsek.terra.api.inventory.item.Enchantment other) {
return !canCombine((Enchantment) other); return canBeCombined(RegistryEntry.of((Enchantment) (Object) this), RegistryEntry.of((Enchantment) (Object) other));
} }
public String terra$getID() { public String terra$getID() {
return Objects.requireNonNull(Registries.ENCHANTMENT.getId((Enchantment) (Object) this)).toString(); return Objects.requireNonNull(CommonPlatform.get().enchantmentRegistry().getId((Enchantment) (Object) this)).toString();
} }
} }

View File

@ -17,10 +17,9 @@
package com.dfsek.terra.mod.mixin.implementations.terra.inventory.meta; package com.dfsek.terra.mod.mixin.implementations.terra.inventory.meta;
import net.minecraft.component.type.ItemEnchantmentsComponent;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound; import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.nbt.NbtList;
import net.minecraft.registry.Registries;
import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Implements;
import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Interface;
import org.spongepowered.asm.mixin.Intrinsic; import org.spongepowered.asm.mixin.Intrinsic;
@ -42,13 +41,14 @@ public abstract class ItemStackMetaMixin {
public abstract boolean hasEnchantments(); public abstract boolean hasEnchantments();
@Shadow @Shadow
public abstract NbtList getEnchantments(); public abstract ItemEnchantmentsComponent getEnchantments();
@Shadow @Shadow
public abstract void addEnchantment(net.minecraft.enchantment.Enchantment enchantment, int level); public abstract void addEnchantment(RegistryEntry<net.minecraft.enchantment.Enchantment> enchantment, int level);
public void terra$addEnchantment(Enchantment enchantment, int level) { public void terra$addEnchantment(Enchantment enchantment, int level) {
addEnchantment((net.minecraft.enchantment.Enchantment) enchantment, level); ;
addEnchantment(RegistryEntry.of((net.minecraft.enchantment.Enchantment) (Object) enchantment), level);
} }
@Intrinsic(displace = true) @Intrinsic(displace = true)
@ -56,9 +56,10 @@ public abstract class ItemStackMetaMixin {
if(!hasEnchantments()) return Collections.emptyMap(); if(!hasEnchantments()) return Collections.emptyMap();
Map<Enchantment, Integer> map = new HashMap<>(); Map<Enchantment, Integer> map = new HashMap<>();
getEnchantments().forEach(enchantment -> { ItemEnchantmentsComponent enchantments = getEnchantments();
NbtCompound eTag = (NbtCompound) enchantment; enchantments.getEnchantments().forEach(enchantment -> {
map.put((Enchantment) Registries.ENCHANTMENT.get(eTag.getInt("id")), eTag.getInt("lvl")); net.minecraft.enchantment.Enchantment enchantmentValue = enchantment.value();
map.put((Enchantment) (Object) enchantmentValue, enchantments.getLevel(RegistryEntry.of(enchantmentValue)));
}); });
return map; return map;
} }

View File

@ -19,11 +19,12 @@ package com.dfsek.terra.mod.mixin.implementations.terra.world;
import net.minecraft.block.FluidBlock; import net.minecraft.block.FluidBlock;
import net.minecraft.fluid.Fluid; import net.minecraft.fluid.Fluid;
import net.minecraft.util.collection.BoundedRegionArray;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.ChunkRegion; import net.minecraft.world.ChunkRegion;
import net.minecraft.world.WorldAccess; import net.minecraft.world.WorldAccess;
import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.ChunkStatus; import net.minecraft.world.chunk.ChunkGenerationStep;
import net.minecraft.world.tick.MultiTickScheduler; import net.minecraft.world.tick.MultiTickScheduler;
import net.minecraft.world.tick.OrderedTick; import net.minecraft.world.tick.OrderedTick;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
@ -36,8 +37,6 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.List;
import com.dfsek.terra.api.block.entity.BlockEntity; import com.dfsek.terra.api.block.entity.BlockEntity;
import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.block.state.BlockState;
import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.api.config.ConfigPack;
@ -48,6 +47,7 @@ import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator;
import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; import com.dfsek.terra.api.world.chunk.generation.ProtoWorld;
import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper; import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper;
import com.dfsek.terra.mod.mixin.invoke.FluidBlockInvoker;
import com.dfsek.terra.mod.util.MinecraftUtil; import com.dfsek.terra.mod.util.MinecraftUtil;
@ -74,10 +74,10 @@ public abstract class ChunkRegionMixin {
@Inject(at = @At("RETURN"), @Inject(at = @At("RETURN"),
method = "<init>(Lnet/minecraft/server/world/ServerWorld;Ljava/util/List;Lnet/minecraft/world/chunk/ChunkStatus;I)V") method = "<init>(Lnet/minecraft/server/world/ServerWorld;Lnet/minecraft/util/collection/BoundedRegionArray;" +
public void injectConstructor(net.minecraft.server.world.ServerWorld world, List<net.minecraft.world.chunk.Chunk> list, "Lnet/minecraft/world/chunk/ChunkGenerationStep;Lnet/minecraft/world/chunk/Chunk;)V")
ChunkStatus chunkStatus, int i, public void injectConstructor(net.minecraft.server.world.ServerWorld world, BoundedRegionArray chunks,
CallbackInfo ci) { ChunkGenerationStep generationStep, Chunk centerPos, CallbackInfo ci) {
this.terra$config = ((ServerWorld) world).getPack(); this.terra$config = ((ServerWorld) world).getPack();
} }
@ -88,7 +88,7 @@ public abstract class ChunkRegionMixin {
((ChunkRegion) (Object) this).setBlockState(pos, (net.minecraft.block.BlockState) data, physics ? 3 : 1042); ((ChunkRegion) (Object) this).setBlockState(pos, (net.minecraft.block.BlockState) data, physics ? 3 : 1042);
if(physics && ((net.minecraft.block.BlockState) data).getBlock() instanceof FluidBlock) { if(physics && ((net.minecraft.block.BlockState) data).getBlock() instanceof FluidBlock) {
fluidTickScheduler.scheduleTick( fluidTickScheduler.scheduleTick(
OrderedTick.create(((FluidBlock) ((net.minecraft.block.BlockState) data).getBlock()).getFluidState( OrderedTick.create((((FluidBlockInvoker) ((net.minecraft.block.BlockState) data).getBlock())).invokeGetFluidState(
(net.minecraft.block.BlockState) data).getFluid(), pos)); (net.minecraft.block.BlockState) data).getFluid(), pos));
} }
} }

View File

@ -0,0 +1,14 @@
package com.dfsek.terra.mod.mixin.invoke;
import net.minecraft.block.BlockState;
import net.minecraft.block.FluidBlock;
import net.minecraft.fluid.FluidState;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(FluidBlock.class)
public interface FluidBlockInvoker {
@Invoker("getFluidState")
FluidState invokeGetFluidState(BlockState state);
}

View File

@ -3,9 +3,12 @@ package com.dfsek.terra.mod.mixin.lifecycle;
import net.minecraft.registry.DynamicRegistryManager; import net.minecraft.registry.DynamicRegistryManager;
import net.minecraft.registry.Registry; import net.minecraft.registry.Registry;
import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.ReloadableRegistries;
import net.minecraft.server.DataPackContents; import net.minecraft.server.DataPackContents;
import net.minecraft.world.biome.Biome; import net.minecraft.world.biome.Biome;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@ -16,11 +19,16 @@ import com.dfsek.terra.mod.util.TagUtil;
@Mixin(DataPackContents.class) @Mixin(DataPackContents.class)
public class DataPackContentsMixin { public class DataPackContentsMixin {
@Shadow
@Final
private ReloadableRegistries.Lookup reloadableRegistries;
/* /*
* #refresh populates all tags in the registries * #refresh populates all tags in the registries
*/ */
@Inject(method = "refresh(Lnet/minecraft/registry/DynamicRegistryManager;)V", at = @At("RETURN")) @Inject(method = "refresh()V", at = @At("RETURN"))
private void injectReload(DynamicRegistryManager dynamicRegistryManager, CallbackInfo ci) { private void injectReload(CallbackInfo ci) {
DynamicRegistryManager.Immutable dynamicRegistryManager = this.reloadableRegistries.getRegistryManager();
TagUtil.registerWorldPresetTags(dynamicRegistryManager.get(RegistryKeys.WORLD_PRESET)); TagUtil.registerWorldPresetTags(dynamicRegistryManager.get(RegistryKeys.WORLD_PRESET));
Registry<Biome> biomeRegistry = dynamicRegistryManager.get(RegistryKeys.BIOME); Registry<Biome> biomeRegistry = dynamicRegistryManager.get(RegistryKeys.BIOME);

View File

@ -45,8 +45,9 @@ public class PresetUtil {
.orElseThrow(); .orElseThrow();
Identifier generatorID = Identifier.of("terra", pack.getID().toLowerCase(Locale.ROOT) + "/" + pack.getNamespace().toLowerCase( Identifier generatorID = Identifier.tryParse(
Locale.ROOT)); "terra:" + pack.getID().toLowerCase(Locale.ROOT) + "/" + pack.getNamespace().toLowerCase(
Locale.ROOT));
PRESETS.add(generatorID); PRESETS.add(generatorID);

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