diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 732a59b1d3..f40b5cfd8c 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,13 +1,14 @@ # Global owners, automatically request review when pull request is submitted -* @dfsek @solonovamax @duplexsystem @Astrashh @justaureus +* @dfsek @solonovamax @duplexsystem @astrsh @justaureus # Platforms /platforms/ @dfsek @solonovamax @duplexsystem @justaureus +/platforms/bukkit @dfsek @solonovamax @duplexsystem @justaureus @OakLoaf # Common -/common/ @dfsek @solonovamax @duplexsystem @Astrashh +/common/ @dfsek @solonovamax @duplexsystem @astrsh # Gradle Stuff /buildSrc/ @dfsek @solonovamax @duplexsystem *.gradle.kts @dfsek @solonovamax @duplexsystem -/gradle/ @dfsek @solonovamax @duplexsystem \ No newline at end of file +/gradle/ @dfsek @solonovamax @duplexsystem diff --git a/build.gradle.kts b/build.gradle.kts index 6d51c74f80..968d1e3b72 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,8 +1,8 @@ preRelease(true) -versionProjects(":common:api", version("6.4.3")) -versionProjects(":common:implementation", version("6.4.3")) -versionProjects(":platforms", version("6.4.3")) +versionProjects(":common:api", version("6.5.1")) +versionProjects(":common:implementation", version("6.5.1")) +versionProjects(":platforms", version("6.5.1")) allprojects { @@ -15,6 +15,7 @@ allprojects { tasks.withType().configureEach { options.isFork = true options.isIncremental = true + options.release.set(21) } tasks.withType().configureEach { @@ -44,7 +45,7 @@ afterEvaluate { } project(":platforms:bukkit:common").configureDistribution() forSubProjects(":common:addons") { - apply(plugin = "com.github.johnrengelman.shadow") + apply(plugin = "com.gradleup.shadow") tasks.named("build") { finalizedBy(tasks.named("shadowJar")) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 3bdfddef0f..cec2d002d2 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -9,18 +9,18 @@ repositories { maven("https://repo.codemc.org/repository/maven-public") { name = "CodeMC" } - maven("https://papermc.io/repo/repository/maven-public/") { + maven("https://repo.papermc.io/repository/maven-public/") { name = "PaperMC" } } dependencies { //TODO Allow pulling from Versions.kt - implementation("com.github.johnrengelman", "shadow", "8.1.1") - implementation("io.papermc.paperweight.userdev", "io.papermc.paperweight.userdev.gradle.plugin", "1.5.11") + implementation("com.gradleup.shadow", "shadow-gradle-plugin", "8.3.1") + implementation("io.papermc.paperweight.userdev", "io.papermc.paperweight.userdev.gradle.plugin", "1.7.2") - implementation("org.ow2.asm", "asm", "9.6") - implementation("org.ow2.asm", "asm-tree", "9.6") + implementation("org.ow2.asm", "asm", "9.7") + implementation("org.ow2.asm", "asm-tree", "9.7") implementation("com.dfsek.tectonic", "common", "4.2.1") - implementation("org.yaml", "snakeyaml", "2.2") + implementation("org.yaml", "snakeyaml", "2.3") } \ No newline at end of file diff --git a/buildSrc/src/main/kotlin/CompilationConfig.kt b/buildSrc/src/main/kotlin/CompilationConfig.kt index 952b910918..f0d1e78294 100644 --- a/buildSrc/src/main/kotlin/CompilationConfig.kt +++ b/buildSrc/src/main/kotlin/CompilationConfig.kt @@ -22,8 +22,8 @@ fun Project.configureCompilation() { apply() configure { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 } tasks.withType { diff --git a/buildSrc/src/main/kotlin/DependencyConfig.kt b/buildSrc/src/main/kotlin/DependencyConfig.kt index 58bde514ce..0df8e29f20 100644 --- a/buildSrc/src/main/kotlin/DependencyConfig.kt +++ b/buildSrc/src/main/kotlin/DependencyConfig.kt @@ -36,7 +36,7 @@ fun Project.configureDependencies() { maven("https://repo.codemc.org/repository/maven-public") { name = "CodeMC" } - maven("https://papermc.io/repo/repository/maven-public/") { + maven("https://repo.papermc.io/repository/maven-public/") { name = "PaperMC" } maven("https://files.minecraftforge.net/maven/") { @@ -48,6 +48,9 @@ fun Project.configureDependencies() { maven("https://jitpack.io") { name = "JitPack" } + maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") { + name = "Sonatype Snapshots" + } } dependencies { diff --git a/buildSrc/src/main/kotlin/DistributionConfig.kt b/buildSrc/src/main/kotlin/DistributionConfig.kt index 80e59104e9..0a1c2d060b 100644 --- a/buildSrc/src/main/kotlin/DistributionConfig.kt +++ b/buildSrc/src/main/kotlin/DistributionConfig.kt @@ -21,13 +21,14 @@ import kotlin.io.path.exists fun Project.configureDistribution() { - apply(plugin = "com.github.johnrengelman.shadow") + apply(plugin = "com.gradleup.shadow") val downloadDefaultPacks = tasks.create("downloadDefaultPacks") { group = "terra" doFirst { file("${buildDir}/resources/main/packs/").deleteRecursively() - val defaultPackUrl = URL("https://github.com/PolyhedralDev/TerraOverworldConfig/releases/download/" + Versions.Terra.overworldConfig + "/default.zip") + val defaultPackUrl = + URL("https://github.com/PolyhedralDev/TerraOverworldConfig/releases/download/" + Versions.Terra.overworldConfig + "/default.zip") downloadPack(defaultPackUrl, project) } } diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index a150ac3b26..1e48e716a6 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -8,27 +8,28 @@ object Versions { const val paralithic = "0.7.1" 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 slf4j = "2.0.9" - const val log4j_slf4j_impl = "2.20.0" - + const val slf4j = "2.0.16" + object Internal { - const val shadow = "8.1.1" - const val apacheText = "1.11.0" - const val apacheIO = "2.15.1" - const val guava = "32.1.3-jre" - const val asm = "9.6" - const val snakeYml = "2.2" + const val shadow = "8.3.1" + const val apacheText = "1.12.0" + const val apacheIO = "2.16.1" + const val guava = "33.3.0-jre" + const val asm = "9.7" + const val snakeYml = "2.3" const val jetBrainsAnnotations = "24.1.0" - const val junit = "5.10.1" + const val junit = "5.11.0" } } object Fabric { - const val fabricAPI = "0.91.2+${Mod.minecraft}" + const val fabricAPI = "0.104.0+${Mod.minecraft}" } // // object Quilt { @@ -37,14 +38,14 @@ object Versions { // } 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 yarn = "$minecraft+build.1" - const val fabricLoader = "0.15.1" + const val minecraft = "1.21.1" + const val yarn = "$minecraft+build.3" + const val fabricLoader = "0.16.5" - const val architecuryLoom = "1.4.369" - const val architecturyPlugin = "3.4.151" + const val architecuryLoom = "1.7.413" + const val architecturyPlugin = "3.4.159" } // // object Forge { @@ -53,14 +54,14 @@ object Versions { // } object Bukkit { - const val minecraft = "1.20.4" - const val paperBuild = "$minecraft-R0.1-20231209.173338-2" + const val minecraft = "1.21.1" + const val paperBuild = "$minecraft-R0.1-20240917.151311-80" const val paper = paperBuild const val paperLib = "1.0.8" - const val reflectionRemapper = "0.1.0" + const val reflectionRemapper = "0.1.1" const val paperDevBundle = paperBuild - const val runPaper = "2.2.2" - const val paperWeight = "1.5.11" + const val runPaper = "2.3.1" + const val paperWeight = "1.7.2" } // @@ -72,6 +73,6 @@ object Versions { // object CLI { const val nbt = "6.1" - const val logback = "1.4.14" + const val logback = "1.5.8" } } \ No newline at end of file diff --git a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/Extrusion.java b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/Extrusion.java index 4c4ca972aa..c1d5f5524d 100644 --- a/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/Extrusion.java +++ b/common/addons/biome-provider-extrusion/src/main/java/com/dfsek/terra/addons/biome/extrusion/api/Extrusion.java @@ -1,9 +1,9 @@ package com.dfsek.terra.addons.biome.extrusion.api; -import java.util.Collection; - import com.dfsek.terra.api.world.biome.Biome; +import java.util.Collection; + public interface Extrusion { Biome extrude(Biome original, int x, int y, int z, long seed); diff --git a/common/addons/biome-provider-pipeline-v2/src/main/java/com/dfsek/terra/addons/biome/pipeline/v2/config/BiomePipelineTemplate.java b/common/addons/biome-provider-pipeline-v2/src/main/java/com/dfsek/terra/addons/biome/pipeline/v2/config/BiomePipelineTemplate.java index 937a1b7dfc..75ffb8d65a 100644 --- a/common/addons/biome-provider-pipeline-v2/src/main/java/com/dfsek/terra/addons/biome/pipeline/v2/config/BiomePipelineTemplate.java +++ b/common/addons/biome-provider-pipeline-v2/src/main/java/com/dfsek/terra/addons/biome/pipeline/v2/config/BiomePipelineTemplate.java @@ -29,7 +29,7 @@ public class BiomePipelineTemplate implements ObjectTemplate { @Default @Description(""" The resolution at which to sample biomes. - + Larger values are quadratically faster, but produce lower quality results. For example, a value of 3 would sample every 3 blocks.""") protected @Meta int resolution = 1; diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/BiomePipelineTemplate.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/BiomePipelineTemplate.java index 491f019baf..1566de5245 100644 --- a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/BiomePipelineTemplate.java +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/BiomePipelineTemplate.java @@ -28,7 +28,7 @@ public class BiomePipelineTemplate extends BiomeProviderTemplate { @Description(""" The initial size of biome chunks. This value must be at least 2. This is not the final size of biome chunks. Final chunks will be much larger. - + It is recommended to keep biome chunks' final size in the range of [50, 300] to prevent performance issues. To calculate the size of biome chunks, simply take initial-size and for each expand stage, multiply the running value by 2 diff --git a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/BiomeProviderTemplate.java b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/BiomeProviderTemplate.java index f42fd7c209..93f84e80a4 100644 --- a/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/BiomeProviderTemplate.java +++ b/common/addons/biome-provider-pipeline/src/main/java/com/dfsek/terra/addons/biome/pipeline/config/BiomeProviderTemplate.java @@ -22,7 +22,7 @@ public abstract class BiomeProviderTemplate implements ObjectTemplate { - event.getPack().applyLoader(SlantHolder.CalculationMethod.class, - (type, o, loader, depthTracker) -> SlantHolder.CalculationMethod.valueOf((String) o)); + event.getPack().applyLoader(SlantCalculationMethod.class, + (type, o, loader, depthTracker) -> SlantCalculationMethod.valueOf((String) o)); NoiseChunkGeneratorPackConfigTemplate config = event.loadTemplate(new NoiseChunkGeneratorPackConfigTemplate()); event.getPack().getContext().put(config); @@ -57,7 +58,8 @@ public void initialize() { pack -> new NoiseChunkGenerator3D(pack, platform, config.getElevationBlend(), config.getHorizontalRes(), config.getVerticalRes(), noisePropertiesPropertyKey, - paletteInfoPropertyKey)); + paletteInfoPropertyKey, config.getSlantCalculationMethod(), + config.isSlantPalettesEnabled())); event.getPack() .applyLoader(SlantHolder.Layer.class, SlantLayerTemplate::new); }) diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/NoiseChunkGeneratorPackConfigTemplate.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/NoiseChunkGeneratorPackConfigTemplate.java index c3828bbbf2..ae1f1ca4a5 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/NoiseChunkGeneratorPackConfigTemplate.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/NoiseChunkGeneratorPackConfigTemplate.java @@ -4,7 +4,7 @@ import com.dfsek.tectonic.api.config.template.annotations.Default; 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.properties.Properties; @@ -24,7 +24,11 @@ public class NoiseChunkGeneratorPackConfigTemplate implements ConfigTemplate, Pr @Value("slant.calculation-method") @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() { return elevationBlend; @@ -38,7 +42,11 @@ public int getVerticalRes() { return verticalRes; } - public SlantHolder.CalculationMethod getSlantCalculationMethod() { + public SlantCalculationMethod getSlantCalculationMethod() { return slantCalculationMethod; } + + public boolean isSlantPalettesEnabled() { + return !disableSlantPalettes; + } } diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/palette/BiomePaletteTemplate.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/palette/BiomePaletteTemplate.java index 2d479f1a21..a4ff986e44 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/palette/BiomePaletteTemplate.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/config/palette/BiomePaletteTemplate.java @@ -16,6 +16,7 @@ import java.util.List; import java.util.Map; +import com.dfsek.terra.addons.chunkgenerator.generation.math.SlantCalculationMethod; import com.dfsek.terra.addons.chunkgenerator.palette.BiomePaletteInfo; import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolder; import com.dfsek.terra.addons.chunkgenerator.palette.slant.SlantHolder; @@ -27,7 +28,7 @@ public class BiomePaletteTemplate implements ObjectTemplate { private final Platform platform; - private final SlantHolder.CalculationMethod slantCalculationMethod; + private final SlantCalculationMethod slantCalculationMethod; @Value("slant") @Default @Description("The slant palettes to use in this biome.") @@ -56,7 +57,7 @@ public BlockState get(int layer, double x, double y, double z, long seed) { @Default private @Meta boolean updatePalette = false; - public BiomePaletteTemplate(Platform platform, SlantHolder.CalculationMethod slantCalculationMethod) { + public BiomePaletteTemplate(Platform platform, SlantCalculationMethod slantCalculationMethod) { this.platform = platform; this.slantCalculationMethod = slantCalculationMethod; } diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/NoiseChunkGenerator3D.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/NoiseChunkGenerator3D.java index 08dc93cbee..4f891d12ba 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/NoiseChunkGenerator3D.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/NoiseChunkGenerator3D.java @@ -11,11 +11,12 @@ import org.jetbrains.annotations.NotNull; 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.samplers.Sampler3D; import com.dfsek.terra.addons.chunkgenerator.generation.math.samplers.SamplerProvider; import com.dfsek.terra.addons.chunkgenerator.palette.BiomePaletteInfo; +import com.dfsek.terra.addons.chunkgenerator.palette.slant.SlantHolder; import com.dfsek.terra.api.Platform; import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.config.ConfigPack; @@ -42,16 +43,23 @@ public class NoiseChunkGenerator3D implements ChunkGenerator { private final PropertyKey paletteInfoPropertyKey; private final PropertyKey noisePropertiesKey; + private final SlantCalculationMethod slantCalculationMethod; + + private final boolean useSlantPalettes; + public NoiseChunkGenerator3D(ConfigPack pack, Platform platform, int elevationBlend, int carverHorizontalResolution, int carverVerticalResolution, PropertyKey noisePropertiesKey, - PropertyKey paletteInfoPropertyKey) { + PropertyKey paletteInfoPropertyKey, + SlantCalculationMethod slantCalculationMethod, boolean useSlantPalettes) { this.platform = platform; this.air = platform.getWorldHandle().air(); this.carverHorizontalResolution = carverHorizontalResolution; this.carverVerticalResolution = carverVerticalResolution; this.paletteInfoPropertyKey = paletteInfoPropertyKey; this.noisePropertiesKey = noisePropertiesKey; + this.slantCalculationMethod = slantCalculationMethod; + this.useSlantPalettes = useSlantPalettes; int maxBlend = pack .getBiomeProvider() .stream() @@ -63,6 +71,17 @@ public NoiseChunkGenerator3D(ConfigPack pack, Platform platform, int elevationBl this.samplerCache = new SamplerProvider(platform, elevationBlend, noisePropertiesKey, maxBlend); } + private Palette paletteAt(int x, int y, int z, Sampler3D sampler, BiomePaletteInfo paletteInfo, int depth) { + SlantHolder slantHolder = paletteInfo.slantHolder(); + if(useSlantPalettes && slantHolder.isAboveDepth(depth)) { + double slant = slantCalculationMethod.slant(sampler, x, y, z); + if(slantHolder.isInSlantThreshold(slant)) { + return slantHolder.getPalette(slant).getPalette(y); + } + } + return paletteInfo.paletteHolder().getPalette(y); + } + @Override @SuppressWarnings("try") public void generateChunkData(@NotNull ProtoChunk chunk, @NotNull WorldProperties world, @@ -103,8 +122,7 @@ public void generateChunkData(@NotNull ProtoChunk chunk, @NotNull WorldPropertie if(sampler.sample(x, y, z) > 0) { if(carver.sample(x, y, z) <= 0) { - data = PaletteUtil - .getPalette(x, y, z, sampler, paletteInfo, paletteLevel) + data = paletteAt(x, y, z, sampler, paletteInfo, paletteLevel) .get(paletteLevel, cx, y, cz, seed); chunk.setBlock(x, y, z, data); paletteLevel++; @@ -135,7 +153,7 @@ public BlockState getBlock(WorldProperties world, int x, int y, int z, BiomeProv int fdX = Math.floorMod(x, 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); if(noise > 0) { int level = 0; @@ -157,11 +175,8 @@ public Palette getPalette(int x, int y, int z, WorldProperties world, BiomeProvi public double getSlant(int x, int y, int z, WorldProperties world, BiomeProvider biomeProvider) { int fdX = Math.floorMod(x, 16); int fdZ = Math.floorMod(z, 16); - return biomeProvider.getBiome(x, y, z, world.getSeed()) - .getContext() - .get(paletteInfoPropertyKey) - .slantHolder() - .calculateSlant(samplerCache.get(x, z, world, biomeProvider), fdX, y, fdZ); + Sampler3D sampler = samplerCache.get(x, z, world, biomeProvider); + return slantCalculationMethod.slant(sampler, fdX, y, fdZ); } public SamplerProvider samplerProvider() { diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/PaletteUtil.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/PaletteUtil.java deleted file mode 100644 index e7c20784cd..0000000000 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/PaletteUtil.java +++ /dev/null @@ -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); - } -} \ No newline at end of file diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/SlantCalculationMethod.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/SlantCalculationMethod.java new file mode 100644 index 0000000000..1c03a038ad --- /dev/null +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/generation/math/SlantCalculationMethod.java @@ -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(); +} diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/palette/slant/MultipleSlantHolder.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/palette/slant/MultipleSlantHolder.java index 895c026980..08f1d16fea 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/palette/slant/MultipleSlantHolder.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/palette/slant/MultipleSlantHolder.java @@ -14,6 +14,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import com.dfsek.terra.addons.chunkgenerator.generation.math.SlantCalculationMethod; import com.dfsek.terra.addons.chunkgenerator.palette.PaletteHolder; @@ -21,7 +22,7 @@ public class MultipleSlantHolder extends SlantHolderImpl { private final NavigableMap layers; private final double slantThreshold; - MultipleSlantHolder(List slant, int slantDepth, CalculationMethod calculationMethod) { + MultipleSlantHolder(List slant, int slantDepth, SlantCalculationMethod calculationMethod) { super(slantDepth, calculationMethod); NavigableMap layers = new TreeMap<>( slant.stream().collect(Collectors.toMap(SlantHolder.Layer::threshold, SlantHolder.Layer::palette))); diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/palette/slant/SingleSlantHolder.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/palette/slant/SingleSlantHolder.java index 12f29ef18d..3f8ab5408a 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/palette/slant/SingleSlantHolder.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/palette/slant/SingleSlantHolder.java @@ -1,5 +1,6 @@ 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; @@ -7,7 +8,7 @@ final class SingleSlantHolder extends SlantHolderImpl { 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); this.layer = layer; } diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/palette/slant/SlantHolder.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/palette/slant/SlantHolder.java index 359913d418..d4c2855cde 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/palette/slant/SlantHolder.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/palette/slant/SlantHolder.java @@ -2,19 +2,13 @@ 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.api.util.vector.Vector3; public interface SlantHolder { SlantHolder EMPTY = new SlantHolder() { - @Override - public double calculateSlant(Sampler3D sampler, double x, double y, double z) { - throw new UnsupportedOperationException("Empty holder should not calculate slant"); - } - @Override public boolean isAboveDepth(int depth) { return false; @@ -31,7 +25,7 @@ public PaletteHolder getPalette(double slant) { } }; - static SlantHolder of(List layers, int slantDepth, CalculationMethod calculationMethod) { + static SlantHolder of(List layers, int slantDepth, SlantCalculationMethod calculationMethod) { if(layers.isEmpty()) { return EMPTY; } else if(layers.size() == 1) { @@ -40,8 +34,6 @@ static SlantHolder of(List layers, int slantDepth, Calculatio return new MultipleSlantHolder(layers, slantDepth, calculationMethod); } - double calculateSlant(Sampler3D sampler, double x, double y, double z); - boolean isAboveDepth(int depth); boolean isInSlantThreshold(double slant); @@ -49,71 +41,6 @@ static SlantHolder of(List layers, int slantDepth, Calculatio 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) { } } diff --git a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/palette/slant/SlantHolderImpl.java b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/palette/slant/SlantHolderImpl.java index 13fc68ef13..bef21cdba9 100644 --- a/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/palette/slant/SlantHolderImpl.java +++ b/common/addons/chunk-generator-noise-3d/src/main/java/com/dfsek/terra/addons/chunkgenerator/palette/slant/SlantHolderImpl.java @@ -1,26 +1,19 @@ 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 { protected final boolean floorToThreshold; - private final SlantHolder.CalculationMethod calculationMethod; private final int slantDepth; - protected SlantHolderImpl(int slantDepth, CalculationMethod calculationMethod) { + protected SlantHolderImpl(int slantDepth, SlantCalculationMethod calculationMethod) { this.floorToThreshold = calculationMethod.floorToThreshold(); - this.calculationMethod = calculationMethod; this.slantDepth = slantDepth; } protected abstract double getSlantThreshold(); - @Override - public final double calculateSlant(Sampler3D sampler, double x, double y, double z) { - return calculationMethod.slant(sampler, x, y, z); - } - @Override public final boolean isAboveDepth(int depth) { return depth <= slantDepth; diff --git a/common/addons/command-addons/src/main/java/com/dfsek/terra/addons/commands/addons/AddonsCommandAddon.java b/common/addons/command-addons/src/main/java/com/dfsek/terra/addons/commands/addons/AddonsCommandAddon.java index 58a22ef7a1..a1c0cfb748 100644 --- a/common/addons/command-addons/src/main/java/com/dfsek/terra/addons/commands/addons/AddonsCommandAddon.java +++ b/common/addons/command-addons/src/main/java/com/dfsek/terra/addons/commands/addons/AddonsCommandAddon.java @@ -1,7 +1,7 @@ package com.dfsek.terra.addons.commands.addons; -import cloud.commandframework.ArgumentDescription; -import cloud.commandframework.CommandManager; +import org.incendo.cloud.CommandManager; +import org.incendo.cloud.description.Description; import com.dfsek.terra.addons.manifest.api.AddonInitializer; import com.dfsek.terra.api.Platform; @@ -30,7 +30,7 @@ public void initialize() { CommandManager manager = event.getCommandManager(); manager.command( - manager.commandBuilder("addons", ArgumentDescription.of("List installed Terra addons")) + manager.commandBuilder("addons", Description.of("List installed Terra addons")) .permission("terra.addons") .handler(context -> { StringBuilder addons = new StringBuilder("Installed addons:\n"); @@ -41,7 +41,7 @@ public void initialize() { .append('@') .append(addon.getVersion().getFormatted()) .append('\n')); - context.getSender().sendMessage(addons.toString()); + context.sender().sendMessage(addons.toString()); }) ) .command( @@ -61,7 +61,7 @@ public void initialize() { .append('@') .append(versions.getFormatted()) .append('\n')); - context.getSender().sendMessage(addonInfo.toString()); + context.sender().sendMessage(addonInfo.toString()); }) ); }); diff --git a/common/addons/command-packs/src/main/java/com/dfsek/terra/addons/commands/packs/PacksCommandAddon.java b/common/addons/command-packs/src/main/java/com/dfsek/terra/addons/commands/packs/PacksCommandAddon.java index 1d99af328a..6b840ef1f7 100644 --- a/common/addons/command-packs/src/main/java/com/dfsek/terra/addons/commands/packs/PacksCommandAddon.java +++ b/common/addons/command-packs/src/main/java/com/dfsek/terra/addons/commands/packs/PacksCommandAddon.java @@ -1,7 +1,7 @@ package com.dfsek.terra.addons.commands.packs; -import cloud.commandframework.ArgumentDescription; -import cloud.commandframework.CommandManager; +import org.incendo.cloud.CommandManager; +import org.incendo.cloud.description.Description; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,7 +35,7 @@ public void initialize() { CommandManager manager = event.getCommandManager(); manager.command( - manager.commandBuilder("packs", ArgumentDescription.of("List installed config packs")) + manager.commandBuilder("packs", Description.of("List installed config packs")) .permission("terra.packs") .handler(context -> { StringBuilder packs = new StringBuilder("Installed packs:\n"); @@ -43,12 +43,12 @@ public void initialize() { .append(pack.getID()) .append('@') .append(pack.getVersion().getFormatted())); - context.getSender().sendMessage(packs.toString()); + context.sender().sendMessage(packs.toString()); }) ) .command( 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") .argument(RegistryArgument.of("pack", platform.getConfigRegistry())) .handler(context -> { @@ -65,21 +65,21 @@ public void initialize() { .append('@') .append(versions.getFormatted()) .append('\n')); - context.getSender().sendMessage(packInfo.toString()); + context.sender().sendMessage(packInfo.toString()); })) .command( manager.commandBuilder("packs") - .literal("reload", ArgumentDescription.of("Reload config packs")) + .literal("reload", Description.of("Reload config packs")) .permission("terra.packs.reload") .handler(context -> { - context.getSender().sendMessage("Reloading Terra..."); + context.sender().sendMessage("Reloading Terra..."); logger.info("Reloading Terra..."); if(platform.reload()) { logger.info("Terra reloaded successfully."); - context.getSender().sendMessage("Terra reloaded successfully."); + context.sender().sendMessage("Terra reloaded successfully."); } else { logger.error("Terra failed to reload."); - context.getSender().sendMessage( + context.sender().sendMessage( "Terra failed to reload. See logs for more information."); } })); diff --git a/common/addons/command-profiler/src/main/java/com/dfsek/terra/addons/commands/profiler/ProfilerCommandAddon.java b/common/addons/command-profiler/src/main/java/com/dfsek/terra/addons/commands/profiler/ProfilerCommandAddon.java index 2376c919bb..a1559c8c51 100644 --- a/common/addons/command-profiler/src/main/java/com/dfsek/terra/addons/commands/profiler/ProfilerCommandAddon.java +++ b/common/addons/command-profiler/src/main/java/com/dfsek/terra/addons/commands/profiler/ProfilerCommandAddon.java @@ -1,7 +1,7 @@ package com.dfsek.terra.addons.commands.profiler; -import cloud.commandframework.ArgumentDescription; -import cloud.commandframework.CommandManager; +import org.incendo.cloud.CommandManager; +import org.incendo.cloud.description.Description; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -33,24 +33,24 @@ public void initialize() { CommandManager manager = event.getCommandManager(); manager .command( - manager.commandBuilder("profiler", ArgumentDescription.of("Access the profiler")) - .literal("start", ArgumentDescription.of("Start profiling"), "st") + manager.commandBuilder("profiler", Description.of("Access the profiler")) + .literal("start", Description.of("Start profiling"), "st") .permission("terra.profiler.start") .handler(context -> { platform.getProfiler().start(); - context.getSender().sendMessage("Profiling started."); + context.sender().sendMessage("Profiling started."); })) .command( - manager.commandBuilder("profiler", ArgumentDescription.of("Access the profiler")) - .literal("stop", ArgumentDescription.of("Stop profiling"), "s") + manager.commandBuilder("profiler", Description.of("Access the profiler")) + .literal("stop", Description.of("Stop profiling"), "s") .permission("terra.profiler.stop") .handler(context -> { platform.getProfiler().stop(); - context.getSender().sendMessage("Profiling stopped."); + context.sender().sendMessage("Profiling stopped."); })) .command( - manager.commandBuilder("profiler", ArgumentDescription.of("Access the profiler")) - .literal("query", ArgumentDescription.of("Query profiler results"), "q") + manager.commandBuilder("profiler", Description.of("Access the profiler")) + .literal("query", Description.of("Query profiler results"), "q") .permission("terra.profiler.query") .handler(context -> { StringBuilder data = new StringBuilder("Terra Profiler data: \n"); @@ -59,15 +59,15 @@ public void initialize() { .append(timings.toString()) .append('\n')); logger.info(data.toString()); - context.getSender().sendMessage("Profiling data dumped to console."); + context.sender().sendMessage("Profiling data dumped to console."); })) .command( - manager.commandBuilder("profiler", ArgumentDescription.of("Access the profiler")) - .literal("reset", ArgumentDescription.of("Reset the profiler"), "r") + manager.commandBuilder("profiler", Description.of("Access the profiler")) + .literal("reset", Description.of("Reset the profiler"), "r") .permission("terra.profiler.reset") .handler(context -> { platform.getProfiler().reset(); - context.getSender().sendMessage("Profiler reset."); + context.sender().sendMessage("Profiler reset."); })); }); } diff --git a/common/addons/command-structures/src/main/java/com/dfsek/terra/addons/commands/structure/StructureCommandAddon.java b/common/addons/command-structures/src/main/java/com/dfsek/terra/addons/commands/structure/StructureCommandAddon.java index 438546137c..e3e9f0c7bc 100644 --- a/common/addons/command-structures/src/main/java/com/dfsek/terra/addons/commands/structure/StructureCommandAddon.java +++ b/common/addons/command-structures/src/main/java/com/dfsek/terra/addons/commands/structure/StructureCommandAddon.java @@ -1,10 +1,11 @@ package com.dfsek.terra.addons.commands.structure; -import cloud.commandframework.ArgumentDescription; -import cloud.commandframework.CommandManager; -import cloud.commandframework.arguments.standard.EnumArgument; -import cloud.commandframework.arguments.standard.LongArgument; -import cloud.commandframework.context.CommandContext; +import org.incendo.cloud.CommandManager; +import org.incendo.cloud.component.DefaultValue; +import org.incendo.cloud.context.CommandContext; +import org.incendo.cloud.description.Description; +import org.incendo.cloud.parser.standard.EnumParser; +import org.incendo.cloud.parser.standard.LongParser; import java.util.Random; @@ -31,7 +32,7 @@ public class StructureCommandAddon implements AddonInitializer { private BaseAddon addon; private static Registry getStructureRegistry(CommandContext sender) { - return sender.getSender().getEntity().orElseThrow().world().getPack().getRegistry(Structure.class); + return sender.sender().getEntity().orElseThrow().world().getPack().getRegistry(Structure.class); } @Override @@ -43,16 +44,16 @@ public void initialize() { CommandManager manager = event.getCommandManager(); manager.command( - manager.commandBuilder("structures", ArgumentDescription.of("Manage or generate structures")) + manager.commandBuilder("structures", Description.of("Manage or generate structures")) .literal("generate") - .argument(RegistryArgument.builder("structure", + .optional(RegistryArgument.builder("structure", StructureCommandAddon::getStructureRegistry, TypeKey.of(Structure.class))) - .argument(LongArgument.optional("seed", 0)) - .argument(EnumArgument.optional(Rotation.class, "rotation", Rotation.NONE)) + .optional("seed", LongParser.longParser(), DefaultValue.constant(0L)) + .optional("rotation", EnumParser.enumParser(Rotation.class), DefaultValue.constant(Rotation.NONE)) .handler(context -> { Structure structure = context.get("structure"); - Entity sender = context.getSender().getEntity().orElseThrow(); + Entity sender = context.sender().getEntity().orElseThrow(); structure.generate( sender.position().toInt(), sender.world(), diff --git a/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/holder/PaletteHolderBuilder.java b/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/holder/PaletteHolderBuilder.java index e840f98178..a96cbcc484 100644 --- a/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/holder/PaletteHolderBuilder.java +++ b/common/addons/config-biome/src/main/java/com/dfsek/terra/addons/biome/holder/PaletteHolderBuilder.java @@ -7,11 +7,11 @@ package com.dfsek.terra.addons.biome.holder; +import com.dfsek.terra.api.world.chunk.generation.util.Palette; + import java.util.Map; import java.util.TreeMap; -import com.dfsek.terra.api.world.chunk.generation.util.Palette; - public class PaletteHolderBuilder { private final TreeMap paletteMap = new TreeMap<>(); diff --git a/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/distributors/PointSetDistributor.java b/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/distributors/PointSetDistributor.java index f85d41e5f7..4285af4869 100644 --- a/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/distributors/PointSetDistributor.java +++ b/common/addons/config-distributors/src/main/java/com/dfsek/terra/addons/feature/distributor/distributors/PointSetDistributor.java @@ -7,11 +7,11 @@ package com.dfsek.terra.addons.feature.distributor.distributors; -import java.util.Set; - import com.dfsek.terra.addons.feature.distributor.util.Point; import com.dfsek.terra.api.structure.feature.Distributor; +import java.util.Set; + public class PointSetDistributor implements Distributor { private final Set points; diff --git a/common/addons/config-noise-function/build.gradle.kts b/common/addons/config-noise-function/build.gradle.kts index af2284b48f..83d927a017 100644 --- a/common/addons/config-noise-function/build.gradle.kts +++ b/common/addons/config-noise-function/build.gradle.kts @@ -1,4 +1,4 @@ -version = version("1.1.0") +version = version("1.2.0") dependencies { compileOnlyApi(project(":common:addons:manifest-addon-loader")) diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/NoiseAddon.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/NoiseAddon.java index ca3aa1a448..3fd52950c0 100644 --- a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/NoiseAddon.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/NoiseAddon.java @@ -17,6 +17,7 @@ import com.dfsek.terra.addons.noise.config.CubicSplinePointTemplate; import com.dfsek.terra.addons.noise.config.DimensionApplicableNoiseSampler; import com.dfsek.terra.addons.noise.config.templates.BinaryArithmeticTemplate; +import com.dfsek.terra.addons.noise.config.templates.DerivativeNoiseSamplerTemplate; import com.dfsek.terra.addons.noise.config.templates.DomainWarpTemplate; import com.dfsek.terra.addons.noise.config.templates.FunctionTemplate; import com.dfsek.terra.addons.noise.config.templates.ImageSamplerTemplate; @@ -28,6 +29,7 @@ import com.dfsek.terra.addons.noise.config.templates.noise.DistanceSamplerTemplate; import com.dfsek.terra.addons.noise.config.templates.noise.ExpressionFunctionTemplate; import com.dfsek.terra.addons.noise.config.templates.noise.GaborNoiseTemplate; +import com.dfsek.terra.addons.noise.config.templates.noise.PseudoErosionTemplate; import com.dfsek.terra.addons.noise.config.templates.noise.SimpleNoiseTemplate; import com.dfsek.terra.addons.noise.config.templates.noise.fractal.BrownianMotionTemplate; import com.dfsek.terra.addons.noise.config.templates.noise.fractal.PingPongTemplate; @@ -63,6 +65,7 @@ import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent; import com.dfsek.terra.api.event.functional.FunctionalEventHandler; import com.dfsek.terra.api.inject.annotations.Inject; +import com.dfsek.terra.api.noise.DerivativeNoiseSampler; import com.dfsek.terra.api.noise.NoiseSampler; import com.dfsek.terra.api.registry.CheckedRegistry; import com.dfsek.terra.api.util.reflection.TypeKey; @@ -94,7 +97,8 @@ public void initialize() { (type, o, loader, depthTracker) -> DistanceSampler.DistanceFunction.valueOf((String) o)) .applyLoader(DimensionApplicableNoiseSampler.class, DimensionApplicableNoiseSampler::new) .applyLoader(FunctionTemplate.class, FunctionTemplate::new) - .applyLoader(CubicSpline.Point.class, CubicSplinePointTemplate::new); + .applyLoader(CubicSpline.Point.class, CubicSplinePointTemplate::new) + .applyLoader(DerivativeNoiseSampler.class, DerivativeNoiseSamplerTemplate::new); noiseRegistry.register(addon.key("LINEAR"), LinearNormalizerTemplate::new); noiseRegistry.register(addon.key("NORMAL"), NormalNormalizerTemplate::new); @@ -117,7 +121,7 @@ public void initialize() { noiseRegistry.register(addon.key("PERLIN"), () -> new SimpleNoiseTemplate(PerlinSampler::new)); noiseRegistry.register(addon.key("SIMPLEX"), () -> new SimpleNoiseTemplate(SimplexSampler::new)); noiseRegistry.register(addon.key("GABOR"), GaborNoiseTemplate::new); - + noiseRegistry.register(addon.key("PSEUDOEROSION"), PseudoErosionTemplate::new); noiseRegistry.register(addon.key("VALUE"), () -> new SimpleNoiseTemplate(ValueSampler::new)); noiseRegistry.register(addon.key("VALUE_CUBIC"), () -> new SimpleNoiseTemplate(ValueCubicSampler::new)); diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/NoiseConfigPackTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/NoiseConfigPackTemplate.java index c41af17633..d6ac6c00c5 100644 --- a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/NoiseConfigPackTemplate.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/NoiseConfigPackTemplate.java @@ -11,14 +11,14 @@ import com.dfsek.tectonic.api.config.template.annotations.Default; import com.dfsek.tectonic.api.config.template.annotations.Value; -import java.util.LinkedHashMap; -import java.util.Map; - import com.dfsek.terra.addons.noise.config.DimensionApplicableNoiseSampler; import com.dfsek.terra.addons.noise.config.templates.FunctionTemplate; import com.dfsek.terra.api.config.meta.Meta; import com.dfsek.terra.api.properties.Properties; +import java.util.LinkedHashMap; +import java.util.Map; + @SuppressWarnings("FieldMayBeFinal") public class NoiseConfigPackTemplate implements ConfigTemplate, Properties { diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/DerivativeNoiseSamplerTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/DerivativeNoiseSamplerTemplate.java new file mode 100644 index 0000000000..9e66b23ead --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/DerivativeNoiseSamplerTemplate.java @@ -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 { + + @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; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/DerivativeNoiseTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/DerivativeNoiseTemplate.java new file mode 100644 index 0000000000..c9100e3444 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/DerivativeNoiseTemplate.java @@ -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 extends NoiseTemplate { + +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/PseudoErosionTemplate.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/PseudoErosionTemplate.java new file mode 100644 index 0000000000..cda91ec326 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/config/templates/noise/PseudoErosionTemplate.java @@ -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 { + @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; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/FunctionUtil.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/FunctionUtil.java index 5dbc740ecf..d47693cde8 100644 --- a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/FunctionUtil.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/FunctionUtil.java @@ -11,6 +11,8 @@ import com.dfsek.terra.addons.noise.paralithic.defined.UserDefinedFunction; import com.dfsek.terra.addons.noise.paralithic.noise.NoiseFunction2; import com.dfsek.terra.addons.noise.paralithic.noise.NoiseFunction3; +import com.dfsek.terra.addons.noise.paralithic.noise.SaltedNoiseFunction2; +import com.dfsek.terra.addons.noise.paralithic.noise.SaltedNoiseFunction3; public class FunctionUtil { @@ -23,10 +25,15 @@ public static Map convertFunctionsAndSamplers(Map entry : functions.entrySet()) { functionMap.put(entry.getKey(), UserDefinedFunction.newInstance(entry.getValue())); } - samplers.forEach((id, sampler) -> functionMap.put(id, - sampler.getDimensions() == 2 ? - new NoiseFunction2(sampler.getSampler()) : - new NoiseFunction3(sampler.getSampler()))); + samplers.forEach((id, sampler) -> { + if(sampler.getDimensions() == 2) { + functionMap.put(id, new NoiseFunction2(sampler.getSampler())); + functionMap.put(id + "Salted", new SaltedNoiseFunction2(sampler.getSampler())); + } else { + functionMap.put(id, new NoiseFunction3(sampler.getSampler())); + functionMap.put(id + "Salted", new SaltedNoiseFunction3(sampler.getSampler())); + } + }); return functionMap; } } diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/noise/SaltedNoiseFunction2.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/noise/SaltedNoiseFunction2.java new file mode 100644 index 0000000000..41ddd12479 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/noise/SaltedNoiseFunction2.java @@ -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; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/noise/SaltedNoiseFunction3.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/noise/SaltedNoiseFunction3.java new file mode 100644 index 0000000000..d4549127cc --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/paralithic/noise/SaltedNoiseFunction3.java @@ -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; + } +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/DerivativeNoiseFunction.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/DerivativeNoiseFunction.java new file mode 100644 index 0000000000..0d654eb646 --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/DerivativeNoiseFunction.java @@ -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); +} diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/PseudoErosionSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/PseudoErosionSampler.java new file mode 100644 index 0000000000..ecb566ca7b --- /dev/null +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/PseudoErosionSampler.java @@ -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); + } +} \ No newline at end of file diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/OpenSimplex2SSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/OpenSimplex2SSampler.java index e3488a6769..86adcee3bb 100644 --- a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/OpenSimplex2SSampler.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/OpenSimplex2SSampler.java @@ -276,4 +276,424 @@ public double getNoiseRaw(long sl, double x, double y, double z) { 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; + } } diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/OpenSimplex2Sampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/OpenSimplex2Sampler.java index e4da85a5bb..e86ec2234a 100644 --- a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/OpenSimplex2Sampler.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/OpenSimplex2Sampler.java @@ -37,41 +37,37 @@ public double getNoiseRaw(long sl, double x, double y) { i *= PRIME_X; j *= PRIME_Y; - double n0, n1, n2; + double value = 0; double a = 0.5 - x0 * x0 - y0 * y0; - if(a <= 0) n0 = 0; - else { - n0 = (a * a) * (a * a) * gradCoord(seed, i, j, x0, y0); + if(a > 0) { + value = (a * a) * (a * a) * gradCoord(seed, i, j, x0, y0); } double c = 2 * (1 - 2 * G2) * (1 / G2 - 2) * t + ((-2 * (1 - 2 * G2) * (1 - 2 * G2)) + a); - if(c <= 0) n2 = 0; - else { + if(c > 0) { double x2 = x0 + (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) { double x1 = x0 + G2; double y1 = y0 + (G2 - 1); double b = 0.5 - x1 * x1 - y1 * y1; - if(b <= 0) n1 = 0; - else { - n1 = (b * b) * (b * b) * gradCoord(seed, i, j + PRIME_Y, x1, y1); + if(b > 0) { + value += (b * b) * (b * b) * gradCoord(seed, i, j + PRIME_Y, x1, y1); } } else { double x1 = x0 + (G2 - 1); double y1 = y0 + G2; double b = 0.5 - x1 * x1 - y1 * y1; - if(b <= 0) n1 = 0; - else { - n1 = (b * b) * (b * b) * gradCoord(seed, i + PRIME_X, j, x1, y1); + if(b > 0) { + value += (b * b) * (b * b) * gradCoord(seed, i + PRIME_X, j, x1, y1); } } - return (n0 + n1 + n2) * 99.83685446303647f; + return value * 99.83685446303647f; } @Override @@ -157,4 +153,208 @@ public double getNoiseRaw(long sl, double x, double y, double z) { 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; + } } diff --git a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/SimplexStyleSampler.java b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/SimplexStyleSampler.java index eda599a347..f9c3f65a7a 100644 --- a/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/SimplexStyleSampler.java +++ b/common/addons/config-noise-function/src/main/java/com/dfsek/terra/addons/noise/samplers/noise/simplex/SimplexStyleSampler.java @@ -7,13 +7,13 @@ 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. */ -public abstract class SimplexStyleSampler extends NoiseFunction { +public abstract class SimplexStyleSampler extends DerivativeNoiseFunction { protected static final double[] GRADIENTS_2_D = { 0.130526192220052d, 0.99144486137381d, 0.38268343236509d, 0.923879532511287d, 0.608761429008721d, 0.793353340291235d, 0.793353340291235d, 0.608761429008721d, 0.923879532511287d, 0.38268343236509d, 0.99144486137381d, 0.130526192220051d, @@ -79,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 }; - 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); hash ^= hash >> 15; hash &= 127 << 1; - double xg = GRADIENTS_2_D[hash]; - double yg = GRADIENTS_2_D[hash | 1]; + return hash; + } + + protected static double gradCoord(int seed, int xPrimed, int yPrimed, double xd, double yd) { + int index = gradCoordIndex(seed, xPrimed, yPrimed); + + double xg = GRADIENTS_2_D[index]; + double yg = GRADIENTS_2_D[index | 1]; 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); hash ^= hash >> 15; hash &= 63 << 2; - double xg = GRADIENTS_3D[hash]; - double yg = GRADIENTS_3D[hash | 1]; - double zg = GRADIENTS_3D[hash | 2]; + return hash; + } + + protected static double gradCoord(int seed, int xPrimed, int yPrimed, int zPrimed, double xd, double yd, double zd) { + int index = gradCoordIndex(seed, xPrimed, yPrimed, zPrimed); + + double xg = GRADIENTS_3D[index]; + double yg = GRADIENTS_3D[index | 1]; + double zg = GRADIENTS_3D[index | 2]; 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; + } } diff --git a/common/addons/generation-stage-feature/src/main/java/com/dfsek/terra/addons/generation/feature/FeatureGenerationAddon.java b/common/addons/generation-stage-feature/src/main/java/com/dfsek/terra/addons/generation/feature/FeatureGenerationAddon.java index 41009ed0b5..f1ca7d9456 100644 --- a/common/addons/generation-stage-feature/src/main/java/com/dfsek/terra/addons/generation/feature/FeatureGenerationAddon.java +++ b/common/addons/generation-stage-feature/src/main/java/com/dfsek/terra/addons/generation/feature/FeatureGenerationAddon.java @@ -11,13 +11,6 @@ import com.dfsek.tectonic.api.config.template.dynamic.DynamicValue; import com.dfsek.tectonic.api.config.template.object.ObjectTemplate; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Supplier; - import com.dfsek.terra.addons.generation.feature.config.BiomeFeatures; import com.dfsek.terra.addons.generation.feature.config.FeatureStageTemplate; import com.dfsek.terra.addons.manifest.api.AddonInitializer; @@ -35,6 +28,9 @@ import com.dfsek.terra.api.world.biome.Biome; import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage; +import java.util.*; +import java.util.function.Supplier; + public class FeatureGenerationAddon implements AddonInitializer { public static final TypeKey>> STAGE_TYPE_KEY = new TypeKey<>() { diff --git a/common/addons/generation-stage-feature/src/main/java/com/dfsek/terra/addons/generation/feature/FeatureGenerationStage.java b/common/addons/generation-stage-feature/src/main/java/com/dfsek/terra/addons/generation/feature/FeatureGenerationStage.java index 6baf88b7a0..132889d237 100644 --- a/common/addons/generation-stage-feature/src/main/java/com/dfsek/terra/addons/generation/feature/FeatureGenerationStage.java +++ b/common/addons/generation-stage-feature/src/main/java/com/dfsek/terra/addons/generation/feature/FeatureGenerationStage.java @@ -7,11 +7,9 @@ package com.dfsek.terra.addons.generation.feature; -import java.util.Collections; -import java.util.Random; - import com.dfsek.terra.addons.generation.feature.config.BiomeFeatures; import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.noise.NoiseSampler; import com.dfsek.terra.api.properties.PropertyKey; import com.dfsek.terra.api.registry.key.StringIdentifiable; import com.dfsek.terra.api.util.Rotation; @@ -21,6 +19,9 @@ import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage; import com.dfsek.terra.api.world.chunk.generation.util.Column; +import java.util.Collections; +import java.util.Random; + public class FeatureGenerationStage implements GenerationStage, StringIdentifiable { private final Platform platform; @@ -31,13 +32,20 @@ public class FeatureGenerationStage implements GenerationStage, StringIdentifiab private final int resolution; private final PropertyKey biomeFeaturesKey; + private final NoiseSampler blendSampler; + private final boolean doBlending; + private final double blendAmplitude; - public FeatureGenerationStage(Platform platform, String id, int resolution, PropertyKey biomeFeaturesKey) { + public FeatureGenerationStage(Platform platform, String id, int resolution, PropertyKey biomeFeaturesKey, + NoiseSampler blendSampler, double blendAmplitude) { this.platform = platform; this.id = id; this.profile = "feature_stage:" + id; this.resolution = resolution; this.biomeFeaturesKey = biomeFeaturesKey; + this.blendSampler = blendSampler; + this.doBlending = blendAmplitude != 0d; + this.blendAmplitude = blendAmplitude; } @Override @@ -52,7 +60,10 @@ public void populate(ProtoWorld world) { int tx = cx + chunkX; int tz = cz + chunkZ; 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) -> { for(int subChunkX = 0; subChunkX < resolution; subChunkX++) { for(int subChunkZ = 0; subChunkZ < resolution; subChunkZ++) { diff --git a/common/addons/generation-stage-feature/src/main/java/com/dfsek/terra/addons/generation/feature/config/FeatureStageTemplate.java b/common/addons/generation-stage-feature/src/main/java/com/dfsek/terra/addons/generation/feature/config/FeatureStageTemplate.java index ffc077f1a8..d0fae0e1f2 100644 --- a/common/addons/generation-stage-feature/src/main/java/com/dfsek/terra/addons/generation/feature/config/FeatureStageTemplate.java +++ b/common/addons/generation-stage-feature/src/main/java/com/dfsek/terra/addons/generation/feature/config/FeatureStageTemplate.java @@ -8,6 +8,7 @@ import com.dfsek.terra.addons.generation.feature.FeatureGenerationStage; import com.dfsek.terra.api.Platform; +import com.dfsek.terra.api.noise.NoiseSampler; import com.dfsek.terra.api.properties.PropertyKey; import com.dfsek.terra.api.world.chunk.generation.stage.GenerationStage; @@ -22,6 +23,24 @@ public class FeatureStageTemplate implements ObjectTemplate, Va @Default private int resolution = 4; + @Value("blend.sampler") + @Default + private NoiseSampler blendSampler = new NoiseSampler() { + @Override + public double noise(long seed, double x, double y) { + return 0; + } + + @Override + public double noise(long seed, double x, double y, double z) { + return 0; + } + }; + + @Value("blend.amplitude") + @Default + private double blendAmplitude = 0d; + public FeatureStageTemplate(Platform platform, PropertyKey biomeFeaturesKey) { this.platform = platform; this.biomeFeaturesKey = biomeFeaturesKey; @@ -30,7 +49,7 @@ public FeatureStageTemplate(Platform platform, PropertyKey biomeF @Override public FeatureGenerationStage get() { - return new FeatureGenerationStage(platform, id, resolution, biomeFeaturesKey); + return new FeatureGenerationStage(platform, id, resolution, biomeFeaturesKey, blendSampler, blendAmplitude); } @Override diff --git a/common/addons/structure-mutator/src/main/java/com/dfsek/terra/addons/structure/mutator/MutatedStructure.java b/common/addons/structure-mutator/src/main/java/com/dfsek/terra/addons/structure/mutator/MutatedStructure.java index 30b2d59844..5b18dd0639 100644 --- a/common/addons/structure-mutator/src/main/java/com/dfsek/terra/addons/structure/mutator/MutatedStructure.java +++ b/common/addons/structure-mutator/src/main/java/com/dfsek/terra/addons/structure/mutator/MutatedStructure.java @@ -1,7 +1,5 @@ package com.dfsek.terra.addons.structure.mutator; -import java.util.Random; - import com.dfsek.terra.api.registry.key.Keyed; import com.dfsek.terra.api.registry.key.RegistryKey; import com.dfsek.terra.api.structure.Structure; @@ -11,6 +9,8 @@ import com.dfsek.terra.api.world.util.ReadInterceptor; import com.dfsek.terra.api.world.util.WriteInterceptor; +import java.util.Random; + public class MutatedStructure implements Structure, Keyed { private final RegistryKey key; diff --git a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/CheckBlockFunctionBuilder.java b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/CheckBlockFunctionBuilder.java index 588b99f53f..cfef3f5728 100644 --- a/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/CheckBlockFunctionBuilder.java +++ b/common/addons/structure-terrascript-loader/src/main/java/com/dfsek/terra/addons/terrascript/script/builders/CheckBlockFunctionBuilder.java @@ -7,13 +7,13 @@ package com.dfsek.terra.addons.terrascript.script.builders; -import java.util.List; - import com.dfsek.terra.addons.terrascript.parser.lang.Returnable; import com.dfsek.terra.addons.terrascript.parser.lang.functions.FunctionBuilder; import com.dfsek.terra.addons.terrascript.script.functions.CheckBlockFunction; import com.dfsek.terra.addons.terrascript.tokenizer.Position; +import java.util.List; + public class CheckBlockFunctionBuilder implements FunctionBuilder { @SuppressWarnings("unchecked") diff --git a/common/api/build.gradle.kts b/common/api/build.gradle.kts index 4f88c83e39..898f8bdcd6 100644 --- a/common/api/build.gradle.kts +++ b/common/api/build.gradle.kts @@ -2,7 +2,7 @@ dependencies { api("ca.solo-studios", "strata", Versions.Libraries.strata) compileOnlyApi("org.slf4j", "slf4j-api", Versions.Libraries.slf4j) testImplementation("org.slf4j", "slf4j-api", Versions.Libraries.slf4j) - api("cloud.commandframework", "cloud-core", Versions.Libraries.cloud) + api("org.incendo", "cloud-core", Versions.Libraries.cloud) api("com.dfsek.tectonic", "common", Versions.Libraries.tectonic) diff --git a/common/api/src/main/java/com/dfsek/terra/api/command/arguments/RegistryArgument.java b/common/api/src/main/java/com/dfsek/terra/api/command/arguments/RegistryArgument.java index e89298751e..8e15c18ceb 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/command/arguments/RegistryArgument.java +++ b/common/api/src/main/java/com/dfsek/terra/api/command/arguments/RegistryArgument.java @@ -1,18 +1,19 @@ package com.dfsek.terra.api.command.arguments; -import cloud.commandframework.ArgumentDescription; -import cloud.commandframework.arguments.CommandArgument; -import cloud.commandframework.arguments.parser.ArgumentParseResult; -import cloud.commandframework.arguments.parser.ArgumentParser; -import cloud.commandframework.context.CommandContext; import io.leangen.geantyref.TypeToken; import org.checkerframework.checker.nullness.qual.NonNull; -import org.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.Queue; -import java.util.function.BiFunction; +import java.util.concurrent.CompletableFuture; import java.util.function.Function; import java.util.stream.Collectors; @@ -22,39 +23,22 @@ import com.dfsek.terra.api.util.reflection.TypeKey; -public class RegistryArgument extends CommandArgument { - private RegistryArgument( - boolean required, - @NonNull String name, - Function, Registry> registryFunction, - TypeToken typeToken, - @NonNull String defaultValue, - @Nullable BiFunction, String, List> suggestionsProvider, - @NonNull ArgumentDescription description - ) { - super(required, - name, - new RegistryArgumentParser<>(registryFunction), - defaultValue, - typeToken, - suggestionsProvider, - description); - } +public class RegistryArgument { public static Builder builder(String name, Registry registry) { return new Builder<>(name, registry); } - public static CommandArgument of(String name, Registry registry) { + public static CommandComponent of(String name, Registry registry) { return RegistryArgument.builder(name, registry).build(); } - public static CommandArgument optional(String name, Registry registry) { - return RegistryArgument.builder(name, registry).asOptional().build(); + public static CommandComponent optional(String name, Registry registry) { + return RegistryArgument.builder(name, registry).optional().build(); } - public static CommandArgument optional(String name, Registry registry, String defaultKey) { - return RegistryArgument.builder(name, registry).asOptionalWithDefault(defaultKey).build(); + public static CommandComponent optional(String name, Registry registry, DefaultValue defaultKey) { + return RegistryArgument.builder(name, registry).optional(defaultKey).build(); } @SuppressWarnings("unchecked") @@ -63,49 +47,36 @@ public static Builder builder(String name, Function(name, registryFunction, (TypeToken) TypeToken.get(registryType.getType())); } - public static CommandArgument of(String name, Function, Registry> registryFunction, - TypeKey registryType) { + public static CommandComponent of(String name, Function, Registry> registryFunction, + TypeKey registryType) { return RegistryArgument.builder(name, registryFunction, registryType).build(); } - public static CommandArgument optional(String name, Function, Registry> registryFunction, - TypeKey registryType) { - return RegistryArgument.builder(name, registryFunction, registryType).asOptional().build(); + public static CommandComponent optional(String name, Function, Registry> registryFunction, + TypeKey registryType) { + return RegistryArgument.builder(name, registryFunction, registryType).optional().build(); } - public static CommandArgument optional(String name, Function, Registry> registryFunction, - TypeKey registryType, String defaultKey) { - return RegistryArgument.builder(name, registryFunction, registryType).asOptionalWithDefault(defaultKey).build(); + public static CommandComponent optional(String name, Function, Registry> registryFunction, + TypeKey registryType, DefaultValue defaultKey) { + return RegistryArgument.builder(name, registryFunction, registryType).optional(defaultKey).build(); } - public static final class Builder extends CommandArgument.Builder { - private final Function, Registry> registryFunction; - private final TypeToken typeToken; + public static final class Builder extends CommandComponent.Builder { @SuppressWarnings("unchecked") private Builder(@NonNull String name, Registry registry) { - super((TypeToken) TypeToken.get(registry.getType().getType()), name); - this.registryFunction = commandContext -> registry; - this.typeToken = (TypeToken) TypeToken.get(registry.getType().getType()); + super(); + this.name(name); + this.parser(ParserDescriptor.of( + new RegistryArgumentParser<>(commandContext -> registry), + (TypeToken) TypeToken.get(registry.getType().getType()))); } private Builder(@NonNull String name, Function, Registry> registryFunction, TypeToken typeToken) { - super(typeToken, name); - this.typeToken = typeToken; - this.registryFunction = registryFunction; - } - - @Override - public @NonNull RegistryArgument build() { - return new RegistryArgument<>( - isRequired(), - getName(), - registryFunction, - typeToken, - getDefaultValue(), - getSuggestionsProvider(), - getDefaultDescription() - ); + super(); + this.name(name); + this.parser(ParserDescriptor.of(new RegistryArgumentParser<>(registryFunction), typeToken)); } } @@ -119,12 +90,12 @@ private RegistryArgumentParser(Function, Registry> registry @Override public @NonNull ArgumentParseResult<@NonNull R> parse(@NonNull CommandContext<@NonNull T> commandContext, - @NonNull Queue<@NonNull String> inputQueue) { - String input = inputQueue.remove(); - String next = inputQueue.peek(); - if(next != null && next.equals(":")) { - input += inputQueue.remove(); - input += inputQueue.remove(); + @NonNull CommandInput commandInput) { + String input = commandInput.readString(); + String next = commandInput.peekString(); + if(next.equals(":")) { + input += commandInput.readString(); + input += commandInput.readString(); } Registry registry = registryFunction.apply(commandContext); @@ -146,8 +117,17 @@ private RegistryArgumentParser(Function, Registry> registry } @Override - public @NonNull List<@NonNull String> suggestions(@NonNull CommandContext commandContext, @NonNull String input) { - return registryFunction.apply(commandContext).keys().stream().map(RegistryKey::toString).sorted().collect(Collectors.toList()); + public @NonNull SuggestionProvider suggestionProvider() { + return new SuggestionProvider<>() { + @Override + public @NonNull CompletableFuture> suggestionsFuture( + @NonNull CommandContext 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())); + } + }; } } } diff --git a/common/api/src/main/java/com/dfsek/terra/api/event/events/platform/CommandRegistrationEvent.java b/common/api/src/main/java/com/dfsek/terra/api/event/events/platform/CommandRegistrationEvent.java index de13f061a2..3ad041c9bd 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/event/events/platform/CommandRegistrationEvent.java +++ b/common/api/src/main/java/com/dfsek/terra/api/event/events/platform/CommandRegistrationEvent.java @@ -1,10 +1,10 @@ package com.dfsek.terra.api.event.events.platform; -import cloud.commandframework.CommandManager; - import com.dfsek.terra.api.command.CommandSender; import com.dfsek.terra.api.event.events.Event; +import org.incendo.cloud.CommandManager; + public class CommandRegistrationEvent implements Event { private final CommandManager commandManager; diff --git a/common/api/src/main/java/com/dfsek/terra/api/noise/DerivativeNoiseSampler.java b/common/api/src/main/java/com/dfsek/terra/api/noise/DerivativeNoiseSampler.java new file mode 100644 index 0000000000..f9e40f0ea5 --- /dev/null +++ b/common/api/src/main/java/com/dfsek/terra/api/noise/DerivativeNoiseSampler.java @@ -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); +} diff --git a/common/api/src/main/java/com/dfsek/terra/api/util/reflection/ReflectionUtil.java b/common/api/src/main/java/com/dfsek/terra/api/util/reflection/ReflectionUtil.java index 8e35c3f9f3..2583b9ab6b 100644 --- a/common/api/src/main/java/com/dfsek/terra/api/util/reflection/ReflectionUtil.java +++ b/common/api/src/main/java/com/dfsek/terra/api/util/reflection/ReflectionUtil.java @@ -8,6 +8,7 @@ package com.dfsek.terra.api.util.reflection; import org.jetbrains.annotations.NotNull; +import sun.misc.Unsafe; import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; @@ -26,6 +27,18 @@ public final class ReflectionUtil { + private static final Unsafe UNSAFE; + + static { + try { + final Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe"); + unsafeField.setAccessible(true); + UNSAFE = (Unsafe) unsafeField.get(null); + } catch(NoSuchFieldException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + public static Field[] getFields(@NotNull Class type) { Field[] result = type.getDeclaredFields(); Class parentClass = type.getSuperclass(); @@ -35,6 +48,14 @@ public static Field[] getFields(@NotNull Class type) { return result; } + public static void setFinalField(Object obj, String fieldName, Object value) throws NoSuchFieldException { + Field field = obj.getClass().getDeclaredField(fieldName); + field.setAccessible(true); + long fieldOffset = UNSAFE.objectFieldOffset(field); + + UNSAFE.putObject(obj, fieldOffset, value); + } + public static Method[] getMethods(@NotNull Class type) { Method[] result = type.getDeclaredMethods(); Class parentClass = type.getSuperclass(); diff --git a/common/implementation/base/src/main/java/com/dfsek/terra/config/preprocessor/MetaNumberPreprocessor.java b/common/implementation/base/src/main/java/com/dfsek/terra/config/preprocessor/MetaNumberPreprocessor.java index 9197adeb1e..c823d7ec44 100644 --- a/common/implementation/base/src/main/java/com/dfsek/terra/config/preprocessor/MetaNumberPreprocessor.java +++ b/common/implementation/base/src/main/java/com/dfsek/terra/config/preprocessor/MetaNumberPreprocessor.java @@ -24,14 +24,15 @@ import com.dfsek.tectonic.api.exception.LoadException; import com.dfsek.tectonic.api.loader.ConfigLoader; import com.dfsek.tectonic.api.preprocessor.Result; + +import com.dfsek.terra.api.config.meta.Meta; +import com.dfsek.terra.api.util.reflection.TypeKey; + import org.jetbrains.annotations.NotNull; import java.lang.reflect.AnnotatedType; import java.util.Map; -import com.dfsek.terra.api.config.meta.Meta; -import com.dfsek.terra.api.util.reflection.TypeKey; - public class MetaNumberPreprocessor extends MetaPreprocessor { public static final TypeKey META_STRING_KEY = new TypeKey<@Meta String>() { diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index d64cd49177..e6441136f3 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index db8c3baafe..8e876e1c55 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=9d926787066a081739e8200858338b4a69e837c3a821a33aca9db09dd4a41026 -distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip +distributionSha256Sum=1541fa36599e12857140465f3c91a97409b4512501c26f9631fb113e392c5bd1 +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME diff --git a/gradlew b/gradlew index 1aa94a4269..b740cf1339 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (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. # # You can find Gradle at https://github.com/gradle/gradle/. diff --git a/gradlew.bat b/gradlew.bat index 93e3f59f13..25da30dbde 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -43,11 +43,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail diff --git a/platforms/bukkit/build.gradle.kts b/platforms/bukkit/build.gradle.kts index 6f75b01330..08a75dc125 100644 --- a/platforms/bukkit/build.gradle.kts +++ b/platforms/bukkit/build.gradle.kts @@ -2,15 +2,9 @@ plugins { id("xyz.jpenilla.run-paper") version Versions.Bukkit.runPaper } -repositories { - maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") { - name = "Sonatype" - } -} - dependencies { shaded(project(":platforms:bukkit:common")) - shaded(project(":platforms:bukkit:nms:v1_20_R3", configuration = "reobf")) + shaded(project(":platforms:bukkit:nms:v1_21", configuration = "reobf")) shaded("xyz.jpenilla", "reflection-remapper", Versions.Bukkit.reflectionRemapper) } diff --git a/platforms/bukkit/common/build.gradle.kts b/platforms/bukkit/common/build.gradle.kts index f47415da4c..eaf1956cbe 100644 --- a/platforms/bukkit/common/build.gradle.kts +++ b/platforms/bukkit/common/build.gradle.kts @@ -11,5 +11,5 @@ dependencies { 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) } diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java index a8701da17e..e3bc1d8376 100644 --- a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/TerraBukkitPlugin.java @@ -17,15 +17,16 @@ 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.GlobalRegionScheduler; import org.bukkit.Bukkit; import org.bukkit.generator.ChunkGenerator; import org.bukkit.plugin.java.JavaPlugin; +import org.incendo.cloud.SenderMapper; +import org.incendo.cloud.brigadier.CloudBrigadierManager; +import org.incendo.cloud.bukkit.CloudBukkitCapabilities; +import org.incendo.cloud.execution.ExecutionCoordinator; +import org.incendo.cloud.paper.LegacyPaperCommandManager; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; @@ -71,14 +72,14 @@ public void onEnable() { } try { - PaperCommandManager commandManager = getCommandSenderPaperCommandManager(); + LegacyPaperCommandManager commandManager = getCommandSenderPaperCommandManager(); platform.getEventManager().callEvent(new CommandRegistrationEvent(commandManager)); } catch(Exception e) { // This should never happen. logger.error(""" TERRA HAS BEEN DISABLED - + Errors occurred while registering commands. Please report this to Terra. """.strip(), e); @@ -91,22 +92,26 @@ public void onEnable() { } @NotNull - private PaperCommandManager getCommandSenderPaperCommandManager() throws Exception { - PaperCommandManager commandManager = new PaperCommandManager<>(this, - CommandExecutionCoordinator.simpleCoordinator(), - BukkitAdapter::adapt, - BukkitAdapter::adapt); + private LegacyPaperCommandManager getCommandSenderPaperCommandManager() throws Exception { + // TODO: Update to PaperCommandManager + LegacyPaperCommandManager commandManager = new LegacyPaperCommandManager<>( + this, + ExecutionCoordinator.simpleCoordinator(), + SenderMapper.create( + BukkitAdapter::adapt, + BukkitAdapter::adapt + )); + if(commandManager.hasCapability(CloudBukkitCapabilities.NATIVE_BRIGADIER)) { commandManager.registerBrigadier(); final CloudBrigadierManager brigManager = commandManager.brigadierManager(); if(brigManager != null) { brigManager.setNativeNumberSuggestions(false); } - } - - if(commandManager.hasCapability(CloudBukkitCapabilities.ASYNCHRONOUS_COMPLETION)) { + } else if(commandManager.hasCapability(CloudBukkitCapabilities.ASYNCHRONOUS_COMPLETION)) { commandManager.registerAsynchronousCompletions(); } + return commandManager; } @@ -176,7 +181,7 @@ private boolean doVersionCheck() { logger.warn(""" You are using Mohist, so we will not give you any support for issues that may arise. Since you enabled the "IKnowMohistCausesLotsOfIssuesButIWillUseItAnyways" flag, we won't disable Terra. But be warned. - + > I felt a great disturbance in the JVM, as if millions of plugins suddenly cried out in stack traces and were suddenly silenced. > I fear something terrible has happened. > - Astrash @@ -189,6 +194,7 @@ private boolean doVersionCheck() { @Override public @Nullable ChunkGenerator getDefaultWorldGenerator(@NotNull String worldName, String id) { + if(id == null || id.trim().equals("")) { return null; } return new BukkitChunkGeneratorWrapper(generatorMap.computeIfAbsent(worldName, name -> { ConfigPack pack = platform.getConfigRegistry().getByID(id).orElseThrow( () -> new IllegalArgumentException("No such config pack \"" + id + "\"")); diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/handles/BukkitWorldHandle.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/handles/BukkitWorldHandle.java index e3b92b069d..35922cab5c 100644 --- a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/handles/BukkitWorldHandle.java +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/handles/BukkitWorldHandle.java @@ -23,13 +23,11 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Locale; - import com.dfsek.terra.api.block.state.BlockState; import com.dfsek.terra.api.entity.EntityType; import com.dfsek.terra.api.handle.WorldHandle; +import com.dfsek.terra.bukkit.util.BukkitUtils; import com.dfsek.terra.bukkit.world.block.data.BukkitBlockState; -import com.dfsek.terra.bukkit.world.entity.BukkitEntityType; public class BukkitWorldHandle implements WorldHandle { @@ -61,21 +59,6 @@ public BukkitWorldHandle() { @Override public @NotNull EntityType getEntity(@NotNull String id) { - if (!id.contains(":")) { //TODO: remove in 7.0 - String newid = "minecraft:" + id.toLowerCase();; - logger.warn( - "Translating " + id + " to " + newid + ". In 1.20.3 entity parsing was reworked" + - ". You are advised to perform this rename in your config backs as this translation will be removed in the next major " + - "version of Terra."); - } - if(!id.startsWith("minecraft:")) throw new IllegalArgumentException("Invalid entity identifier " + id); - String entityID = id.toUpperCase(Locale.ROOT).substring(10); - - return new BukkitEntityType(switch(entityID) { - case "END_CRYSTAL" -> org.bukkit.entity.EntityType.ENDER_CRYSTAL; - case "ENDER_CRYSTAL" -> throw new IllegalArgumentException( - "Invalid entity identifier " + id); // make sure this issue can't happen the other way around. - default -> org.bukkit.entity.EntityType.valueOf(entityID); - }); + return BukkitUtils.getEntityType(id); } } diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/nms/Initializer.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/nms/Initializer.java index 413250d57b..fc28e4bc38 100644 --- a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/nms/Initializer.java +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/nms/Initializer.java @@ -1,20 +1,25 @@ package com.dfsek.terra.bukkit.nms; -import org.bukkit.Bukkit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.dfsek.terra.bukkit.PlatformImpl; +import com.dfsek.terra.bukkit.util.VersionUtil; public interface Initializer { - String NMS = Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]; + String NMS = VersionUtil.getMinecraftVersionInfo().toString().replace(".", "_"); String TERRA_PACKAGE = Initializer.class.getPackageName(); static boolean init(PlatformImpl platform) { Logger logger = LoggerFactory.getLogger(Initializer.class); 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 { Initializer initializer = (Initializer) initializerClass.getConstructor().newInstance(); initializer.initialize(platform); diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/util/BukkitUtils.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/util/BukkitUtils.java index cc2fa78ef3..6c0a9c7f4d 100644 --- a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/util/BukkitUtils.java +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/util/BukkitUtils.java @@ -2,11 +2,40 @@ import org.bukkit.Material; import org.bukkit.block.data.BlockData; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.Locale; + +import com.dfsek.terra.api.entity.EntityType; +import com.dfsek.terra.bukkit.world.entity.BukkitEntityType; public class BukkitUtils { + private static final Logger logger = LoggerFactory.getLogger(BukkitUtils.class); + public static boolean isLiquid(BlockData blockState) { Material material = blockState.getMaterial(); return material == Material.WATER || material == Material.LAVA; } + + public static EntityType getEntityType(String id) { + if(!id.contains(":")) { //TODO: remove in 7.0 + String newid = "minecraft:" + id.toLowerCase(); + ; + logger.warn( + "Translating " + id + " to " + newid + ". In 1.20.3 entity parsing was reworked" + + ". You are advised to perform this rename in your config backs as this translation will be removed in the next major " + + "version of Terra."); + } + if(!id.startsWith("minecraft:")) throw new IllegalArgumentException("Invalid entity identifier " + id); + String entityID = id.toUpperCase(Locale.ROOT).substring(10); + + return new BukkitEntityType(switch(entityID) { + case "END_CRYSTAL" -> org.bukkit.entity.EntityType.END_CRYSTAL; + case "ENDER_CRYSTAL" -> throw new IllegalArgumentException( + "Invalid entity identifier " + id); // make sure this issue can't happen the other way around. + default -> org.bukkit.entity.EntityType.valueOf(entityID); + }); + } } diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/util/VersionUtil.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/util/VersionUtil.java index 6bc06a4371..3f32b6be2b 100644 --- a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/util/VersionUtil.java +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/util/VersionUtil.java @@ -77,13 +77,13 @@ public boolean isSpigot() { public static final class MinecraftVersionInfo { 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 minor; private final int patch; private MinecraftVersionInfo() { - this(Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]); + this(Bukkit.getServer().getBukkitVersion().split("-")[0]); } private MinecraftVersionInfo(int major, int minor, int patch) { @@ -97,7 +97,7 @@ private MinecraftVersionInfo(String versionString) { if(versionMatcher.find()) { major = Integer.parseInt(versionMatcher.group(1)); minor = Integer.parseInt(versionMatcher.group(2)); - patch = Integer.parseInt(versionMatcher.group(3)); + patch = versionMatcher.group(3) != null ? Integer.parseInt(versionMatcher.group(3)) : -1; } else { logger.warn("Error while parsing minecraft version info. Continuing launch, but setting all versions to -1."); @@ -112,7 +112,11 @@ public String toString() { if(major == -1 && minor == -1 && patch == -1) 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() { diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitAdapter.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitAdapter.java index f2d446de7f..4082658211 100644 --- a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitAdapter.java +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitAdapter.java @@ -20,7 +20,6 @@ import org.bukkit.Location; import org.bukkit.Material; -import org.bukkit.TreeType; import org.bukkit.entity.Player; import org.bukkit.generator.WorldInfo; import org.bukkit.util.Vector; @@ -46,27 +45,12 @@ import com.dfsek.terra.bukkit.world.block.data.BukkitBlockState; import com.dfsek.terra.bukkit.world.inventory.BukkitItemStack; import com.dfsek.terra.bukkit.world.inventory.meta.BukkitEnchantment; -import com.dfsek.terra.transform.MapTransform; -import com.dfsek.terra.transform.TransformerImpl; /** * Utility class to adapt Bukkit enums to Terra enums. */ public final class BukkitAdapter { - public static TransformerImpl TREE_TRANSFORMER = new TransformerImpl.Builder() - .addTransform(new MapTransform() - .add(TreeType.COCOA_TREE, "JUNGLE_COCOA") - .add(TreeType.BIG_TREE, "LARGE_OAK") - .add(TreeType.TALL_REDWOOD, "LARGE_SPRUCE") - .add(TreeType.REDWOOD, "SPRUCE") - .add(TreeType.TREE, "OAK") - .add(TreeType.MEGA_REDWOOD, "MEGA_SPRUCE") - .add(TreeType.SWAMP, "SWAMP_OAK")) - .addTransform(TreeType::toString) - .build(); - - public static BlockState adapt(org.bukkit.block.data.BlockData data) { return BukkitBlockState.newInstance(data); } diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitWorldProperties.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitWorldProperties.java index f9763df902..7ece9ac7b6 100644 --- a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitWorldProperties.java +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/BukkitWorldProperties.java @@ -1,9 +1,9 @@ package com.dfsek.terra.bukkit.world; -import org.bukkit.generator.WorldInfo; - import com.dfsek.terra.api.world.info.WorldProperties; +import org.bukkit.generator.WorldInfo; + public class BukkitWorldProperties implements WorldProperties { private final WorldInfo delegate; diff --git a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitMobSpawner.java b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitMobSpawner.java index 7bdc75d967..dc9d1ecb6c 100644 --- a/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitMobSpawner.java +++ b/platforms/bukkit/common/src/main/java/com/dfsek/terra/bukkit/world/block/state/BukkitMobSpawner.java @@ -23,6 +23,7 @@ import com.dfsek.terra.api.block.entity.MobSpawner; import com.dfsek.terra.api.block.entity.SerialState; import com.dfsek.terra.api.entity.EntityType; +import com.dfsek.terra.bukkit.util.BukkitUtils; import com.dfsek.terra.bukkit.world.entity.BukkitEntityType; @@ -115,7 +116,7 @@ public void setSpawnRange(int spawnRange) { public void applyState(String state) { SerialState.parse(state).forEach((k, v) -> { switch(k) { - case "type" -> setSpawnedType(new BukkitEntityType(org.bukkit.entity.EntityType.valueOf(v.toUpperCase()))); + case "type" -> setSpawnedType(BukkitUtils.getEntityType(v)); case "delay" -> setDelay(Integer.parseInt(v)); case "min_delay" -> setMinSpawnDelay(Integer.parseInt(v)); case "max_delay" -> setMaxSpawnDelay(Integer.parseInt(v)); diff --git a/platforms/bukkit/common/src/main/resources/plugin.yml b/platforms/bukkit/common/src/main/resources/plugin.yml index e965d7deed..782861cfea 100644 --- a/platforms/bukkit/common/src/main/resources/plugin.yml +++ b/platforms/bukkit/common/src/main/resources/plugin.yml @@ -2,8 +2,8 @@ name: "Terra" main: "com.dfsek.terra.bukkit.TerraBukkitPlugin" version: "@VERSION@" load: "STARTUP" -author: dfsek +authors: [ "dfsek", "duplexsystem", "Astrash", "solonovamax", "Sancires", "Aureus", "RogueShade" ] website: "@WIKI@" -api-version: "1.20" +api-version: "1.21.1" description: "@DESCRIPTION@" folia-supported: true diff --git a/platforms/bukkit/nms/v1_20_R3/build.gradle.kts b/platforms/bukkit/nms/v1_21/build.gradle.kts similarity index 77% rename from platforms/bukkit/nms/v1_20_R3/build.gradle.kts rename to platforms/bukkit/nms/v1_21/build.gradle.kts index 6881c96ca1..d52f1d1691 100644 --- a/platforms/bukkit/nms/v1_20_R3/build.gradle.kts +++ b/platforms/bukkit/nms/v1_21/build.gradle.kts @@ -1,9 +1,5 @@ apply(plugin = "io.papermc.paperweight.userdev") -repositories { - maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") -} - dependencies { api(project(":platforms:bukkit:common")) paperDevBundle(Versions.Bukkit.paperDevBundle) diff --git a/platforms/bukkit/nms/v1_20_R3/src/main/java/com/dfsek/terra/bukkit/nms/v1_20_R3/AwfulBukkitHacks.java b/platforms/bukkit/nms/v1_21/src/main/java/com/dfsek/terra/bukkit/nms/v1_21/AwfulBukkitHacks.java similarity index 91% rename from platforms/bukkit/nms/v1_20_R3/src/main/java/com/dfsek/terra/bukkit/nms/v1_20_R3/AwfulBukkitHacks.java rename to platforms/bukkit/nms/v1_21/src/main/java/com/dfsek/terra/bukkit/nms/v1_21/AwfulBukkitHacks.java index fa2cc9907b..42d6833942 100644 --- a/platforms/bukkit/nms/v1_20_R3/src/main/java/com/dfsek/terra/bukkit/nms/v1_20_R3/AwfulBukkitHacks.java +++ b/platforms/bukkit/nms/v1_21/src/main/java/com/dfsek/terra/bukkit/nms/v1_21/AwfulBukkitHacks.java @@ -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.mojang.serialization.Lifecycle; import net.minecraft.core.Holder; import net.minecraft.core.Holder.Reference; import net.minecraft.core.MappedRegistry; +import net.minecraft.core.RegistrationInfo; import net.minecraft.core.WritableRegistry; import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceKey; @@ -41,15 +41,16 @@ public static void registerBiomes(ConfigRegistry configRegistry) { try { BukkitPlatformBiome platformBiome = (BukkitPlatformBiome) biome.getPlatformBiome(); 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))); ResourceKey delegateKey = ResourceKey.create( Registries.BIOME, - new ResourceLocation("terra", NMSBiomeInjector.createBiomeID(pack, key)) + ResourceLocation.fromNamespaceAndPath("terra", NMSBiomeInjector.createBiomeID(pack, key)) ); - Reference holder = biomeRegistry.register(delegateKey, platform, Lifecycle.stable()); + Reference holder = biomeRegistry.register(delegateKey, platform, RegistrationInfo.BUILT_IN); Reflection.REFERENCE.invokeBindValue(holder, platform); // IMPORTANT: bind holder. platformBiome.getContext().put(new NMSBiomeInfo(delegateKey)); diff --git a/platforms/bukkit/nms/v1_20_R3/src/main/java/com/dfsek/terra/bukkit/nms/v1_20_R3/NMSBiomeInfo.java b/platforms/bukkit/nms/v1_21/src/main/java/com/dfsek/terra/bukkit/nms/v1_21/NMSBiomeInfo.java similarity index 83% rename from platforms/bukkit/nms/v1_20_R3/src/main/java/com/dfsek/terra/bukkit/nms/v1_20_R3/NMSBiomeInfo.java rename to platforms/bukkit/nms/v1_21/src/main/java/com/dfsek/terra/bukkit/nms/v1_21/NMSBiomeInfo.java index f47d21c56e..5bf85aa6de 100644 --- a/platforms/bukkit/nms/v1_20_R3/src/main/java/com/dfsek/terra/bukkit/nms/v1_20_R3/NMSBiomeInfo.java +++ b/platforms/bukkit/nms/v1_21/src/main/java/com/dfsek/terra/bukkit/nms/v1_21/NMSBiomeInfo.java @@ -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.world.level.biome.Biome; diff --git a/platforms/bukkit/nms/v1_20_R3/src/main/java/com/dfsek/terra/bukkit/nms/v1_20_R3/NMSBiomeInjector.java b/platforms/bukkit/nms/v1_21/src/main/java/com/dfsek/terra/bukkit/nms/v1_21/NMSBiomeInjector.java similarity index 98% rename from platforms/bukkit/nms/v1_20_R3/src/main/java/com/dfsek/terra/bukkit/nms/v1_20_R3/NMSBiomeInjector.java rename to platforms/bukkit/nms/v1_21/src/main/java/com/dfsek/terra/bukkit/nms/v1_21/NMSBiomeInjector.java index e75b6fc0a6..e6d1f78695 100644 --- a/platforms/bukkit/nms/v1_20_R3/src/main/java/com/dfsek/terra/bukkit/nms/v1_20_R3/NMSBiomeInjector.java +++ b/platforms/bukkit/nms/v1_21/src/main/java/com/dfsek/terra/bukkit/nms/v1_21/NMSBiomeInjector.java @@ -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.Registry; diff --git a/platforms/bukkit/nms/v1_20_R3/src/main/java/com/dfsek/terra/bukkit/nms/v1_20_R3/NMSBiomeProvider.java b/platforms/bukkit/nms/v1_21/src/main/java/com/dfsek/terra/bukkit/nms/v1_21/NMSBiomeProvider.java similarity index 73% rename from platforms/bukkit/nms/v1_20_R3/src/main/java/com/dfsek/terra/bukkit/nms/v1_20_R3/NMSBiomeProvider.java rename to platforms/bukkit/nms/v1_21/src/main/java/com/dfsek/terra/bukkit/nms/v1_21/NMSBiomeProvider.java index 875a77fb52..8abe26a51b 100644 --- a/platforms/bukkit/nms/v1_20_R3/src/main/java/com/dfsek/terra/bukkit/nms/v1_20_R3/NMSBiomeProvider.java +++ b/platforms/bukkit/nms/v1_21/src/main/java/com/dfsek/terra/bukkit/nms/v1_21/NMSBiomeProvider.java @@ -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.Registry; import net.minecraft.world.level.biome.Biome; @@ -35,8 +35,12 @@ protected Stream> collectPossibleBiomes() { } @Override - protected @NotNull Codec codec() { - return BiomeSource.CODEC; + protected @NotNull MapCodec 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 diff --git a/platforms/bukkit/nms/v1_20_R3/src/main/java/com/dfsek/terra/bukkit/nms/v1_20_R3/NMSChunkGeneratorDelegate.java b/platforms/bukkit/nms/v1_21/src/main/java/com/dfsek/terra/bukkit/nms/v1_21/NMSChunkGeneratorDelegate.java similarity index 90% rename from platforms/bukkit/nms/v1_20_R3/src/main/java/com/dfsek/terra/bukkit/nms/v1_20_R3/NMSChunkGeneratorDelegate.java rename to platforms/bukkit/nms/v1_21/src/main/java/com/dfsek/terra/bukkit/nms/v1_21/NMSChunkGeneratorDelegate.java index 4338dc140c..16097df272 100644 --- a/platforms/bukkit/nms/v1_20_R3/src/main/java/com/dfsek/terra/bukkit/nms/v1_20_R3/NMSChunkGeneratorDelegate.java +++ b/platforms/bukkit/nms/v1_21/src/main/java/com/dfsek/terra/bukkit/nms/v1_21/NMSChunkGeneratorDelegate.java @@ -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.server.level.WorldGenRegion; import net.minecraft.world.level.LevelAccessor; @@ -19,14 +19,13 @@ import net.minecraft.world.level.levelgen.Heightmap.Types; import net.minecraft.world.level.levelgen.RandomState; import net.minecraft.world.level.levelgen.blending.Blender; -import org.bukkit.craftbukkit.v1_20_R3.block.data.CraftBlockData; +import org.bukkit.craftbukkit.block.data.CraftBlockData; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.List; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Executor; import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; @@ -54,8 +53,8 @@ public NMSChunkGeneratorDelegate(ChunkGenerator vanilla, ConfigPack pack, NMSBio } @Override - protected @NotNull Codec codec() { - return ChunkGenerator.CODEC; + protected @NotNull MapCodec codec() { + return MapCodec.assumeMapUnsafe(ChunkGenerator.CODEC); } @Override @@ -87,10 +86,10 @@ public int getGenDepth() { } @Override - public @NotNull CompletableFuture fillFromNoise(@NotNull Executor executor, @NotNull Blender blender, - @NotNull RandomState noiseConfig, - @NotNull StructureManager structureAccessor, @NotNull ChunkAccess chunk) { - return vanilla.fillFromNoise(executor, blender, noiseConfig, structureAccessor, chunk) + public CompletableFuture fillFromNoise(@NotNull Blender blender, + @NotNull RandomState noiseConfig, + @NotNull StructureManager structureAccessor, @NotNull ChunkAccess chunk) { + return vanilla.fillFromNoise(blender, noiseConfig, structureAccessor, chunk) .thenApply(c -> { LevelAccessor level = Reflection.STRUCTURE_MANAGER.getLevel(structureAccessor); BiomeProvider biomeProvider = pack.getBiomeProvider(); diff --git a/platforms/bukkit/nms/v1_20_R3/src/main/java/com/dfsek/terra/bukkit/nms/v1_20_R3/NMSInitializer.java b/platforms/bukkit/nms/v1_21/src/main/java/com/dfsek/terra/bukkit/nms/v1_21/NMSInitializer.java similarity index 90% rename from platforms/bukkit/nms/v1_20_R3/src/main/java/com/dfsek/terra/bukkit/nms/v1_20_R3/NMSInitializer.java rename to platforms/bukkit/nms/v1_21/src/main/java/com/dfsek/terra/bukkit/nms/v1_21/NMSInitializer.java index 084c5c30a0..18f1a058f9 100644 --- a/platforms/bukkit/nms/v1_20_R3/src/main/java/com/dfsek/terra/bukkit/nms/v1_20_R3/NMSInitializer.java +++ b/platforms/bukkit/nms/v1_21/src/main/java/com/dfsek/terra/bukkit/nms/v1_21/NMSInitializer.java @@ -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; diff --git a/platforms/bukkit/nms/v1_20_R3/src/main/java/com/dfsek/terra/bukkit/nms/v1_20_R3/NMSInjectListener.java b/platforms/bukkit/nms/v1_21/src/main/java/com/dfsek/terra/bukkit/nms/v1_21/NMSInjectListener.java similarity index 68% rename from platforms/bukkit/nms/v1_20_R3/src/main/java/com/dfsek/terra/bukkit/nms/v1_20_R3/NMSInjectListener.java rename to platforms/bukkit/nms/v1_21/src/main/java/com/dfsek/terra/bukkit/nms/v1_21/NMSInjectListener.java index a81e93a3f3..a25638594e 100644 --- a/platforms/bukkit/nms/v1_20_R3/src/main/java/com/dfsek/terra/bukkit/nms/v1_20_R3/NMSInjectListener.java +++ b/platforms/bukkit/nms/v1_21/src/main/java/com/dfsek/terra/bukkit/nms/v1_21/NMSInjectListener.java @@ -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.world.level.chunk.ChunkGenerator; +import net.minecraft.world.level.chunk.status.WorldGenContext; 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.Listener; import org.bukkit.event.world.WorldInitEvent; @@ -15,6 +17,7 @@ import java.util.concurrent.locks.ReentrantLock; import com.dfsek.terra.api.config.ConfigPack; +import com.dfsek.terra.api.util.reflection.ReflectionUtil; import com.dfsek.terra.bukkit.generator.BukkitChunkGeneratorWrapper; @@ -37,8 +40,15 @@ public void onWorldInit(WorldInitEvent event) { ChunkGenerator vanilla = serverWorld.getChunkSource().getGenerator(); NMSBiomeProvider provider = new NMSBiomeProvider(pack.getBiomeProvider(), craftWorld.getSeed()); - - serverWorld.getChunkSource().chunkMap.generator = new NMSChunkGeneratorDelegate(vanilla, pack, provider, craftWorld.getSeed()); + ChunkMap chunkMap = serverWorld.getChunkSource().chunkMap; + WorldGenContext worldGenContext = chunkMap.worldGenContext; + Reflection.CHUNKMAP.setWorldGenContext(chunkMap, new WorldGenContext( + worldGenContext.level(), + new NMSChunkGeneratorDelegate(vanilla, pack, provider, craftWorld.getSeed()), + worldGenContext.structureManager(), + worldGenContext.lightEngine(), + worldGenContext.mainThreadMailBox() + )); LOGGER.info("Successfully injected into world."); diff --git a/platforms/bukkit/nms/v1_20_R3/src/main/java/com/dfsek/terra/bukkit/nms/v1_20_R3/NMSWorldProperties.java b/platforms/bukkit/nms/v1_21/src/main/java/com/dfsek/terra/bukkit/nms/v1_21/NMSWorldProperties.java similarity index 94% rename from platforms/bukkit/nms/v1_20_R3/src/main/java/com/dfsek/terra/bukkit/nms/v1_20_R3/NMSWorldProperties.java rename to platforms/bukkit/nms/v1_21/src/main/java/com/dfsek/terra/bukkit/nms/v1_21/NMSWorldProperties.java index 60f6cee46c..7860cf5308 100644 --- a/platforms/bukkit/nms/v1_20_R3/src/main/java/com/dfsek/terra/bukkit/nms/v1_20_R3/NMSWorldProperties.java +++ b/platforms/bukkit/nms/v1_21/src/main/java/com/dfsek/terra/bukkit/nms/v1_21/NMSWorldProperties.java @@ -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; diff --git a/platforms/bukkit/nms/v1_20_R3/src/main/java/com/dfsek/terra/bukkit/nms/v1_20_R3/Reflection.java b/platforms/bukkit/nms/v1_21/src/main/java/com/dfsek/terra/bukkit/nms/v1_21/Reflection.java similarity index 80% rename from platforms/bukkit/nms/v1_20_R3/src/main/java/com/dfsek/terra/bukkit/nms/v1_20_R3/Reflection.java rename to platforms/bukkit/nms/v1_21/src/main/java/com/dfsek/terra/bukkit/nms/v1_21/Reflection.java index 32243da54d..a6f4ea9ba1 100644 --- a/platforms/bukkit/nms/v1_20_R3/src/main/java/com/dfsek/terra/bukkit/nms/v1_20_R3/Reflection.java +++ b/platforms/bukkit/nms/v1_21/src/main/java/com/dfsek/terra/bukkit/nms/v1_21/Reflection.java @@ -1,10 +1,12 @@ -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.Reference; import net.minecraft.core.MappedRegistry; +import net.minecraft.server.level.ChunkMap; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.StructureManager; +import net.minecraft.world.level.chunk.status.WorldGenContext; import xyz.jpenilla.reflectionremapper.ReflectionRemapper; import xyz.jpenilla.reflectionremapper.proxy.ReflectionProxyFactory; import xyz.jpenilla.reflectionremapper.proxy.annotation.FieldGetter; @@ -19,6 +21,8 @@ public class Reflection { public static final ReferenceProxy REFERENCE; + public static final ChunkMapProxy CHUNKMAP; + static { ReflectionRemapper reflectionRemapper = ReflectionRemapper.forReobfMappingsInPaperJar(); ReflectionProxyFactory reflectionProxyFactory = ReflectionProxyFactory.create(reflectionRemapper, @@ -27,6 +31,7 @@ public class Reflection { MAPPED_REGISTRY = reflectionProxyFactory.reflectionProxy(MappedRegistryProxy.class); STRUCTURE_MANAGER = reflectionProxyFactory.reflectionProxy(StructureManagerProxy.class); REFERENCE = reflectionProxyFactory.reflectionProxy(ReferenceProxy.class); + CHUNKMAP = reflectionProxyFactory.reflectionProxy(ChunkMapProxy.class); } @@ -49,4 +54,10 @@ public interface ReferenceProxy { @MethodName("bindValue") void invokeBindValue(Reference instance, T value); } + + @Proxies(ChunkMap.class) + public interface ChunkMapProxy { + @FieldSetter("worldGenContext") + void setWorldGenContext(ChunkMap instance, WorldGenContext worldGenContext); + } } diff --git a/platforms/bukkit/nms/v1_20_R3/src/main/java/com/dfsek/terra/bukkit/nms/v1_20_R3/RegistryFetcher.java b/platforms/bukkit/nms/v1_21/src/main/java/com/dfsek/terra/bukkit/nms/v1_21/RegistryFetcher.java similarity index 88% rename from platforms/bukkit/nms/v1_20_R3/src/main/java/com/dfsek/terra/bukkit/nms/v1_20_R3/RegistryFetcher.java rename to platforms/bukkit/nms/v1_21/src/main/java/com/dfsek/terra/bukkit/nms/v1_21/RegistryFetcher.java index 6dbbecbc77..0377eea0fe 100644 --- a/platforms/bukkit/nms/v1_20_R3/src/main/java/com/dfsek/terra/bukkit/nms/v1_20_R3/RegistryFetcher.java +++ b/platforms/bukkit/nms/v1_21/src/main/java/com/dfsek/terra/bukkit/nms/v1_21/RegistryFetcher.java @@ -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.registries.Registries; @@ -6,7 +6,7 @@ import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.world.level.biome.Biome; import org.bukkit.Bukkit; -import org.bukkit.craftbukkit.v1_20_R3.CraftServer; +import org.bukkit.craftbukkit.CraftServer; public class RegistryFetcher { diff --git a/platforms/fabric/build.gradle.kts b/platforms/fabric/build.gradle.kts index dba2687289..6314246998 100644 --- a/platforms/fabric/build.gradle.kts +++ b/platforms/fabric/build.gradle.kts @@ -26,8 +26,8 @@ dependencies { modImplementation("net.fabricmc:fabric-loader:${Versions.Mod.fabricLoader}") - modImplementation("cloud.commandframework", "cloud-fabric", Versions.Libraries.cloud) - include("cloud.commandframework", "cloud-fabric", Versions.Libraries.cloud) + modImplementation("org.incendo", "cloud-fabric", Versions.Libraries.cloudFabric) + include("org.incendo", "cloud-fabric", Versions.Libraries.cloudFabric) 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()) tasks { - compileJava { - options.release.set(17) - } - remapJar { dependsOn("installAddons") diff --git a/platforms/fabric/src/main/resources/fabric.mod.json b/platforms/fabric/src/main/resources/fabric.mod.json index 8b67c7b547..592d4021a6 100644 --- a/platforms/fabric/src/main/resources/fabric.mod.json +++ b/platforms/fabric/src/main/resources/fabric.mod.json @@ -5,7 +5,13 @@ "name": "Terra", "description": "@DESCRIPTION@", "authors": [ - "dfsek" + "dfsek", + "duplexsystem", + "Astrash", + "solonovamax", + "Sancires", + "Aureus", + "RogueShade" ], "contact": { "homepage": "@WIKI@", @@ -26,9 +32,9 @@ "terra.common.mixins.json" ], "depends": { - "fabricloader": ">=0.15.1", - "java": ">=17", - "minecraft": ">=1.20.4", + "fabricloader": ">=0.16.5", + "java": ">=21", + "minecraft": ">=1.21.1", "fabric": "*" } } \ No newline at end of file diff --git a/platforms/fabric/src/main/resources/terra.fabric.mixins.json b/platforms/fabric/src/main/resources/terra.fabric.mixins.json index f97889f6d9..4778acf1b3 100644 --- a/platforms/fabric/src/main/resources/terra.fabric.mixins.json +++ b/platforms/fabric/src/main/resources/terra.fabric.mixins.json @@ -2,7 +2,7 @@ "required": true, "minVersion": "0.8", "package": "com.dfsek.terra.fabric.mixin", - "compatibilityLevel": "JAVA_17", + "compatibilityLevel": "JAVA_21", "mixins": [ ], "client": [ diff --git a/platforms/forge/src/main/resources/terra.forge.mixins.json b/platforms/forge/src/main/resources/terra.forge.mixins.json index 25c1c470ed..095ea92348 100644 --- a/platforms/forge/src/main/resources/terra.forge.mixins.json +++ b/platforms/forge/src/main/resources/terra.forge.mixins.json @@ -2,7 +2,7 @@ "required": true, "minVersion": "0.8", "package": "com.dfsek.terra.forge.mixin", - "compatibilityLevel": "JAVA_17", + "compatibilityLevel": "JAVA_21", "mixins": [ "lifecycle.NoiseConfigMixin" ], diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/ModPlatform.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/ModPlatform.java index 25c78c228c..09681f6b61 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/ModPlatform.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/ModPlatform.java @@ -3,6 +3,7 @@ import com.dfsek.tectonic.api.TypeRegistry; import com.dfsek.tectonic.api.depth.DepthTracker; import com.dfsek.tectonic.api.exception.LoadException; +import net.minecraft.enchantment.Enchantment; import net.minecraft.entity.EntityType; import net.minecraft.entity.SpawnGroup; import net.minecraft.registry.Registry; @@ -44,7 +45,6 @@ import com.dfsek.terra.mod.config.SoundEventTemplate; import com.dfsek.terra.mod.config.SpawnCostConfig; 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.SpawnTypeConfig; import com.dfsek.terra.mod.config.VillagerTypeTemplate; @@ -82,6 +82,7 @@ public void register(TypeRegistry registry) { .registerLoader(GrassColorModifier.class, (type, o, loader, depthTracker) -> TemperatureModifier.valueOf(((String) o).toUpperCase( Locale.ROOT))) + .registerLoader(SpawnGroup.class, (type, o, loader, depthTracker) -> SpawnGroup.valueOf((String) o)) .registerLoader(BiomeParticleConfig.class, BiomeParticleConfigTemplate::new) .registerLoader(SoundEvent.class, SoundEventTemplate::new) .registerLoader(BiomeMoodSound.class, BiomeMoodSoundTemplate::new) @@ -90,7 +91,6 @@ public void register(TypeRegistry registry) { .registerLoader(EntityType.class, EntityTypeTemplate::new) .registerLoader(SpawnCostConfig.class, SpawnCostConfig::new) .registerLoader(SpawnEntry.class, SpawnEntryTemplate::new) - .registerLoader(SpawnGroup.class, SpawnGroupTemplate::new) .registerLoader(SpawnTypeConfig.class, SpawnTypeConfig::new) .registerLoader(SpawnSettings.class, SpawnSettingsTemplate::new) .registerLoader(VillagerType.class, VillagerTypeTemplate::new); @@ -117,6 +117,8 @@ protected Iterable platformAddon() { public abstract Registry multiNoiseBiomeSourceParameterListRegistry(); + public abstract Registry enchantmentRegistry(); + @Override public @NotNull WorldHandle getWorldHandle() { return worldHandle; @@ -126,4 +128,6 @@ protected Iterable platformAddon() { public @NotNull ItemHandle getItemHandle() { return itemHandle; } + + } diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/BiomeParticleConfigTemplate.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/BiomeParticleConfigTemplate.java index 97c8c8ed7a..457566444d 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/BiomeParticleConfigTemplate.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/BiomeParticleConfigTemplate.java @@ -7,6 +7,7 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.command.argument.ParticleEffectArgumentType; import net.minecraft.registry.Registries; +import net.minecraft.registry.RegistryWrapper; import net.minecraft.world.biome.BiomeParticleConfig; @@ -27,7 +28,8 @@ public BiomeParticleConfig get() { try { return new BiomeParticleConfig( - ParticleEffectArgumentType.readParameters(new StringReader(particle), Registries.PARTICLE_TYPE.getReadOnlyWrapper()), + ParticleEffectArgumentType.readParameters(new StringReader(particle), + (RegistryWrapper.WrapperLookup) Registries.PARTICLE_TYPE.getReadOnlyWrapper()), probability); } catch(CommandSyntaxException e) { throw new RuntimeException(e); diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/SpawnGroupTemplate.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/SpawnGroupTemplate.java deleted file mode 100644 index 0ae2047f2c..0000000000 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/SpawnGroupTemplate.java +++ /dev/null @@ -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 { - @Value("group") - @Default - private String group = null; - - @Override - public SpawnGroup get() { - return SpawnGroup.valueOf(group); - } -} diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/SpawnSettingsTemplate.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/SpawnSettingsTemplate.java index 9392e94e10..a0e8932e50 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/SpawnSettingsTemplate.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/SpawnSettingsTemplate.java @@ -3,7 +3,9 @@ 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; import net.minecraft.world.biome.SpawnSettings; +import net.minecraft.world.biome.SpawnSettings.SpawnEntry; import java.util.List; @@ -25,7 +27,10 @@ public class SpawnSettingsTemplate implements ObjectTemplate { public SpawnSettings get() { SpawnSettings.Builder builder = new SpawnSettings.Builder(); 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) { builder.spawnCost(cost.getType(), cost.getMass(), cost.getGravity()); diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/SpawnTypeConfig.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/SpawnTypeConfig.java index 9384f991d3..0eba7ca67a 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/SpawnTypeConfig.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/config/SpawnTypeConfig.java @@ -6,21 +6,23 @@ import net.minecraft.entity.SpawnGroup; import net.minecraft.world.biome.SpawnSettings.SpawnEntry; +import java.util.List; + public class SpawnTypeConfig implements ObjectTemplate { @Value("group") @Default private SpawnGroup group = null; - @Value("entry") + @Value("entries") @Default - private SpawnEntry entry = null; + private List entry = null; public SpawnGroup getGroup() { return group; } - public SpawnEntry getEntry() { + public List getEntry() { return entry; } diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/data/Codecs.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/data/Codecs.java index 595f5ec5b8..ab7604fe50 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/data/Codecs.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/data/Codecs.java @@ -1,6 +1,7 @@ package com.dfsek.terra.mod.data; import com.mojang.serialization.Codec; +import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.world.gen.chunk.ChunkGeneratorSettings; @@ -32,15 +33,15 @@ public final class Codecs { "No such config pack " + id))))); - public static final Codec TERRA_BIOME_SOURCE = RecordCodecBuilder - .create(instance -> instance.group( + public static final MapCodec TERRA_BIOME_SOURCE = RecordCodecBuilder + .mapCodec(instance -> instance.group( CONFIG_PACK.fieldOf("pack") .stable() .forGetter(TerraBiomeSource::getPack)) .apply(instance, instance.stable(TerraBiomeSource::new))); - public static final Codec MINECRAFT_CHUNK_GENERATOR_WRAPPER = RecordCodecBuilder - .create( + public static final MapCodec MINECRAFT_CHUNK_GENERATOR_WRAPPER = RecordCodecBuilder + .mapCodec( instance -> instance.group( TERRA_BIOME_SOURCE.fieldOf("biome_source") .stable() diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/generation/MinecraftChunkGeneratorWrapper.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/generation/MinecraftChunkGeneratorWrapper.java index 899b007f0b..46f5601ded 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/generation/MinecraftChunkGeneratorWrapper.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/generation/MinecraftChunkGeneratorWrapper.java @@ -17,7 +17,7 @@ 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.Blocks; import net.minecraft.registry.entry.RegistryEntry; @@ -48,7 +48,6 @@ import java.util.List; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Executor; import com.dfsek.terra.api.config.ConfigPack; import com.dfsek.terra.api.world.biome.generation.BiomeProvider; @@ -85,7 +84,7 @@ public MinecraftChunkGeneratorWrapper(TerraBiomeSource biomeSource, ConfigPack c } @Override - protected Codec getCodec() { + protected MapCodec getCodec() { return Codecs.MINECRAFT_CHUNK_GENERATOR_WRAPPER; } @@ -110,10 +109,9 @@ public int getWorldHeight() { return settings.value().generationShapeConfig().height(); } - @Override - public CompletableFuture populateNoise(Executor executor, Blender blender, NoiseConfig noiseConfig, - StructureAccessor structureAccessor, Chunk chunk) { + public CompletableFuture populateNoise(Blender blender, NoiseConfig noiseConfig, StructureAccessor structureAccessor, + Chunk chunk) { return CompletableFuture.supplyAsync(() -> { ProtoWorld world = (ProtoWorld) ((StructureAccessorAccessor) structureAccessor).getWorld(); BiomeProvider biomeProvider = pack.getBiomeProvider(); diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/generation/TerraBiomeSource.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/generation/TerraBiomeSource.java index 7aa5d8aea2..81651ece8c 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/generation/TerraBiomeSource.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/generation/TerraBiomeSource.java @@ -17,7 +17,7 @@ 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.world.biome.Biome; import net.minecraft.world.biome.source.BiomeSource; @@ -47,7 +47,7 @@ public TerraBiomeSource(ConfigPack pack) { } @Override - protected Codec getCodec() { + protected MapCodec getCodec() { return Codecs.TERRA_BIOME_SOURCE; } diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/handle/MinecraftItemHandle.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/handle/MinecraftItemHandle.java index 541e764aba..c9ef02f378 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/handle/MinecraftItemHandle.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/handle/MinecraftItemHandle.java @@ -21,14 +21,15 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.command.CommandRegistryAccess; import net.minecraft.command.argument.ItemStackArgumentType; -import net.minecraft.registry.Registries; import net.minecraft.registry.Registry; import net.minecraft.registry.RegistryKey; -import net.minecraft.registry.RegistryWrapper; +import net.minecraft.registry.RegistryWrapper.Impl; import net.minecraft.util.Identifier; +import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; +import java.util.stream.Stream; import com.dfsek.terra.api.handle.ItemHandle; import com.dfsek.terra.api.inventory.Item; @@ -43,8 +44,13 @@ public Item createItem(String data) { try { return (Item) new ItemStackArgumentType(new CommandRegistryAccess() { @Override - public RegistryWrapper createWrapper(RegistryKey> registryRef) { - return CommonPlatform.get().getServer().getRegistryManager().getWrapperOrThrow(registryRef); + public Stream>> streamAllRegistryKeys() { + return CommonPlatform.get().getServer().getRegistryManager().streamAllRegistryKeys(); + } + + @Override + public Optional> getOptionalWrapper(RegistryKey> registryRef) { + return Optional.of(CommonPlatform.get().getServer().getRegistryManager().getWrapperOrThrow(registryRef)); } }).parse(new StringReader(data)).getItem(); } catch(CommandSyntaxException e) { @@ -54,11 +60,12 @@ public RegistryWrapper createWrapper(RegistryKey> r @Override public Enchantment getEnchantment(String id) { - return (Enchantment) (Registries.ENCHANTMENT.get(Identifier.tryParse(id))); + return (Enchantment) (Object) (CommonPlatform.get().enchantmentRegistry().get(Identifier.tryParse(id))); } @Override public Set 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()); } } diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/handle/MinecraftWorldHandle.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/handle/MinecraftWorldHandle.java index 3b5e1fe49b..c36744d183 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/handle/MinecraftWorldHandle.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/handle/MinecraftWorldHandle.java @@ -64,8 +64,9 @@ public class MinecraftWorldHandle implements WorldHandle { @Override public @NotNull EntityType getEntity(@NotNull String id) { - if (!id.contains(":")) { //TODO: remove in 7.0 - String newid = "minecraft:" + id.toLowerCase();; + if(!id.contains(":")) { //TODO: remove in 7.0 + String newid = "minecraft:" + id.toLowerCase(); + ; logger.warn( "Translating " + id + " to " + newid + ". In 1.20.3 entity parsing was reworked" + ". You are advised to perform this rename in your config packs as this translation will be removed in the next major " + diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/MobSpawnerBlockEntityMixin.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/MobSpawnerBlockEntityMixin.java index ccc8b738a5..15e8fab349 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/MobSpawnerBlockEntityMixin.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/entity/MobSpawnerBlockEntityMixin.java @@ -49,8 +49,9 @@ private MobSpawnerBlockEntityMixin(BlockEntityType type, BlockPos pos, BlockS @Shadow public abstract MobSpawnerLogic getLogic(); + //method_46408 @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() { return (EntityType) Registries.ENTITY_TYPE.get( @@ -59,12 +60,12 @@ private MobSpawnerBlockEntityMixin(BlockEntityType type, BlockPos pos, BlockS public void terra$setSpawnedType(@NotNull EntityType creatureType) { Random rand; - if (hasWorld()) { + if(hasWorld()) { rand = world.getRandom(); } else { rand = Random.create(); } - method_46408((net.minecraft.entity.EntityType) creatureType, rand); + setEntityType((net.minecraft.entity.EntityType) creatureType, rand); } public int terra$getDelay() { diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/state/BlockStateMixin.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/state/BlockStateMixin.java index 7053dd4f51..4243bf9428 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/state/BlockStateMixin.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/block/state/BlockStateMixin.java @@ -1,8 +1,8 @@ package com.dfsek.terra.mod.mixin.implementations.terra.block.state; -import com.google.common.collect.ImmutableMap; import com.mojang.serialization.MapCodec; +import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap; import net.minecraft.block.AbstractBlock.AbstractBlockState; import net.minecraft.block.Block; import net.minecraft.registry.Registries; @@ -24,7 +24,7 @@ @Mixin(AbstractBlockState.class) @Implements(@Interface(iface = BlockState.class, prefix = "terra$")) public abstract class BlockStateMixin extends State { - private BlockStateMixin(Block owner, ImmutableMap, Comparable> entries, + private BlockStateMixin(Block owner, Reference2ObjectArrayMap, Comparable> entries, MapCodec codec) { super(owner, entries, codec); } diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/EntityMixin.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/EntityMixin.java index 3225cd4a6a..0b2f470176 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/EntityMixin.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/entity/EntityMixin.java @@ -39,14 +39,14 @@ public abstract class EntityMixin { private BlockPos blockPos; @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() { return MinecraftAdapter.adapt(blockPos); } public void terra$position(Vector3 location) { - teleport(location.getX(), location.getY(), location.getZ()); + updatePosition(location.getX(), location.getY(), location.getZ()); } public ServerWorld terra$world() { diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/item/ItemMixin.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/item/ItemMixin.java index 78593ecb1a..e8832c2149 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/item/ItemMixin.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/item/ItemMixin.java @@ -30,7 +30,7 @@ @Implements(@Interface(iface = com.dfsek.terra.api.inventory.Item.class, prefix = "terra$")) public abstract class ItemMixin { @Shadow - public abstract int getMaxDamage(); + public abstract net.minecraft.item.ItemStack getDefaultStack(); @SuppressWarnings("ConstantConditions") public ItemStack terra$newItemStack(int amount) { @@ -38,6 +38,7 @@ public abstract class ItemMixin { } public double terra$getMaxDurability() { - return getMaxDamage(); + //TODO verify this is correct + return getDefaultStack().getMaxDamage(); } } diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/item/ItemStackMixin.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/item/ItemStackMixin.java index 089a6db1dc..76121f64b8 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/item/ItemStackMixin.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/item/ItemStackMixin.java @@ -17,9 +17,11 @@ 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.nbt.NbtCompound; -import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Intrinsic; @@ -33,6 +35,10 @@ @Mixin(ItemStack.class) @Implements(@Interface(iface = com.dfsek.terra.api.inventory.ItemStack.class, prefix = "terra$")) public abstract class ItemStackMixin { + @Shadow + @Final + private ComponentMapImpl components; + @Shadow public abstract int getCount(); @@ -46,7 +52,7 @@ public abstract class ItemStackMixin { public abstract boolean isDamageable(); @Shadow - public abstract void setNbt(@Nullable NbtCompound tag); + public abstract ComponentMap getComponents(); public int terra$getAmount() { return getCount(); @@ -66,7 +72,13 @@ public abstract class ItemStackMixin { @SuppressWarnings("ConstantConditions") 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 diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/meta/EnchantmentMixin.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/meta/EnchantmentMixin.java index 24b096c856..8f58fb9d88 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/meta/EnchantmentMixin.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/meta/EnchantmentMixin.java @@ -18,7 +18,9 @@ package com.dfsek.terra.mod.mixin.implementations.terra.inventory.meta; 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.Interface; import org.spongepowered.asm.mixin.Mixin; @@ -27,16 +29,20 @@ import java.util.Objects; import com.dfsek.terra.api.inventory.ItemStack; +import com.dfsek.terra.mod.CommonPlatform; + +import static net.minecraft.enchantment.Enchantment.canBeCombined; @Mixin(Enchantment.class) @Implements(@Interface(iface = com.dfsek.terra.api.inventory.item.Enchantment.class, prefix = "terra$")) public abstract class EnchantmentMixin { @Shadow - public abstract boolean isAcceptableItem(net.minecraft.item.ItemStack stack); + @Final + private RegistryEntryList exclusiveSet; @Shadow - public abstract boolean canCombine(Enchantment other); + public abstract boolean isAcceptableItem(net.minecraft.item.ItemStack stack); @SuppressWarnings("ConstantConditions") 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) { - return !canCombine((Enchantment) other); + return canBeCombined(RegistryEntry.of((Enchantment) (Object) this), RegistryEntry.of((Enchantment) (Object) other)); } 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(); } } diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/meta/ItemStackMetaMixin.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/meta/ItemStackMetaMixin.java index a6307b02ca..91a487d0b1 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/meta/ItemStackMetaMixin.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/inventory/meta/ItemStackMetaMixin.java @@ -17,10 +17,9 @@ package com.dfsek.terra.mod.mixin.implementations.terra.inventory.meta; +import net.minecraft.component.type.ItemEnchantmentsComponent; import net.minecraft.item.ItemStack; -import net.minecraft.nbt.NbtCompound; -import net.minecraft.nbt.NbtList; -import net.minecraft.registry.Registries; +import net.minecraft.registry.entry.RegistryEntry; import org.spongepowered.asm.mixin.Implements; import org.spongepowered.asm.mixin.Interface; import org.spongepowered.asm.mixin.Intrinsic; @@ -42,13 +41,14 @@ public abstract class ItemStackMetaMixin { public abstract boolean hasEnchantments(); @Shadow - public abstract NbtList getEnchantments(); + public abstract ItemEnchantmentsComponent getEnchantments(); @Shadow - public abstract void addEnchantment(net.minecraft.enchantment.Enchantment enchantment, int level); + public abstract void addEnchantment(RegistryEntry 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) @@ -56,9 +56,10 @@ public abstract class ItemStackMetaMixin { if(!hasEnchantments()) return Collections.emptyMap(); Map map = new HashMap<>(); - getEnchantments().forEach(enchantment -> { - NbtCompound eTag = (NbtCompound) enchantment; - map.put((Enchantment) Registries.ENCHANTMENT.get(eTag.getInt("id")), eTag.getInt("lvl")); + ItemEnchantmentsComponent enchantments = getEnchantments(); + enchantments.getEnchantments().forEach(enchantment -> { + net.minecraft.enchantment.Enchantment enchantmentValue = enchantment.value(); + map.put((Enchantment) (Object) enchantmentValue, enchantments.getLevel(RegistryEntry.of(enchantmentValue))); }); return map; } diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/world/ChunkRegionMixin.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/world/ChunkRegionMixin.java index 82080579ba..70a62ae797 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/world/ChunkRegionMixin.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/implementations/terra/world/ChunkRegionMixin.java @@ -19,11 +19,12 @@ import net.minecraft.block.FluidBlock; import net.minecraft.fluid.Fluid; +import net.minecraft.util.collection.BoundedRegionArray; import net.minecraft.util.math.BlockPos; import net.minecraft.world.ChunkRegion; import net.minecraft.world.WorldAccess; 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.OrderedTick; import org.spongepowered.asm.mixin.Final; @@ -36,8 +37,6 @@ import org.spongepowered.asm.mixin.injection.Inject; 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.state.BlockState; import com.dfsek.terra.api.config.ConfigPack; @@ -48,6 +47,7 @@ import com.dfsek.terra.api.world.chunk.generation.ChunkGenerator; import com.dfsek.terra.api.world.chunk.generation.ProtoWorld; import com.dfsek.terra.mod.generation.MinecraftChunkGeneratorWrapper; +import com.dfsek.terra.mod.mixin.invoke.FluidBlockInvoker; import com.dfsek.terra.mod.util.MinecraftUtil; @@ -74,10 +74,10 @@ public abstract class ChunkRegionMixin { @Inject(at = @At("RETURN"), - method = "(Lnet/minecraft/server/world/ServerWorld;Ljava/util/List;Lnet/minecraft/world/chunk/ChunkStatus;I)V") - public void injectConstructor(net.minecraft.server.world.ServerWorld world, List list, - ChunkStatus chunkStatus, int i, - CallbackInfo ci) { + method = "(Lnet/minecraft/server/world/ServerWorld;Lnet/minecraft/util/collection/BoundedRegionArray;" + + "Lnet/minecraft/world/chunk/ChunkGenerationStep;Lnet/minecraft/world/chunk/Chunk;)V") + public void injectConstructor(net.minecraft.server.world.ServerWorld world, BoundedRegionArray chunks, + ChunkGenerationStep generationStep, Chunk centerPos, CallbackInfo ci) { this.terra$config = ((ServerWorld) world).getPack(); } @@ -88,7 +88,7 @@ public void injectConstructor(net.minecraft.server.world.ServerWorld world, List ((ChunkRegion) (Object) this).setBlockState(pos, (net.minecraft.block.BlockState) data, physics ? 3 : 1042); if(physics && ((net.minecraft.block.BlockState) data).getBlock() instanceof FluidBlock) { 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)); } } diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/invoke/FluidBlockInvoker.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/invoke/FluidBlockInvoker.java new file mode 100644 index 0000000000..620d03ec16 --- /dev/null +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/invoke/FluidBlockInvoker.java @@ -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); +} diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/lifecycle/DataPackContentsMixin.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/lifecycle/DataPackContentsMixin.java index 48ea985192..680c1833c8 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/lifecycle/DataPackContentsMixin.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/mixin/lifecycle/DataPackContentsMixin.java @@ -3,9 +3,12 @@ import net.minecraft.registry.DynamicRegistryManager; import net.minecraft.registry.Registry; import net.minecraft.registry.RegistryKeys; +import net.minecraft.registry.ReloadableRegistries; import net.minecraft.server.DataPackContents; import net.minecraft.world.biome.Biome; +import org.spongepowered.asm.mixin.Final; 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.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @@ -16,11 +19,16 @@ @Mixin(DataPackContents.class) public class DataPackContentsMixin { + @Shadow + @Final + private ReloadableRegistries.Lookup reloadableRegistries; + /* * #refresh populates all tags in the registries */ - @Inject(method = "refresh(Lnet/minecraft/registry/DynamicRegistryManager;)V", at = @At("RETURN")) - private void injectReload(DynamicRegistryManager dynamicRegistryManager, CallbackInfo ci) { + @Inject(method = "refresh()V", at = @At("RETURN")) + private void injectReload(CallbackInfo ci) { + DynamicRegistryManager.Immutable dynamicRegistryManager = this.reloadableRegistries.getRegistryManager(); TagUtil.registerWorldPresetTags(dynamicRegistryManager.get(RegistryKeys.WORLD_PRESET)); Registry biomeRegistry = dynamicRegistryManager.get(RegistryKeys.BIOME); diff --git a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/PresetUtil.java b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/PresetUtil.java index 1c86273644..32c19a4056 100644 --- a/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/PresetUtil.java +++ b/platforms/mixin-common/src/main/java/com/dfsek/terra/mod/util/PresetUtil.java @@ -45,8 +45,9 @@ public static Pair createDefault(ConfigPack pack, ModPl .orElseThrow(); - Identifier generatorID = Identifier.of("terra", pack.getID().toLowerCase(Locale.ROOT) + "/" + pack.getNamespace().toLowerCase( - Locale.ROOT)); + Identifier generatorID = Identifier.tryParse( + "terra:" + pack.getID().toLowerCase(Locale.ROOT) + "/" + pack.getNamespace().toLowerCase( + Locale.ROOT)); PRESETS.add(generatorID); diff --git a/platforms/mixin-common/src/main/resources/terra.accesswidener b/platforms/mixin-common/src/main/resources/terra.accesswidener index d638bbf457..46f1b986e5 100644 --- a/platforms/mixin-common/src/main/resources/terra.accesswidener +++ b/platforms/mixin-common/src/main/resources/terra.accesswidener @@ -1,3 +1,4 @@ accessWidener v1 named accessible class net/minecraft/world/biome/Biome$Weather accessible class net/minecraft/world/gen/WorldPresets$Registrar +accessible class net/minecraft/registry/RegistryLoader$Loader \ No newline at end of file diff --git a/platforms/mixin-common/src/main/resources/terra.common.mixins.json b/platforms/mixin-common/src/main/resources/terra.common.mixins.json index d4402241c5..e25cb7da45 100644 --- a/platforms/mixin-common/src/main/resources/terra.common.mixins.json +++ b/platforms/mixin-common/src/main/resources/terra.common.mixins.json @@ -2,7 +2,7 @@ "required": true, "minVersion": "0.8", "package": "com.dfsek.terra.mod.mixin", - "compatibilityLevel": "JAVA_17", + "compatibilityLevel": "JAVA_21", "mixins": [ "access.BiomeAccessor", "access.MobSpawnerLogicAccessor", @@ -36,6 +36,7 @@ "implementations.terra.inventory.meta.ItemStackMetaMixin", "implementations.terra.world.ChunkRegionMixin", "implementations.terra.world.ServerWorldMixin", + "invoke.FluidBlockInvoker", "lifecycle.DataPackContentsMixin" ], "client": [ diff --git a/platforms/mixin-lifecycle/build.gradle.kts b/platforms/mixin-lifecycle/build.gradle.kts index af8a062569..416764871b 100644 --- a/platforms/mixin-lifecycle/build.gradle.kts +++ b/platforms/mixin-lifecycle/build.gradle.kts @@ -15,7 +15,7 @@ dependencies { minecraft("com.mojang:minecraft:${Versions.Mod.minecraft}") mappings("net.fabricmc:yarn:${Versions.Mod.yarn}:v2") - modImplementation("cloud.commandframework", "cloud-fabric", Versions.Libraries.cloud) { + modImplementation("org.incendo", "cloud-fabric", Versions.Libraries.cloudFabric) { exclude("net.fabricmc") exclude("net.fabricmc.fabric-api") } @@ -30,10 +30,6 @@ loom { } tasks { - compileJava { - options.release.set(17) - } - remapJar { inputFile.set(shadowJar.get().archiveFile) } diff --git a/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/LifecycleEntryPoint.java b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/LifecycleEntryPoint.java index f20038e5ef..48dc882498 100644 --- a/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/LifecycleEntryPoint.java +++ b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/LifecycleEntryPoint.java @@ -1,14 +1,15 @@ package com.dfsek.terra.lifecycle; -import cloud.commandframework.execution.CommandExecutionCoordinator; -import cloud.commandframework.fabric.FabricServerCommandManager; +import com.dfsek.terra.api.command.CommandSender; +import com.dfsek.terra.api.event.events.platform.CommandRegistrationEvent; + import net.minecraft.server.command.ServerCommandSource; +import org.incendo.cloud.SenderMapper; +import org.incendo.cloud.execution.ExecutionCoordinator; +import org.incendo.cloud.fabric.FabricServerCommandManager; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.dfsek.terra.api.command.CommandSender; -import com.dfsek.terra.api.event.events.platform.CommandRegistrationEvent; - public final class LifecycleEntryPoint { private static final Logger logger = LoggerFactory.getLogger(LifecycleEntryPoint.class); @@ -17,9 +18,10 @@ public static void initialize(String modName, LifecyclePlatform platform) { logger.info("Initializing Terra {} mod...", modName); FabricServerCommandManager manager = new FabricServerCommandManager<>( - CommandExecutionCoordinator.simpleCoordinator(), - serverCommandSource -> (CommandSender) serverCommandSource, - commandSender -> (ServerCommandSource) commandSender + ExecutionCoordinator.simpleCoordinator(), + SenderMapper.create( + serverCommandSource -> (CommandSender) serverCommandSource, + commandSender -> (ServerCommandSource) commandSender) ); diff --git a/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/LifecyclePlatform.java b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/LifecyclePlatform.java index be845eb191..3918423117 100644 --- a/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/LifecyclePlatform.java +++ b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/LifecyclePlatform.java @@ -4,6 +4,7 @@ import ca.solostudios.strata.parser.tokenizer.ParseException; import ca.solostudios.strata.version.Version; import net.minecraft.MinecraftVersion; +import net.minecraft.enchantment.Enchantment; import net.minecraft.registry.Registry; import net.minecraft.registry.RegistryKeys; import net.minecraft.server.MinecraftServer; @@ -34,6 +35,7 @@ public abstract class LifecyclePlatform extends ModPlatform { private static final AtomicReference> DIMENSIONS = new AtomicReference<>(); private static final AtomicReference> SETTINGS = new AtomicReference<>(); private static final AtomicReference> NOISE = new AtomicReference<>(); + private static final AtomicReference> ENCHANTMENT = new AtomicReference<>(); private static MinecraftServer server; public LifecyclePlatform() { @@ -44,11 +46,13 @@ public LifecyclePlatform() { public static void setRegistries(Registry biomeRegistry, Registry dimensionTypeRegistry, Registry chunkGeneratorSettingsRegistry, - Registry multiNoiseBiomeSourceParameterListRegistry) { + Registry multiNoiseBiomeSourceParameterListRegistry, + Registry enchantmentRegistry) { BIOMES.set(biomeRegistry); DIMENSIONS.set(dimensionTypeRegistry); SETTINGS.set(chunkGeneratorSettingsRegistry); NOISE.set(multiNoiseBiomeSourceParameterListRegistry); + ENCHANTMENT.set(enchantmentRegistry); } @Override @@ -69,7 +73,7 @@ public boolean reload() { if(server != null) { BiomeUtil.registerBiomes(server.getRegistryManager().get(RegistryKeys.BIOME)); - server.reloadResources(server.getDataPackManager().getNames()).exceptionally(throwable -> { + server.reloadResources(server.getDataPackManager().getEnabledIds()).exceptionally(throwable -> { LOGGER.warn("Failed to execute reload", throwable); return null; }).join(); @@ -141,5 +145,10 @@ public Registry multiNoiseBiomeSourceParamet return NOISE.get(); } + @Override + public Registry enchantmentRegistry() { + return ENCHANTMENT.get(); + } + protected abstract Collection getPlatformMods(); } diff --git a/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/lifecycle/MinecraftServerMixin.java b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/lifecycle/MinecraftServerMixin.java index 25ac340d01..0f04c0963c 100644 --- a/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/lifecycle/MinecraftServerMixin.java +++ b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/lifecycle/MinecraftServerMixin.java @@ -16,6 +16,8 @@ import com.dfsek.terra.lifecycle.LifecyclePlatform; +import static com.dfsek.terra.lifecycle.util.LifecycleUtil.initialized; + @Mixin(MinecraftServer.class) public class MinecraftServerMixin { @@ -29,4 +31,9 @@ private void injectConstructor(Thread serverThread, LevelStorage.Session session WorldGenerationProgressListenerFactory worldGenerationProgressListenerFactory, CallbackInfo ci) { LifecyclePlatform.setServer((MinecraftServer) (Object) this); } + + @Inject(method = "shutdown()V", at = @At("RETURN")) + private void injectShutdown(CallbackInfo ci) { + initialized = false; + } } diff --git a/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/lifecycle/RegistryLoaderMixin.java b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/lifecycle/RegistryLoaderMixin.java index 052598ac25..739c084f37 100644 --- a/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/lifecycle/RegistryLoaderMixin.java +++ b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/lifecycle/RegistryLoaderMixin.java @@ -1,11 +1,13 @@ package com.dfsek.terra.lifecycle.mixin.lifecycle; -import com.mojang.datafixers.util.Pair; +import net.minecraft.enchantment.Enchantment; import net.minecraft.registry.MutableRegistry; import net.minecraft.registry.Registry; import net.minecraft.registry.RegistryKey; import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.RegistryLoader; +import net.minecraft.registry.RegistryLoader.Loader; +import net.minecraft.world.biome.Biome; import net.minecraft.world.biome.source.MultiNoiseBiomeSourceParameterList; import net.minecraft.world.dimension.DimensionType; import net.minecraft.world.gen.WorldPreset; @@ -14,6 +16,7 @@ import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; @@ -25,48 +28,50 @@ import com.dfsek.terra.lifecycle.util.LifecycleUtil; import com.dfsek.terra.lifecycle.util.RegistryHack; +import static com.dfsek.terra.lifecycle.util.LifecycleUtil.initialized; + @Mixin(RegistryLoader.class) public class RegistryLoaderMixin { + @Shadow @Final private static Logger LOGGER; @Redirect( - method = "load(Lnet/minecraft/resource/ResourceManager;Lnet/minecraft/registry/DynamicRegistryManager;Ljava/util/List;)" + - "Lnet/minecraft/registry/DynamicRegistryManager$Immutable;", + method = "load(Lnet/minecraft/registry/RegistryLoader$RegistryLoadable;Lnet/minecraft/registry/DynamicRegistryManager;" + + "Ljava/util/List;)Lnet/minecraft/registry/DynamicRegistryManager$Immutable;", at = @At( value = "INVOKE", target = "Ljava/util/List;forEach(Ljava/util/function/Consumer;)V", ordinal = 1 // we want right after the first forEach ) ) - private static void grabManager(List, Object>> instance, Consumer, Object>> consumer) { - instance.forEach(mutableRegistryObjectPair -> LOGGER.debug("{}: {} entries", - mutableRegistryObjectPair.getFirst().toString(), - mutableRegistryObjectPair.getFirst().size()) - ); - extractRegistry(instance, RegistryKeys.BIOME).ifPresent( - biomes -> { // this redirect triggers twice, second time only with dimension registry. don't try extraction second time - MutableRegistry dimensionTypes = extractRegistry(instance, RegistryKeys.DIMENSION_TYPE).orElseThrow(); - MutableRegistry worldPresets = extractRegistry(instance, RegistryKeys.WORLD_PRESET).orElseThrow(); - MutableRegistry chunkGeneratorSettings = extractRegistry(instance, - RegistryKeys.CHUNK_GENERATOR_SETTINGS).orElseThrow(); - MutableRegistry multiNoiseBiomeSourceParameterLists = extractRegistry(instance, - RegistryKeys.MULTI_NOISE_BIOME_SOURCE_PARAMETER_LIST).orElseThrow(); + private static void grabManager(List> instance, Consumer> consumer) { + if(!initialized) { + MutableRegistry biomes = extractRegistry(instance, RegistryKeys.BIOME).orElseThrow(); + MutableRegistry dimensionTypes = extractRegistry(instance, RegistryKeys.DIMENSION_TYPE).orElseThrow(); + MutableRegistry worldPresets = extractRegistry(instance, RegistryKeys.WORLD_PRESET).orElseThrow(); + MutableRegistry chunkGeneratorSettings = extractRegistry(instance, + RegistryKeys.CHUNK_GENERATOR_SETTINGS).orElseThrow(); + MutableRegistry multiNoiseBiomeSourceParameterLists = extractRegistry(instance, + RegistryKeys.MULTI_NOISE_BIOME_SOURCE_PARAMETER_LIST).orElseThrow(); + MutableRegistry enchantments = extractRegistry(instance, RegistryKeys.ENCHANTMENT).orElseThrow(); - LifecyclePlatform.setRegistries(biomes, dimensionTypes, chunkGeneratorSettings, multiNoiseBiomeSourceParameterLists); - LifecycleUtil.initialize(biomes, worldPresets); - }); + LifecyclePlatform.setRegistries(biomes, dimensionTypes, chunkGeneratorSettings, multiNoiseBiomeSourceParameterLists, + enchantments); + LifecycleUtil.initialize(biomes, worldPresets); + initialized = true; + } instance.forEach(consumer); } + @Unique @SuppressWarnings("unchecked") - private static Optional> extractRegistry(List, Object>> instance, + private static Optional> extractRegistry(List> instance, RegistryKey> key) { List> matches = instance - .stream() - .map(Pair::getFirst) + .stream().map(RegistryLoader.Loader::registry) .filter(r -> r.getKey().equals(key)) .toList(); if(matches.size() > 1) { @@ -74,7 +79,7 @@ private static Optional> extractRegistry(List registry = (MutableRegistry) matches.get(0); + MutableRegistry registry = (MutableRegistry) matches.getFirst(); ((RegistryHack) registry).terra_bind(); return Optional.of(registry); } diff --git a/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/lifecycle/SaveLoadingMixin.java b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/lifecycle/SaveLoadingMixin.java index 6f373130fe..89490ef415 100644 --- a/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/lifecycle/SaveLoadingMixin.java +++ b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/mixin/lifecycle/SaveLoadingMixin.java @@ -13,18 +13,18 @@ @Mixin(SaveLoading.class) public class SaveLoadingMixin { @ModifyArg( - method = "method_42097(Lnet/minecraft/registry/DynamicRegistryManager$Immutable;" + - "Lnet/minecraft/server/SaveLoading$SaveApplierFactory;Lnet/minecraft/resource/LifecycledResourceManager;" + - "Lnet/minecraft/registry/CombinedDynamicRegistries;Lnet/minecraft/server/SaveLoading$LoadContext;" + - "Lnet/minecraft/server/DataPackContents;)Ljava/lang/Object;", + method = "load(Lnet/minecraft/server/SaveLoading$ServerConfig;Lnet/minecraft/server/SaveLoading$LoadContextSupplier;" + + "Lnet/minecraft/server/SaveLoading$SaveApplierFactory;Ljava/util/concurrent/Executor;Ljava/util/concurrent/Executor;)" + + "Ljava/util/concurrent/CompletableFuture;", at = @At( value = "INVOKE", - target = "Lnet/minecraft/server/DataPackContents;refresh(Lnet/minecraft/registry/DynamicRegistryManager;)V" - ), - index = 0 + target = "Lnet/minecraft/registry/RegistryLoader;loadFromResource(Lnet/minecraft/resource/ResourceManager;" + + "Lnet/minecraft/registry/DynamicRegistryManager;Ljava/util/List;)" + + "Lnet/minecraft/registry/DynamicRegistryManager$Immutable;"), + index = 1 ) - private static DynamicRegistryManager grabManager(DynamicRegistryManager in) { - MinecraftUtil.registerFlora(in.get(RegistryKeys.BIOME)); - return in; + private static DynamicRegistryManager grabManager(DynamicRegistryManager registryManager) { + MinecraftUtil.registerFlora(registryManager.get(RegistryKeys.BIOME)); + return registryManager; } } diff --git a/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/util/BiomeUtil.java b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/util/BiomeUtil.java index 5d5ab11c08..b32e129358 100644 --- a/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/util/BiomeUtil.java +++ b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/util/BiomeUtil.java @@ -58,7 +58,7 @@ private static void registerBiome(Biome biome, ConfigPack pack, net.minecraft.world.biome.Biome minecraftBiome = MinecraftUtil.createBiome(biome, Objects.requireNonNull(registry.get(vanilla)), vanillaBiomeProperties); - Identifier identifier = new Identifier("terra", MinecraftUtil.createBiomeID(pack, id)); + Identifier identifier = Identifier.of("terra", MinecraftUtil.createBiomeID(pack, id)); if(registry.containsId(identifier)) { ((ProtoPlatformBiome) biome.getPlatformBiome()).setDelegate(MinecraftUtil.getEntry(registry, identifier) diff --git a/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/util/LifecycleUtil.java b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/util/LifecycleUtil.java index a251bedbd1..9ba81f8642 100644 --- a/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/util/LifecycleUtil.java +++ b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/util/LifecycleUtil.java @@ -12,6 +12,8 @@ public final class LifecycleUtil { + public static boolean initialized = false; + private LifecycleUtil() { } diff --git a/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/util/RegistryUtil.java b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/util/RegistryUtil.java index 03f0639c7c..69bc2ce21a 100644 --- a/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/util/RegistryUtil.java +++ b/platforms/mixin-lifecycle/src/main/java/com/dfsek/terra/lifecycle/util/RegistryUtil.java @@ -13,7 +13,7 @@ private RegistryUtil() { } public static void register() { - Registry.register(Registries.CHUNK_GENERATOR, new Identifier("terra:terra"), Codecs.MINECRAFT_CHUNK_GENERATOR_WRAPPER); - Registry.register(Registries.BIOME_SOURCE, new Identifier("terra:terra"), Codecs.TERRA_BIOME_SOURCE); + Registry.register(Registries.CHUNK_GENERATOR, Identifier.of("terra:terra"), Codecs.MINECRAFT_CHUNK_GENERATOR_WRAPPER); + Registry.register(Registries.BIOME_SOURCE, Identifier.of("terra:terra"), Codecs.TERRA_BIOME_SOURCE); } } diff --git a/platforms/mixin-lifecycle/src/main/resources/terra.lifecycle.mixins.json b/platforms/mixin-lifecycle/src/main/resources/terra.lifecycle.mixins.json index 33695db0eb..2e4708bd49 100644 --- a/platforms/mixin-lifecycle/src/main/resources/terra.lifecycle.mixins.json +++ b/platforms/mixin-lifecycle/src/main/resources/terra.lifecycle.mixins.json @@ -2,7 +2,7 @@ "required": true, "minVersion": "0.8", "package": "com.dfsek.terra.lifecycle.mixin", - "compatibilityLevel": "JAVA_17", + "compatibilityLevel": "JAVA_21", "mixins": [ "NoiseConfigMixin", "RegistryEntryReferenceInvoker", diff --git a/platforms/quilt/src/main/resources/terra.quilt.mixins.json b/platforms/quilt/src/main/resources/terra.quilt.mixins.json index 91f51b3445..84ca8264ae 100644 --- a/platforms/quilt/src/main/resources/terra.quilt.mixins.json +++ b/platforms/quilt/src/main/resources/terra.quilt.mixins.json @@ -2,7 +2,7 @@ "required": true, "minVersion": "0.8", "package": "com.dfsek.terra.quilt.mixin", - "compatibilityLevel": "JAVA_17", + "compatibilityLevel": "JAVA_21", "mixins": [ ], "client": [